@@ -19,7 +19,7 @@ use indexmap::{indexmap, IndexMap};
19
19
use lazy_static:: lazy_static;
20
20
use regex:: Regex ;
21
21
22
- use crate :: error:: ModelError ;
22
+ use crate :: error:: { ModelError , ValidationError , YamlPath } ;
23
23
use crate :: model:: expressions:: OwningNode ;
24
24
use crate :: parser as p;
25
25
use crate :: parser:: expressions:: { parse_process, parse_type_ref, AttrType } ;
@@ -35,6 +35,7 @@ pub use name::*;
35
35
/// contains helper structures, that contains only necessary subset of fields.
36
36
/// Advantages over just unnamed tuples is names of fields.
37
37
mod helpers {
38
+ use crate :: error:: YamlPath ;
38
39
use crate :: parser as p;
39
40
40
41
/// Wrapper for inheritable values
@@ -86,6 +87,8 @@ mod helpers {
86
87
pub eos_error : Option < bool > ,
87
88
88
89
pub pad_right : Option < u8 > ,
90
+
91
+ pub path : YamlPath ,
89
92
}
90
93
91
94
/// Transitional structure, that contains all data from parser structure,
@@ -97,6 +100,7 @@ mod helpers {
97
100
pub encoding : Inheritable < String > ,
98
101
pub endian : Option < p:: Variant < p:: ByteOrder > > ,
99
102
pub bit_endian : Option < p:: BitOrder > ,
103
+ pub path : YamlPath ,
100
104
}
101
105
}
102
106
@@ -203,23 +207,24 @@ pub enum Variant<T> {
203
207
cases : IndexMap < OwningNode , T > ,
204
208
} ,
205
209
}
206
- impl < T , U : TryInto < T > > TryFrom < p:: Variant < U > > for Variant < T >
210
+ impl < T , U : TryInto < T > > TryFrom < ( YamlPath , p:: Variant < U > ) > for Variant < T >
207
211
where U :: Error : Into < ModelError > ,
208
212
{
209
213
type Error = ModelError ;
210
214
211
- fn try_from ( data : p:: Variant < U > ) -> Result < Self , Self :: Error > {
215
+ fn try_from ( data : ( YamlPath , p:: Variant < U > ) ) -> Result < Self , Self :: Error > {
212
216
use p:: Variant :: * ;
213
217
214
- match data {
218
+ match data. 1 {
215
219
Fixed ( val) => Ok ( Variant :: Fixed ( val. try_into ( ) . map_err ( Into :: into) ?) ) ,
216
220
Choice { switch_on, cases } => {
217
221
let mut new_cases = IndexMap :: with_capacity ( cases. len ( ) ) ;
218
222
for ( k, v) in cases. into_iter ( ) {
219
- new_cases. insert ( k. try_into ( ) ?, v. try_into ( ) . map_err ( Into :: into) ?) ;
223
+ let path = data. 0 . extend ( vec ! [ "cases" ] ) ; //TODO: path to case
224
+ new_cases. insert ( ( path, k) . try_into ( ) ?, v. try_into ( ) . map_err ( Into :: into) ?) ;
220
225
}
221
226
Ok ( Variant :: Choice {
222
- switch_on : switch_on. try_into ( ) ?,
227
+ switch_on : ( data . 0 . extend ( vec ! [ " switch_on" ] ) , switch_on ) . try_into ( ) ?,
223
228
cases : new_cases,
224
229
} )
225
230
}
@@ -304,16 +309,16 @@ impl Repeat {
304
309
} ,
305
310
306
311
#[ cfg( feature = "compatible" ) ]
307
- ( None , Some ( _) , None ) => Err ( Validation ( "missed `repeat: expr`" . into ( ) ) ) ,
312
+ ( None , Some ( _) , None ) => Err ( Validation ( data . path , "missed `repeat: expr`" . into ( ) ) ) ,
308
313
#[ cfg( feature = "compatible" ) ]
309
- ( None , None , Some ( _) ) => Err ( Validation ( "missed `repeat: until`" . into ( ) ) ) ,
314
+ ( None , None , Some ( _) ) => Err ( Validation ( data . path , "missed `repeat: until`" . into ( ) ) ) ,
310
315
311
- ( Some ( Expr ) , None , _) => Err ( Validation ( "missed `repeat-expr`" . into ( ) ) ) ,
312
- ( Some ( Until ) , _, None ) => Err ( Validation ( "missed `repeat-until`" . into ( ) ) ) ,
316
+ ( Some ( Expr ) , None , _) => Err ( Validation ( data . path , "missed `repeat-expr`" . into ( ) ) ) ,
317
+ ( Some ( Until ) , _, None ) => Err ( Validation ( data . path , "missed `repeat-until`" . into ( ) ) ) ,
313
318
314
- ( _, Some ( _) , Some ( _) ) => Err ( Validation ( "either `repeat-expr` or `repeat-until` must be specified" . into ( ) ) ) ,
315
- ( Some ( _) , _, Some ( _) ) => Err ( Validation ( "`repeat-until` requires `repeat: until`" . into ( ) ) ) ,
316
- ( Some ( _) , Some ( _) , _) => Err ( Validation ( "`repeat-expr` requires `repeat: expr`" . into ( ) ) ) ,
319
+ ( _, Some ( _) , Some ( _) ) => Err ( Validation ( data . path , "either `repeat-expr` or `repeat-until` must be specified" . into ( ) ) ) ,
320
+ ( Some ( _) , _, Some ( _) ) => Err ( Validation ( data . path , "`repeat-until` requires `repeat: until`" . into ( ) ) ) ,
321
+ ( Some ( _) , Some ( _) , _) => Err ( Validation ( data . path , "`repeat-expr` requires `repeat: expr`" . into ( ) ) ) ,
317
322
}
318
323
}
319
324
}
@@ -462,7 +467,7 @@ impl Size {
462
467
mandatory : mandatory. unwrap_or ( true ) ,
463
468
} ) ,
464
469
// TODO: Emit warning instead here, but error also an option until warnings is not implemented
465
- //(None, ..) => return Err(Validation("`consume`, `include` or `eos-error` has no effect without `terminator`".into())),
470
+ //(None, ..) => return Err(Validation(data.path, "`consume`, `include` or `eos-error` has no effect without `terminator`".into())),
466
471
( None , ..) => None ,
467
472
} ;
468
473
@@ -501,11 +506,11 @@ impl Size {
501
506
( None , false , Some ( t) ) => Ok ( Self :: Until ( t) ) ,
502
507
// TODO: Warning or even error, if natural type size is less that size
503
508
( Some ( size) , false , until) => Ok ( Self :: Exact { count : Count :: validate ( size) ?, until } ) ,
504
- ( Some ( _) , true , _) => Err ( Validation ( "only one of `size` or `size-eos: true` must be specified" . into ( ) ) ) ,
509
+ ( Some ( _) , true , _) => Err ( Validation ( data . path , "only one of `size` or `size-eos: true` must be specified" . into ( ) ) ) ,
505
510
( None , false , None ) => match type_ref. sizeof ( ) {
506
511
// For unknown sized types use all remaining input
507
512
Unknown => Ok ( Self :: Eos ( None ) ) ,
508
- Unsized ( _ , _ ) => Err ( Validation ( "`size`, `size-eos: true` or `terminator` must be specified" . into ( ) ) ) ,
513
+ Unsized => Err ( Validation ( data . path , "`size`, `size-eos: true` or `terminator` must be specified" . into ( ) ) ) ,
509
514
Sized ( _) => Ok ( Self :: Natural ) ,
510
515
} ,
511
516
}
@@ -704,14 +709,15 @@ impl TypeRef {
704
709
use ModelError :: * ;
705
710
use TypeRef :: { Enum , F32 , F64 } ;
706
711
712
+ let path = props. path ;
707
713
let endian = props. endian ;
708
714
let endian = |t| match endian {
709
- Some ( e) => Ok ( ByteOrder :: try_from ( e ) ?) ,
710
- None => Err ( Validation ( format ! ( "unable to use type `{:?}` without default endianness" , t) . into ( ) ) ) ,
715
+ Some ( e) => Ok ( ByteOrder :: try_from ( ( path . extend ( vec ! [ "endian" ] ) , e ) ) ?) ,
716
+ None => Err ( Validation ( data . path , format ! ( "unable to use type `{:?}` without default endianness" , t) . into ( ) ) ) ,
711
717
} ;
712
718
// Extract encoding of string
713
719
let encoding = |e : helpers:: Inheritable < String > | match e {
714
- Undefined => Err ( Validation ( "string requires encoding" . into ( ) ) ) ,
720
+ Undefined => Err ( Validation ( path , "string requires encoding" . into ( ) ) ) ,
715
721
Default ( enc) => Ok ( enc) ,
716
722
Defined ( enc) => Ok ( enc) ,
717
723
} ;
@@ -780,8 +786,8 @@ impl TypeRef {
780
786
( None , None , Some ( content) , None ) => Ok ( TypeRef :: Fixed ( content. into ( ) ) ) ,
781
787
( None , None , None , None ) => Ok ( TypeRef :: Bytes ) ,
782
788
783
- ( _, Some ( _) , _, _) => Err ( Validation ( "`encoding` can be specified only for `type: str` or `type: strz`" . into ( ) ) ) ,
784
- ( _, _, Some ( _) , _) => Err ( Validation ( "`contents` don't require type, its always byte array" . into ( ) ) ) ,
789
+ ( _, Some ( _) , _, _) => Err ( Validation ( data . path , "`encoding` can be specified only for `type: str` or `type: strz`" . into ( ) ) ) ,
790
+ ( _, _, Some ( _) , _) => Err ( Validation ( data . path , "`contents` don't require type, its always byte array" . into ( ) ) ) ,
785
791
( _, _, _, Some ( _) ) => enum_err ( ) ,
786
792
}
787
793
}
@@ -936,6 +942,7 @@ impl Attribute {
936
942
eos_error : attr. eos_error ,
937
943
938
944
pad_right : attr. pad_right ,
945
+ path : data. path ,
939
946
} ;
940
947
Ok ( Self {
941
948
chunk : match attr. type_ {
@@ -1076,7 +1083,7 @@ impl TryFrom<p::Ksy> for Root {
1076
1083
Some ( Bool ( false ) ) => TypeName :: valid ( "r#false" ) ,
1077
1084
Some ( Name ( name) ) => TypeName :: validate ( name) ?,
1078
1085
} ;
1079
- let type_ = UserType :: validate ( data. root , data. meta . defaults . into ( ) ) ?;
1086
+ let type_ = UserType :: validate ( data. root , data. meta . defaults . into ( ) , YamlPath :: default ( ) ) ?;
1080
1087
1081
1088
Ok ( Self { name, type_ } )
1082
1089
}
0 commit comments