1+ use std:: {
2+ num:: { ParseFloatError , ParseIntError } ,
3+ str:: ParseBoolError ,
4+ } ;
5+
6+ // `from_op` is generated as if-else chain from op.parse()
7+ // Because of this alot of instances of FromStr::Err wil lbe constructed just as a "take other branch" marker
8+ // This type should be very cheap to construct new instances, at least while we use FromStr chains
9+ // Don't store any input in here, FromStr is not designed for this, and it requires allocation
10+ // Instead rely on egg::FromOpError for now, it will return allocated `op`, but only once in the end
11+ // TODO make parser dispatch stricter, and return both input and LanguageParseError from `from_op`
12+ #[ derive( thiserror:: Error , Debug ) ]
13+ pub enum LanguageParseError {
14+ #[ error( "Should start with '{0}'" ) ]
15+ ShouldStartWith ( & ' static str ) ,
16+ #[ error( "Can't be matched against {0}" ) ]
17+ ShouldMatch ( & ' static str ) ,
18+ #[ error( "Should contain a valid type" ) ]
19+ InvalidType ,
20+ #[ error( "Should contains a valid scalar type" ) ]
21+ InvalidScalarType ,
22+ #[ error( "Can't parse boolean scalar value with error: {0}" ) ]
23+ InvalidBoolValue ( #[ source] ParseBoolError ) ,
24+ #[ error( "Can't parse i64 scalar value with error: {0}" ) ]
25+ InvalidIntValue ( #[ source] ParseIntError ) ,
26+ #[ error( "Can't parse f64 scalar value with error: {0}" ) ]
27+ InvalidFloatValue ( #[ source] ParseFloatError ) ,
28+ #[ error( "Conversion from string is not supported" ) ]
29+ NotSupported ,
30+ }
31+
132#[ macro_export]
233macro_rules! plan_to_language {
334 ( $( #[ $meta: meta] ) * $vis: vis enum $name: ident $variants: tt) => {
@@ -13,13 +44,13 @@ macro_rules! variant_field_struct {
1344 pub struct [ <$variant $var_field: camel>] ( String ) ;
1445
1546 impl FromStr for [ <$variant $var_field: camel>] {
16- type Err = CubeError ;
47+ type Err = $crate :: compile :: rewrite :: language :: LanguageParseError ;
1748 fn from_str( s: & str ) -> Result <Self , Self :: Err > {
18- let prefix = format! ( "{}:" , std:: stringify!( [ <$variant $var_field: camel>] ) ) ;
19- if s . starts_with ( & prefix ) {
20- return Ok ( [ <$variant $var_field: camel>] ( s . replace ( & prefix , "" ) ) ) ;
49+ const PREFIX : & ' static str = concat! ( std:: stringify!( [ <$variant $var_field: camel>] ) , ":" ) ;
50+ if let Some ( suffix ) = s . strip_prefix ( PREFIX ) {
51+ return Ok ( [ <$variant $var_field: camel>] ( suffix . to_string ( ) ) ) ;
2152 }
22- Err ( CubeError :: internal ( format! ( "Can't convert {}. Should start with '{}'" , s , prefix ) ) )
53+ Err ( Self :: Err :: ShouldStartWith ( PREFIX ) )
2354 }
2455 }
2556
@@ -37,13 +68,13 @@ macro_rules! variant_field_struct {
3768 pub struct [ <$variant $var_field: camel>] ( usize ) ;
3869
3970 impl FromStr for [ <$variant $var_field: camel>] {
40- type Err = CubeError ;
71+ type Err = $crate :: compile :: rewrite :: language :: LanguageParseError ;
4172 fn from_str( s: & str ) -> Result <Self , Self :: Err > {
42- let prefix = format! ( "{}:" , std:: stringify!( [ <$variant $var_field: camel>] ) ) ;
43- if s . starts_with ( & prefix ) {
44- return Ok ( [ <$variant $var_field: camel>] ( s . replace ( & prefix , "" ) . parse( ) . unwrap( ) ) ) ;
73+ const PREFIX : & ' static str = concat! ( std:: stringify!( [ <$variant $var_field: camel>] ) , ":" ) ;
74+ if let Some ( suffix ) = s . strip_prefix ( PREFIX ) {
75+ return Ok ( [ <$variant $var_field: camel>] ( suffix . parse( ) . unwrap( ) ) ) ;
4576 }
46- Err ( CubeError :: internal ( format! ( "Can't convert {}. Should start with '{}'" , s , prefix ) ) )
77+ Err ( Self :: Err :: ShouldStartWith ( PREFIX ) )
4778 }
4879 }
4980
@@ -61,13 +92,13 @@ macro_rules! variant_field_struct {
6192 pub struct [ <$variant $var_field: camel>] ( bool ) ;
6293
6394 impl FromStr for [ <$variant $var_field: camel>] {
64- type Err = CubeError ;
95+ type Err = $crate :: compile :: rewrite :: language :: LanguageParseError ;
6596 fn from_str( s: & str ) -> Result <Self , Self :: Err > {
66- let prefix = format! ( "{}:" , std:: stringify!( [ <$variant $var_field: camel>] ) ) ;
67- if s . starts_with ( & prefix ) {
68- return Ok ( [ <$variant $var_field: camel>] ( s . replace ( & prefix , "" ) . parse( ) . unwrap( ) ) ) ;
97+ const PREFIX : & ' static str = concat! ( std:: stringify!( [ <$variant $var_field: camel>] ) , ":" ) ;
98+ if let Some ( suffix ) = s . strip_prefix ( PREFIX ) {
99+ return Ok ( [ <$variant $var_field: camel>] ( suffix . parse( ) . unwrap( ) ) ) ;
69100 }
70- Err ( CubeError :: internal ( format! ( "Can't convert {}. Should start with '{}'" , s , prefix ) ) )
101+ Err ( Self :: Err :: ShouldStartWith ( PREFIX ) )
71102 }
72103 }
73104
@@ -85,18 +116,17 @@ macro_rules! variant_field_struct {
85116 pub struct [ <$variant $var_field: camel>] ( Option <usize >) ;
86117
87118 impl FromStr for [ <$variant $var_field: camel>] {
88- type Err = CubeError ;
119+ type Err = $crate :: compile :: rewrite :: language :: LanguageParseError ;
89120 fn from_str( s: & str ) -> Result <Self , Self :: Err > {
90- let prefix = format!( "{}:" , std:: stringify!( [ <$variant $var_field: camel>] ) ) ;
91- if s. starts_with( & prefix) {
92- let replaced = s. replace( & prefix, "" ) ;
93- if & replaced == "None" {
121+ const PREFIX : & ' static str = concat!( std:: stringify!( [ <$variant $var_field: camel>] ) , ":" ) ;
122+ if let Some ( suffix) = s. strip_prefix( PREFIX ) {
123+ if suffix == "None" {
94124 return Ok ( [ <$variant $var_field: camel>] ( None ) ) ;
95125 } else {
96- return Ok ( [ <$variant $var_field: camel>] ( Some ( s . replace ( & prefix , "" ) . parse( ) . unwrap( ) ) ) ) ;
126+ return Ok ( [ <$variant $var_field: camel>] ( Some ( suffix . parse( ) . unwrap( ) ) ) ) ;
97127 }
98128 }
99- Err ( CubeError :: internal ( format! ( "Can't convert {}. Should start with '{}'" , s , prefix ) ) )
129+ Err ( Self :: Err :: ShouldStartWith ( PREFIX ) )
100130 }
101131 }
102132
@@ -114,18 +144,17 @@ macro_rules! variant_field_struct {
114144 pub struct [ <$variant $var_field: camel>] ( Option <Vec <String >>) ;
115145
116146 impl FromStr for [ <$variant $var_field: camel>] {
117- type Err = CubeError ;
147+ type Err = $crate :: compile :: rewrite :: language :: LanguageParseError ;
118148 fn from_str( s: & str ) -> Result <Self , Self :: Err > {
119- let prefix = format!( "{}:" , std:: stringify!( [ <$variant $var_field: camel>] ) ) ;
120- if s. starts_with( & prefix) {
121- let replaced = s. replace( & prefix, "" ) ;
122- if & replaced == "None" {
149+ const PREFIX : & ' static str = concat!( std:: stringify!( [ <$variant $var_field: camel>] ) , ":" ) ;
150+ if let Some ( suffix) = s. strip_prefix( PREFIX ) {
151+ if suffix == "None" {
123152 return Ok ( [ <$variant $var_field: camel>] ( None ) ) ;
124153 } else {
125- return Ok ( [ <$variant $var_field: camel>] ( Some ( s . split( ',' ) . map( |s| s. to_string( ) ) . collect:: <Vec <_>>( ) ) ) ) ;
154+ return Ok ( [ <$variant $var_field: camel>] ( Some ( suffix . split( ',' ) . map( |s| s. to_string( ) ) . collect:: <Vec <_>>( ) ) ) ) ;
126155 }
127156 }
128- Err ( CubeError :: internal ( format! ( "Can't convert {}. Should start with '{}'" , s , prefix ) ) )
157+ Err ( Self :: Err :: ShouldStartWith ( PREFIX ) )
129158 }
130159 }
131160
@@ -143,18 +172,17 @@ macro_rules! variant_field_struct {
143172 pub struct [ <$variant $var_field: camel>] ( Option <String >) ;
144173
145174 impl FromStr for [ <$variant $var_field: camel>] {
146- type Err = CubeError ;
175+ type Err = $crate :: compile :: rewrite :: language :: LanguageParseError ;
147176 fn from_str( s: & str ) -> Result <Self , Self :: Err > {
148- let prefix = format!( "{}:" , std:: stringify!( [ <$variant $var_field: camel>] ) ) ;
149- if s. starts_with( & prefix) {
150- let replaced = s. replace( & prefix, "" ) ;
151- if & replaced == "None" {
177+ const PREFIX : & ' static str = concat!( std:: stringify!( [ <$variant $var_field: camel>] ) , ":" ) ;
178+ if let Some ( suffix) = s. strip_prefix( PREFIX ) {
179+ if suffix == "None" {
152180 return Ok ( [ <$variant $var_field: camel>] ( None ) ) ;
153181 } else {
154- return Ok ( [ <$variant $var_field: camel>] ( Some ( s . to_string( ) ) ) ) ;
182+ return Ok ( [ <$variant $var_field: camel>] ( Some ( suffix . to_string( ) ) ) ) ;
155183 }
156184 }
157- Err ( CubeError :: internal ( "Conversion from string is not supported" . to_string ( ) ) )
185+ Err ( Self :: Err :: NotSupported )
158186 }
159187 }
160188
@@ -172,9 +200,9 @@ macro_rules! variant_field_struct {
172200 pub struct [ <$variant $var_field: camel>] ( Column ) ;
173201
174202 impl FromStr for [ <$variant $var_field: camel>] {
175- type Err = CubeError ;
203+ type Err = $crate :: compile :: rewrite :: language :: LanguageParseError ;
176204 fn from_str( _s: & str ) -> Result <Self , Self :: Err > {
177- Err ( CubeError :: internal ( "Conversion from string is not supported" . to_string ( ) ) )
205+ Err ( Self :: Err :: NotSupported )
178206 }
179207 }
180208
@@ -192,9 +220,9 @@ macro_rules! variant_field_struct {
192220 pub struct [ <$variant $var_field: camel>] ( Vec <Column >) ;
193221
194222 impl FromStr for [ <$variant $var_field: camel>] {
195- type Err = CubeError ;
223+ type Err = $crate :: compile :: rewrite :: language :: LanguageParseError ;
196224 fn from_str( _s: & str ) -> Result <Self , Self :: Err > {
197- Err ( CubeError :: internal ( "Conversion from string is not supported" . to_string ( ) ) )
225+ Err ( Self :: Err :: NotSupported )
198226 }
199227 }
200228
@@ -212,9 +240,9 @@ macro_rules! variant_field_struct {
212240 pub struct [ <$variant $var_field: camel>] ( Vec <Column >) ;
213241
214242 impl FromStr for [ <$variant $var_field: camel>] {
215- type Err = CubeError ;
243+ type Err = $crate :: compile :: rewrite :: language :: LanguageParseError ;
216244 fn from_str( _s: & str ) -> Result <Self , Self :: Err > {
217- Err ( CubeError :: internal ( "Conversion from string is not supported" . to_string ( ) ) )
245+ Err ( Self :: Err :: NotSupported )
218246 }
219247 }
220248
@@ -232,9 +260,9 @@ macro_rules! variant_field_struct {
232260 pub struct [ <$variant $var_field: camel>] ( String ) ;
233261
234262 impl FromStr for [ <$variant $var_field: camel>] {
235- type Err = CubeError ;
263+ type Err = $crate :: compile :: rewrite :: language :: LanguageParseError ;
236264 fn from_str( _s: & str ) -> Result <Self , Self :: Err > {
237- Err ( CubeError :: internal ( "Conversion from string is not supported" . to_string ( ) ) )
265+ Err ( Self :: Err :: NotSupported )
238266 }
239267 }
240268
@@ -252,9 +280,9 @@ macro_rules! variant_field_struct {
252280 pub struct [ <$variant $var_field: camel>] ( String ) ;
253281
254282 impl FromStr for [ <$variant $var_field: camel>] {
255- type Err = CubeError ;
283+ type Err = $crate :: compile :: rewrite :: language :: LanguageParseError ;
256284 fn from_str( _s: & str ) -> Result <Self , Self :: Err > {
257- Err ( CubeError :: internal ( "Conversion from string is not supported" . to_string ( ) ) )
285+ Err ( Self :: Err :: NotSupported )
258286 }
259287 }
260288
@@ -272,13 +300,13 @@ macro_rules! variant_field_struct {
272300 pub struct [ <$variant $var_field: camel>] ( String ) ;
273301
274302 impl FromStr for [ <$variant $var_field: camel>] {
275- type Err = CubeError ;
303+ type Err = $crate :: compile :: rewrite :: language :: LanguageParseError ;
276304 fn from_str( s: & str ) -> Result <Self , Self :: Err > {
277- let prefix = format! ( "{}:" , std:: stringify!( [ <$variant $var_field: camel>] ) ) ;
278- if s . starts_with ( & prefix ) {
279- return Ok ( [ <$variant $var_field: camel>] ( s . replace ( & prefix , "" ) ) ) ;
305+ const PREFIX : & ' static str = concat! ( std:: stringify!( [ <$variant $var_field: camel>] ) , ":" ) ;
306+ if let Some ( suffix ) = s . strip_prefix ( PREFIX ) {
307+ return Ok ( [ <$variant $var_field: camel>] ( suffix . to_string ( ) ) ) ;
280308 }
281- Err ( CubeError :: internal ( format! ( "Can't convert {}. Should start with '{}'" , s , prefix ) ) )
309+ Err ( Self :: Err :: ShouldStartWith ( PREFIX ) )
282310 }
283311 }
284312
@@ -484,14 +512,16 @@ macro_rules! variant_field_struct {
484512 pub struct [ <$variant $var_field: camel>] ( $var_field_type) ;
485513
486514 impl FromStr for [ <$variant $var_field: camel>] {
487- type Err = CubeError ;
515+ type Err = $crate :: compile :: rewrite :: language :: LanguageParseError ;
488516 fn from_str( s: & str ) -> Result <Self , Self :: Err > {
489- let prefix = format!( "{}:" , std:: stringify!( [ <$variant $var_field: camel>] ) ) ;
490- let name = s. strip_prefix( & prefix) . ok_or( CubeError :: internal( format!( "Can't convert {}. Should start with '{}'" , s, prefix) ) ) ?;
517+ const PREFIX : & ' static str = concat!( std:: stringify!( [ <$variant $var_field: camel>] ) , ":" ) ;
518+ let name = s
519+ . strip_prefix( PREFIX )
520+ . ok_or( Self :: Err :: ShouldStartWith ( PREFIX ) ) ?;
491521
492522 match name {
493523 $( $name => Ok ( [ <$variant $var_field: camel>] ( $variant_type) ) , ) *
494- x => Err ( CubeError :: internal ( format! ( "{} can't be matched against {}" , x , std:: stringify!( $var_field_type) ) ) )
524+ _ => Err ( Self :: Err :: ShouldMatch ( std:: stringify!( $var_field_type) ) )
495525 }
496526 }
497527 }
@@ -557,10 +587,12 @@ macro_rules! variant_field_struct {
557587 pub struct [ <$variant $var_field: camel>] ( DataType ) ;
558588
559589 impl FromStr for [ <$variant $var_field: camel>] {
560- type Err = CubeError ;
590+ type Err = $crate :: compile :: rewrite :: language :: LanguageParseError ;
561591 fn from_str( s: & str ) -> Result <Self , Self :: Err > {
562- let prefix = format!( "{}:" , std:: stringify!( [ <$variant $var_field: camel>] ) ) ;
563- let typed_str = s. strip_prefix( & prefix) . ok_or( CubeError :: internal( format!( "Can't convert {}. Should start with '{}'" , s, prefix) ) ) ?;
592+ const PREFIX : & ' static str = concat!( std:: stringify!( [ <$variant $var_field: camel>] ) , ":" ) ;
593+ let typed_str = s
594+ . strip_prefix( PREFIX )
595+ . ok_or( Self :: Err :: ShouldStartWith ( PREFIX ) ) ?;
564596
565597 match typed_str {
566598 "Float32" => Ok ( [ <$variant $var_field: camel>] ( DataType :: Float32 ) ) ,
@@ -571,7 +603,7 @@ macro_rules! variant_field_struct {
571603 "Utf8" => Ok ( [ <$variant $var_field: camel>] ( DataType :: Utf8 ) ) ,
572604 "Date32" => Ok ( [ <$variant $var_field: camel>] ( DataType :: Date32 ) ) ,
573605 "Date64" => Ok ( [ <$variant $var_field: camel>] ( DataType :: Date64 ) ) ,
574- _ => Err ( CubeError :: internal ( format! ( "Can't convert {}. Should contain a valid type, actual: {}" , s , typed_str ) ) ) ,
606+ _ => Err ( Self :: Err :: InvalidType ) ,
575607 }
576608 }
577609 }
@@ -590,24 +622,26 @@ macro_rules! variant_field_struct {
590622 pub struct [ <$variant $var_field: camel>] ( ScalarValue ) ;
591623
592624 impl FromStr for [ <$variant $var_field: camel>] {
593- type Err = CubeError ;
625+ type Err = $crate :: compile :: rewrite :: language :: LanguageParseError ;
594626 fn from_str( s: & str ) -> Result <Self , Self :: Err > {
595- let prefix = format!( "{}:" , std:: stringify!( [ <$variant $var_field: camel>] ) ) ;
596- let typed_str = s. strip_prefix( & prefix) . ok_or( CubeError :: internal( format!( "Can't convert {}. Should start with '{}'" , s, prefix) ) ) ?;
627+ const PREFIX : & ' static str = concat!( std:: stringify!( [ <$variant $var_field: camel>] ) , ":" ) ;
628+ let typed_str = s
629+ . strip_prefix( PREFIX )
630+ . ok_or( Self :: Err :: ShouldStartWith ( PREFIX ) ) ?;
597631
598632 if let Some ( value) = typed_str. strip_prefix( "s:" ) {
599633 Ok ( [ <$variant $var_field: camel>] ( ScalarValue :: Utf8 ( Some ( value. to_string( ) ) ) ) )
600634 } else if let Some ( value) = typed_str. strip_prefix( "b:" ) {
601- let n: bool = value. parse( ) . map_err( |err| CubeError :: internal ( format! ( "Can't parse boolean scalar value from '{}' with error: {}" , typed_str , err) ) ) ?;
635+ let n: bool = value. parse( ) . map_err( |err| Self :: Err :: InvalidBoolValue ( err) ) ?;
602636 Ok ( [ <$variant $var_field: camel>] ( ScalarValue :: Boolean ( Some ( n) ) ) )
603637 } else if let Some ( value) = typed_str. strip_prefix( "i:" ) {
604- let n: i64 = value. parse( ) . map_err( |err| CubeError :: internal ( format! ( "Can't parse i64 scalar value from '{}' with error: {}" , typed_str , err) ) ) ?;
638+ let n: i64 = value. parse( ) . map_err( |err| Self :: Err :: InvalidIntValue ( err) ) ?;
605639 Ok ( [ <$variant $var_field: camel>] ( ScalarValue :: Int64 ( Some ( n) ) ) )
606640 } else if let Some ( value) = typed_str. strip_prefix( "f:" ) {
607- let n: f64 = value. parse( ) . map_err( |err| CubeError :: internal ( format! ( "Can't parse f64 scalar value from '{}' with error: {}" , typed_str , err) ) ) ?;
641+ let n: f64 = value. parse( ) . map_err( |err| Self :: Err :: InvalidFloatValue ( err) ) ?;
608642 Ok ( [ <$variant $var_field: camel>] ( ScalarValue :: Float64 ( Some ( n) ) ) )
609643 } else {
610- Err ( CubeError :: internal ( format! ( "Can't convert {}. Should contains type type, actual: {}" , s , typed_str ) ) )
644+ Err ( Self :: Err :: InvalidScalarType )
611645 }
612646 }
613647 }
@@ -657,9 +691,9 @@ macro_rules! variant_field_struct {
657691 pub struct [ <$variant $var_field: camel>] ( $var_field_type) ;
658692
659693 impl FromStr for [ <$variant $var_field: camel>] {
660- type Err = CubeError ;
694+ type Err = $crate :: compile :: rewrite :: language :: LanguageParseError ;
661695 fn from_str( _s: & str ) -> Result <Self , Self :: Err > {
662- Err ( CubeError :: internal ( "Conversion from string is not supported" . to_string ( ) ) )
696+ Err ( Self :: Err :: NotSupported )
663697 }
664698 }
665699
0 commit comments