@@ -7,6 +7,115 @@ use std::{
77
88use crate :: { FieldValue , XPath } ;
99
10+ /// An iterator over field names in an [`XPath`]-like path.
11+ ///
12+ /// This iterator is used to traverse field names in structured data paths,
13+ /// such as `.parent.child.field` in jq notation. It provides methods to
14+ /// access the current field name and advance to the next one.
15+ ///
16+ /// The iterator can be created from an [`XPath`] using the [`From`] trait,
17+ /// or directly from a slice of field names.
18+ ///
19+ /// # Examples
20+ ///
21+ /// ```
22+ /// use gene::{FieldNameIterator, XPath};
23+ ///
24+ /// // From XPath
25+ /// let path = XPath::parse(".parent.child.field").unwrap();
26+ /// let mut iter = FieldNameIterator::from(&path);
27+ ///
28+ /// assert_eq!(iter.next_field_name(), Some("parent"));
29+ /// assert_eq!(iter.next_field_name(), Some("child"));
30+ /// assert_eq!(iter.next_field_name(), Some("field"));
31+ /// assert_eq!(iter.next_field_name(), None);
32+ ///
33+ /// // From field names directly
34+ /// let field_names = vec!["parent".to_string(), "child".to_string(), "field".to_string()];
35+ /// let mut iter = FieldNameIterator::from(field_names.as_slice());
36+ ///
37+ /// assert_eq!(iter.next_field_name(), Some("parent"));
38+ /// assert_eq!(iter.next_field_name(), Some("child"));
39+ /// assert_eq!(iter.next_field_name(), Some("field"));
40+ /// assert_eq!(iter.next_field_name(), None);
41+ /// ```
42+ pub struct FieldNameIterator < ' f > {
43+ i : Option < usize > ,
44+ field_names : & ' f [ String ] ,
45+ }
46+
47+ impl < ' f > From < & ' f [ String ] > for FieldNameIterator < ' f > {
48+ fn from ( value : & ' f [ String ] ) -> Self {
49+ Self {
50+ i : None ,
51+ field_names : value,
52+ }
53+ }
54+ }
55+
56+ impl < ' f > From < & ' f XPath > for FieldNameIterator < ' f > {
57+ fn from ( value : & ' f XPath ) -> Self {
58+ value. segments ( ) . into ( )
59+ }
60+ }
61+
62+ impl < ' f > FieldNameIterator < ' f > {
63+ /// Advances the iterator and returns the next field name.
64+ ///
65+ /// This method moves the iterator to the next position and returns the field name
66+ /// at that position. On the first call, it returns the first field name.
67+ /// When the iterator reaches the end, it returns `None`.
68+ ///
69+ /// # Examples
70+ ///
71+ /// ```
72+ /// use gene::FieldNameIterator;
73+ ///
74+ /// let field_names = vec!["field1".to_string(), "field2".to_string()];
75+ /// let mut iter = FieldNameIterator::from(field_names.as_slice());
76+ ///
77+ /// assert_eq!(iter.next_field_name(), Some("field1"));
78+ /// assert_eq!(iter.next_field_name(), Some("field2"));
79+ /// assert_eq!(iter.next_field_name(), None);
80+ /// ```
81+ #[ inline]
82+ pub fn next_field_name ( & mut self ) -> Option < & str > {
83+ match self . i . as_mut ( ) {
84+ Some ( i) => {
85+ * i = i. checked_add ( 1 ) ?;
86+ self . field_names . get ( * i) . map ( |s| s. as_ref ( ) )
87+ }
88+ None => {
89+ self . i = Some ( 0 ) ;
90+ self . field_names . first ( ) . map ( |s| s. as_ref ( ) )
91+ }
92+ }
93+ }
94+
95+ /// Checks if the iterator is at the last field name.
96+ ///
97+ /// Returns `true` if the current position is at the last field name in the path,
98+ /// indicating that this is a terminal field access. Returns `false` otherwise.
99+ ///
100+ /// # Examples
101+ ///
102+ /// ```
103+ /// use gene::FieldNameIterator;
104+ ///
105+ /// let field_names = vec!["field1".to_string(), "field2".to_string()];
106+ /// let mut iter = FieldNameIterator::from(field_names.as_slice());
107+ ///
108+ /// assert_eq!(iter.next_field_name(), Some("field1"));
109+ /// assert!(!iter.is_terminal()); // At start, not terminal
110+ /// assert_eq!(iter.next_field_name(), Some("field2"));
111+ /// assert!(iter.is_terminal()); // After advancing once, at last field
112+ /// ```
113+ #[ inline( always) ]
114+ pub fn is_terminal ( & self ) -> bool {
115+ self . i . unwrap_or_default ( ) == self . field_names . len ( ) - 1
116+ }
117+ }
118+
10119/// Trait representing a log event that can be scanned by the engine.
11120///
12121/// Events provide access to their unique identifier, source, and field values
@@ -16,7 +125,7 @@ use crate::{FieldValue, XPath};
16125/// # Examples
17126///
18127/// ```
19- /// use gene::{FieldValue, Event, FieldGetter};
128+ /// use gene::{FieldValue, Event, FieldGetter, FieldNameIterator };
20129/// use gene_derive::{Event, FieldGetter};
21130/// use std::borrow::Cow;
22131///
@@ -54,7 +163,7 @@ pub trait Event<'event>: FieldGetter<'event> {
54163/// # Examples
55164///
56165/// ```
57- /// use gene::{FieldGetter, FieldValue};
166+ /// use gene::{FieldGetter, FieldValue, FieldNameIterator };
58167/// use std::net::IpAddr;
59168///
60169/// struct NetworkEvent {
@@ -66,9 +175,9 @@ pub trait Event<'event>: FieldGetter<'event> {
66175/// impl<'f> FieldGetter<'f> for NetworkEvent {
67176/// fn get_from_iter(
68177/// &'f self,
69- /// mut i: core::slice::Iter<'_, std::string::String> ,
178+ /// mut i: FieldNameIterator ,
70179/// ) -> Option<FieldValue<'f>> {
71- /// match i.next().map(|s| s.as_str() ) {
180+ /// match i.next_field_name( ) {
72181/// Some("source_ip") => Some(self.source_ip.to_string().into()),
73182/// Some("destination_ip") => Some(self.destination_ip.to_string().into()),
74183/// Some("port") => Some(self.port.into()),
@@ -109,7 +218,7 @@ pub trait FieldGetter<'field> {
109218 /// override [`Self::get_from_iter`] instead of overriding this method.
110219 #[ inline]
111220 fn get_from_path ( & ' field self , path : & XPath ) -> Option < FieldValue < ' field > > {
112- self . get_from_iter ( path . iter_segments ( ) )
221+ self . get_from_iter ( FieldNameIterator :: from ( path ) )
113222 }
114223
115224 /// Gets a field value using an iterator of path segments.
@@ -126,19 +235,16 @@ pub trait FieldGetter<'field> {
126235 ///
127236 /// * `Some(FieldValue)` if the field exists and can be accessed
128237 /// * `None` if the field does not exist or cannot be accessed
129- fn get_from_iter (
130- & ' field self ,
131- i : core:: slice:: Iter < ' _ , std:: string:: String > ,
132- ) -> Option < FieldValue < ' field > > ;
238+ fn get_from_iter ( & ' field self , i : FieldNameIterator < ' _ > ) -> Option < FieldValue < ' field > > ;
133239}
134240
135241macro_rules! impl_with_getter {
136242 ( $( ( $type: ty, $getter: tt) ) ,* ) => {
137243 $(
138244 impl <' f> FieldGetter <' f> for $type {
139245 #[ inline]
140- fn get_from_iter( & ' f self , i: core :: slice :: Iter <' _, std :: string :: String >) -> Option <FieldValue <' f>> {
141- if i . len ( ) > 0 {
246+ fn get_from_iter( & ' f self , i: FieldNameIterator <' _>) -> Option <FieldValue <' f>> {
247+ if !i . is_terminal ( ) {
142248 return None ;
143249 }
144250 Some ( self . $getter( ) . into( ) )
@@ -153,8 +259,8 @@ macro_rules! impl_for_type {
153259 $(
154260 impl <' f> FieldGetter <' f> for $type {
155261 #[ inline]
156- fn get_from_iter( & ' f self , i: core :: slice :: Iter <' _, std :: string :: String >) -> Option <FieldValue <' f>> {
157- if i . len ( ) > 0 {
262+ fn get_from_iter( & ' f self , i: FieldNameIterator <' _>) -> Option <FieldValue <' f>> {
263+ if !i . is_terminal ( ) {
158264 return None ;
159265 }
160266 Some ( self . into( ) )
@@ -196,10 +302,7 @@ where
196302 T : FieldGetter < ' field > ,
197303{
198304 #[ inline]
199- fn get_from_iter (
200- & ' field self ,
201- i : core:: slice:: Iter < ' _ , std:: string:: String > ,
202- ) -> Option < FieldValue < ' field > > {
305+ fn get_from_iter ( & ' field self , i : FieldNameIterator < ' _ > ) -> Option < FieldValue < ' field > > {
203306 match self {
204307 Some ( v) => v. get_from_iter ( i) ,
205308 None => Some ( FieldValue :: None ) ,
@@ -212,11 +315,8 @@ where
212315 T : FieldGetter < ' f > ,
213316{
214317 #[ inline]
215- fn get_from_iter (
216- & ' f self ,
217- mut i : core:: slice:: Iter < ' _ , std:: string:: String > ,
218- ) -> Option < FieldValue < ' f > > {
219- let k = match i. next ( ) {
318+ fn get_from_iter ( & ' f self , mut i : FieldNameIterator < ' _ > ) -> Option < FieldValue < ' f > > {
319+ let k = match i. next_field_name ( ) {
220320 Some ( s) => s,
221321 None => {
222322 // No key to look up, return Some to indicate map existence
@@ -238,9 +338,9 @@ macro_rules! impl_field_getter_for_vec {
238338 #[ inline]
239339 fn get_from_iter(
240340 & ' f self ,
241- i: core :: slice :: Iter <' _, std :: string :: String >,
341+ i: FieldNameIterator <' _>,
242342 ) -> Option <FieldValue <' f>> {
243- if i . len ( ) > 0 {
343+ if !i . is_terminal ( ) {
244344 return None ;
245345 }
246346
0 commit comments