@@ -139,6 +139,11 @@ pub struct NodeList<'pr> {
139139}
140140
141141impl < ' pr > NodeList < ' pr > {
142+ unsafe fn at ( & self , index : usize ) -> Node < ' pr > {
143+ let node: * mut pm_node_t = * ( self . pointer . as_ref ( ) . nodes . add ( index) ) ;
144+ Node :: new ( self . parser , node)
145+ }
146+
142147 /// Returns an iterator over the nodes.
143148 #[ must_use]
144149 pub const fn iter ( & self ) -> NodeListIter < ' pr > {
@@ -161,6 +166,26 @@ impl<'pr> NodeList<'pr> {
161166 pub const fn is_empty ( & self ) -> bool {
162167 self . len ( ) == 0
163168 }
169+
170+ /// Returns the first element of the list, or `None` if it is empty.
171+ #[ must_use]
172+ pub fn first ( & self ) -> Option < Node < ' pr > > {
173+ if self . is_empty ( ) {
174+ None
175+ } else {
176+ Some ( unsafe { self . at ( 0 ) } )
177+ }
178+ }
179+
180+ /// Returns the last element of the list, or `None` if it is empty.
181+ #[ must_use]
182+ pub fn last ( & self ) -> Option < Node < ' pr > > {
183+ if self . is_empty ( ) {
184+ None
185+ } else {
186+ Some ( unsafe { self . at ( self . len ( ) - 1 ) } )
187+ }
188+ }
164189}
165190
166191impl < ' pr > IntoIterator for & NodeList < ' pr > {
@@ -245,6 +270,11 @@ pub struct ConstantList<'pr> {
245270}
246271
247272impl < ' pr > ConstantList < ' pr > {
273+ const unsafe fn at ( & self , index : usize ) -> ConstantId < ' pr > {
274+ let constant_id: pm_constant_id_t = * ( self . pointer . as_ref ( ) . ids . add ( index) ) ;
275+ ConstantId :: new ( self . parser , constant_id)
276+ }
277+
248278 /// Returns an iterator over the constants in the list.
249279 #[ must_use]
250280 pub const fn iter ( & self ) -> ConstantListIter < ' pr > {
@@ -267,6 +297,26 @@ impl<'pr> ConstantList<'pr> {
267297 pub const fn is_empty ( & self ) -> bool {
268298 self . len ( ) == 0
269299 }
300+
301+ /// Returns the first element of the list, or `None` if it is empty.
302+ #[ must_use]
303+ pub const fn first ( & self ) -> Option < ConstantId < ' pr > > {
304+ if self . is_empty ( ) {
305+ None
306+ } else {
307+ Some ( unsafe { self . at ( 0 ) } )
308+ }
309+ }
310+
311+ /// Returns the last element of the list, or `None` if it is empty.
312+ #[ must_use]
313+ pub const fn last ( & self ) -> Option < ConstantId < ' pr > > {
314+ if self . is_empty ( ) {
315+ None
316+ } else {
317+ Some ( unsafe { self . at ( self . len ( ) - 1 ) } )
318+ }
319+ }
270320}
271321
272322impl < ' pr > IntoIterator for & ConstantList < ' pr > {
@@ -815,31 +865,28 @@ mod tests {
815865
816866 #[ test]
817867 fn constant_id_test ( ) {
818- let source = "module Foo; x = 1; end" ;
868+ let source = "module Foo; x = 1; y = 2; end" ;
819869 let result = parse ( source. as_ref ( ) ) ;
820870
821871 let node = result. node ( ) ;
822872 assert_eq ! ( node. as_program_node( ) . unwrap( ) . statements( ) . body( ) . len( ) , 1 ) ;
823873 assert ! ( !node. as_program_node( ) . unwrap( ) . statements( ) . body( ) . is_empty( ) ) ;
824- let module = node. as_program_node ( ) . unwrap ( ) . statements ( ) . body ( ) . iter ( ) . next ( ) . unwrap ( ) ;
874+ let module = node. as_program_node ( ) . and_then ( |pn| pn . statements ( ) . body ( ) . first ( ) ) . unwrap ( ) ;
825875 let module = module. as_module_node ( ) . unwrap ( ) ;
826876
827- assert_eq ! ( module. locals( ) . len( ) , 1 ) ;
877+ assert_eq ! ( module. locals( ) . len( ) , 2 ) ;
828878 assert ! ( !module. locals( ) . is_empty( ) ) ;
829879
830- let locals = module. locals ( ) . iter ( ) . collect :: < Vec < _ > > ( ) ;
831-
832- assert_eq ! ( locals. len( ) , 1 ) ;
833-
834- assert_eq ! ( locals[ 0 ] . as_slice( ) , b"x" ) ;
880+ assert_eq ! ( module. locals( ) . first( ) . unwrap( ) . as_slice( ) , b"x" ) ;
881+ assert_eq ! ( module. locals( ) . last( ) . unwrap( ) . as_slice( ) , b"y" ) ;
835882
836883 let source = "module Foo; end" ;
837884 let result = parse ( source. as_ref ( ) ) ;
838885
839886 let node = result. node ( ) ;
840887 assert_eq ! ( node. as_program_node( ) . unwrap( ) . statements( ) . body( ) . len( ) , 1 ) ;
841888 assert ! ( !node. as_program_node( ) . unwrap( ) . statements( ) . body( ) . is_empty( ) ) ;
842- let module = node. as_program_node ( ) . unwrap ( ) . statements ( ) . body ( ) . iter ( ) . next ( ) . unwrap ( ) ;
889+ let module = node. as_program_node ( ) . and_then ( |pn| pn . statements ( ) . body ( ) . first ( ) ) . unwrap ( ) ;
843890 let module = module. as_module_node ( ) . unwrap ( ) ;
844891
845892 assert_eq ! ( module. locals( ) . len( ) , 0 ) ;
0 commit comments