@@ -10,10 +10,16 @@ use crate::dscerror::DscError;
1010use crate :: functions:: FunctionDispatcher ;
1111use crate :: parser:: functions:: Function ;
1212
13+ #[ derive( Clone ) ]
14+ pub enum Accessor {
15+ Member ( String ) ,
16+ Index ( Value ) ,
17+ }
18+
1319#[ derive( Clone ) ]
1420pub struct Expression {
1521 function : Function ,
16- member_access : Option < Vec < String > > ,
22+ accessors : Vec < Accessor > ,
1723}
1824
1925impl Expression {
@@ -32,64 +38,115 @@ impl Expression {
3238 let Some ( function) = expression. child_by_field_name ( "function" ) else {
3339 return Err ( DscError :: Parser ( "Function node not found" . to_string ( ) ) ) ;
3440 } ;
41+ debug ! ( "Parsing function '{:?}'" , function) ;
3542 let function = Function :: new ( statement_bytes, & function) ?;
36- let member_access = if let Some ( members) = expression. child_by_field_name ( "members" ) {
37- if members. is_error ( ) {
38- return Err ( DscError :: Parser ( "Error parsing dot-notation" . to_string ( ) ) ) ;
43+ let mut accessors = Vec :: < Accessor > :: new ( ) ;
44+ if let Some ( accessor) = expression. child_by_field_name ( "accessor" ) {
45+ debug ! ( "Parsing accessor '{:?}'" , accessor) ;
46+ if accessor. is_error ( ) {
47+ return Err ( DscError :: Parser ( "Error parsing accessor" . to_string ( ) ) ) ;
3948 }
40- let mut result = vec ! [ ] ;
41- let mut cursor = members. walk ( ) ;
42- for member in members. named_children ( & mut cursor) {
43- if member. is_error ( ) {
44- return Err ( DscError :: Parser ( "Error parsing dot-notation member" . to_string ( ) ) ) ;
49+ let mut cursor = accessor. walk ( ) ;
50+ for accessor in accessor. named_children ( & mut cursor) {
51+ if accessor. is_error ( ) {
52+ return Err ( DscError :: Parser ( "Error parsing accessor" . to_string ( ) ) ) ;
4553 }
46- let value = member. utf8_text ( statement_bytes) ?;
47- result. push ( value. to_string ( ) ) ;
54+ let accessor_kind = accessor. kind ( ) ;
55+ let value = match accessor_kind {
56+ "memberAccess" => {
57+ debug ! ( "Parsing member accessor '{:?}'" , accessor) ;
58+ let Some ( member_name) = accessor. child_by_field_name ( "name" ) else {
59+ return Err ( DscError :: Parser ( "Member name not found" . to_string ( ) ) ) ;
60+ } ;
61+ let member = member_name. utf8_text ( statement_bytes) ?;
62+ Accessor :: Member ( member. to_string ( ) )
63+ } ,
64+ "index" => {
65+ debug ! ( "Parsing index accessor '{:?}'" , accessor) ;
66+ let Some ( index_value) = accessor. child_by_field_name ( "indexValue" ) else {
67+ return Err ( DscError :: Parser ( "Index value not found" . to_string ( ) ) ) ;
68+ } ;
69+ match index_value. kind ( ) {
70+ "number" => {
71+ let value = index_value. utf8_text ( statement_bytes) ?;
72+ let value = serde_json:: from_str ( value) ?;
73+ Accessor :: Index ( value)
74+ } ,
75+ "expression" => {
76+ return Err ( DscError :: Parser ( "Expression index not supported" . to_string ( ) ) ) ;
77+ } ,
78+ _ => {
79+ return Err ( DscError :: Parser ( format ! ( "Invalid accessor kind: '{accessor_kind}'" ) ) ) ;
80+ } ,
81+ }
82+ } ,
83+ _ => {
84+ return Err ( DscError :: Parser ( format ! ( "Invalid accessor kind: '{accessor_kind}'" ) ) ) ;
85+ } ,
86+ } ;
87+ accessors. push ( value) ;
4888 }
49- Some ( result)
5089 }
51- else {
52- None
53- } ;
90+
5491 Ok ( Expression {
5592 function,
56- member_access ,
93+ accessors ,
5794 } )
5895 }
5996
6097 /// Invoke the expression.
6198 ///
99+ /// # Arguments
100+ ///
101+ /// * `function_dispatcher` - The function dispatcher to use.
102+ /// * `context` - The context to use.
103+ ///
104+ /// # Returns
105+ ///
106+ /// The result of the expression.
107+ ///
62108 /// # Errors
63109 ///
64110 /// This function will return an error if the expression fails to execute.
65111 pub fn invoke ( & self , function_dispatcher : & FunctionDispatcher , context : & Context ) -> Result < Value , DscError > {
66112 let result = self . function . invoke ( function_dispatcher, context) ?;
67113 trace ! ( "Function result: '{:?}'" , result) ;
68- if let Some ( member_access) = & self . member_access {
69- debug ! ( "Evaluating member access '{:?}'" , member_access) ;
70- if !result. is_object ( ) {
71- return Err ( DscError :: Parser ( "Member access on non-object value" . to_string ( ) ) ) ;
72- }
73-
114+ if self . accessors . is_empty ( ) {
115+ Ok ( result)
116+ }
117+ else {
118+ debug ! ( "Evaluating accessors" ) ;
74119 let mut value = result;
75- for member in member_access {
76- if !value. is_object ( ) {
77- return Err ( DscError :: Parser ( format ! ( "Member access '{member}' on non-object value" ) ) ) ;
78- }
79-
80- if let Some ( object) = value. as_object ( ) {
81- if !object. contains_key ( member) {
82- return Err ( DscError :: Parser ( format ! ( "Member '{member}' not found" ) ) ) ;
83- }
84-
85- value = object[ member] . clone ( ) ;
120+ for accessor in & self . accessors {
121+ match accessor {
122+ Accessor :: Member ( member) => {
123+ if let Some ( object) = value. as_object ( ) {
124+ if !object. contains_key ( member) {
125+ return Err ( DscError :: Parser ( format ! ( "Member '{member}' not found" ) ) ) ;
126+ }
127+ value = object[ member] . clone ( ) ;
128+ } else {
129+ return Err ( DscError :: Parser ( "Member access on non-object value" . to_string ( ) ) ) ;
130+ }
131+ } ,
132+ Accessor :: Index ( index) => {
133+ if let Some ( array) = value. as_array ( ) {
134+ let Some ( index) = index. as_u64 ( ) else {
135+ return Err ( DscError :: Parser ( "Index is not a valid number" . to_string ( ) ) ) ;
136+ } ;
137+ let index = usize:: try_from ( index) ?;
138+ if index >= array. len ( ) {
139+ return Err ( DscError :: Parser ( "Index out of bounds" . to_string ( ) ) ) ;
140+ }
141+ value = array[ index] . clone ( ) ;
142+ } else {
143+ return Err ( DscError :: Parser ( "Index access on non-array value" . to_string ( ) ) ) ;
144+ }
145+ } ,
86146 }
87147 }
88148
89149 Ok ( value)
90150 }
91- else {
92- Ok ( result)
93- }
94151 }
95152}
0 commit comments