Skip to main content

substrait_explain/parser/
expressions.rs

1use chrono::{DateTime, NaiveDate, NaiveDateTime, NaiveTime};
2use substrait::proto::aggregate_rel::Measure;
3use substrait::proto::expression::field_reference::{ReferenceType, RootReference, RootType};
4use substrait::proto::expression::if_then::IfClause;
5use substrait::proto::expression::literal::LiteralType;
6use substrait::proto::expression::{
7    Cast, FieldReference, IfThen, Literal, ReferenceSegment, RexType, ScalarFunction, cast,
8    reference_segment,
9};
10use substrait::proto::function_argument::ArgType;
11use substrait::proto::r#type::{Fp64, I64, Kind, Nullability};
12use substrait::proto::{AggregateFunction, Expression, FunctionArgument, Type};
13
14use super::types::get_and_validate_anchor;
15use super::{
16    MessageParseError, ParsePair, Rule, RuleIter, ScopedParsePair, unescape_string,
17    unwrap_single_pair,
18};
19use crate::extensions::SimpleExtensions;
20use crate::extensions::simple::{CompoundName, ExtensionKind};
21use crate::parser::ErrorKind;
22
23/// A field index (e.g., parsed from "$0" -> 0).
24#[derive(Debug, Clone, Copy, PartialEq, Eq)]
25pub struct FieldIndex(pub i32);
26
27impl FieldIndex {
28    /// Convert this field index to a FieldReference for use in expressions.
29    pub fn to_field_reference(self) -> FieldReference {
30        // XXX: Why is it so many layers to make a struct field reference? This is
31        // surprisingly complex
32        FieldReference {
33            reference_type: Some(ReferenceType::DirectReference(ReferenceSegment {
34                reference_type: Some(reference_segment::ReferenceType::StructField(Box::new(
35                    reference_segment::StructField {
36                        field: self.0,
37                        child: None,
38                    },
39                ))),
40            })),
41            root_type: Some(RootType::RootReference(RootReference {})),
42        }
43    }
44}
45
46impl ParsePair for FieldIndex {
47    fn rule() -> Rule {
48        Rule::reference
49    }
50
51    fn message() -> &'static str {
52        "FieldIndex"
53    }
54
55    fn parse_pair(pair: pest::iterators::Pair<Rule>) -> Self {
56        assert_eq!(pair.as_rule(), Self::rule());
57        let inner = unwrap_single_pair(pair);
58        let index: i32 = inner.as_str().parse().unwrap();
59        FieldIndex(index)
60    }
61}
62
63impl ParsePair for FieldReference {
64    fn rule() -> Rule {
65        Rule::reference
66    }
67
68    fn message() -> &'static str {
69        "FieldReference"
70    }
71
72    fn parse_pair(pair: pest::iterators::Pair<Rule>) -> Self {
73        assert_eq!(pair.as_rule(), Self::rule());
74
75        // TODO: Other types of references.
76        FieldIndex::parse_pair(pair).to_field_reference()
77    }
78}
79
80fn to_int_literal(
81    value: pest::iterators::Pair<Rule>,
82    typ: Option<Type>,
83) -> Result<Literal, MessageParseError> {
84    assert_eq!(value.as_rule(), Rule::integer);
85    let parsed_value: i64 = value.as_str().parse().unwrap();
86
87    const DEFAULT_KIND: Kind = Kind::I64(I64 {
88        type_variation_reference: 0,
89        nullability: Nullability::Required as i32,
90    });
91
92    // If no type is provided, we assume i64, Nullability::Required.
93    let kind = typ.and_then(|t| t.kind).unwrap_or(DEFAULT_KIND);
94
95    let (lit, nullability, tvar) = match &kind {
96        // If no type is provided, we assume i64, Nullability::Required.
97        Kind::I8(i) => (
98            LiteralType::I8(parsed_value as i32),
99            i.nullability,
100            i.type_variation_reference,
101        ),
102        Kind::I16(i) => (
103            LiteralType::I16(parsed_value as i32),
104            i.nullability,
105            i.type_variation_reference,
106        ),
107        Kind::I32(i) => (
108            LiteralType::I32(parsed_value as i32),
109            i.nullability,
110            i.type_variation_reference,
111        ),
112        Kind::I64(i) => (
113            LiteralType::I64(parsed_value),
114            i.nullability,
115            i.type_variation_reference,
116        ),
117        k => {
118            let pest_error = pest::error::Error::new_from_span(
119                pest::error::ErrorVariant::CustomError {
120                    message: format!("Invalid type for integer literal: {k:?}"),
121                },
122                value.as_span(),
123            );
124            let error = MessageParseError {
125                message: "int_literal_type",
126                kind: ErrorKind::InvalidValue,
127                error: Box::new(pest_error),
128            };
129            return Err(error);
130        }
131    };
132
133    Ok(Literal {
134        literal_type: Some(lit),
135        nullable: nullability != Nullability::Required as i32,
136        type_variation_reference: tvar,
137    })
138}
139
140fn to_float_literal(
141    value: pest::iterators::Pair<Rule>,
142    typ: Option<Type>,
143) -> Result<Literal, MessageParseError> {
144    assert_eq!(value.as_rule(), Rule::float);
145    let parsed_value: f64 = value.as_str().parse().unwrap();
146
147    const DEFAULT_KIND: Kind = Kind::Fp64(Fp64 {
148        type_variation_reference: 0,
149        nullability: Nullability::Required as i32,
150    });
151
152    // If no type is provided, we assume fp64, Nullability::Required.
153    let kind = typ.and_then(|t| t.kind).unwrap_or(DEFAULT_KIND);
154
155    let (lit, nullability, tvar) = match &kind {
156        Kind::Fp32(f) => (
157            LiteralType::Fp32(parsed_value as f32),
158            f.nullability,
159            f.type_variation_reference,
160        ),
161        Kind::Fp64(f) => (
162            LiteralType::Fp64(parsed_value),
163            f.nullability,
164            f.type_variation_reference,
165        ),
166        k => {
167            let pest_error = pest::error::Error::new_from_span(
168                pest::error::ErrorVariant::CustomError {
169                    message: format!("Invalid type for float literal: {k:?}"),
170                },
171                value.as_span(),
172            );
173            let error = MessageParseError {
174                message: "float_literal_type",
175                kind: ErrorKind::InvalidValue,
176                error: Box::new(pest_error),
177            };
178            return Err(error);
179        }
180    };
181
182    Ok(Literal {
183        literal_type: Some(lit),
184        nullable: nullability != Nullability::Required as i32,
185        type_variation_reference: tvar,
186    })
187}
188
189fn to_boolean_literal(
190    value: pest::iterators::Pair<Rule>,
191    typ: Option<Type>,
192) -> Result<Literal, MessageParseError> {
193    assert_eq!(value.as_rule(), Rule::boolean);
194    let parsed_value: bool = value.as_str().parse().unwrap();
195
196    let (nullable, tvar) = match typ.and_then(|t| t.kind) {
197        Some(Kind::Bool(b)) => (
198            b.nullability != Nullability::Required as i32,
199            b.type_variation_reference,
200        ),
201        None => (false, 0),
202        Some(k) => {
203            let pest_error = pest::error::Error::new_from_span(
204                pest::error::ErrorVariant::CustomError {
205                    message: format!("Invalid type for boolean literal: {k:?}"),
206                },
207                value.as_span(),
208            );
209            return Err(MessageParseError {
210                message: "bool_literal_type",
211                kind: ErrorKind::InvalidValue,
212                error: Box::new(pest_error),
213            });
214        }
215    };
216
217    Ok(Literal {
218        literal_type: Some(LiteralType::Boolean(parsed_value)),
219        nullable,
220        type_variation_reference: tvar,
221    })
222}
223
224fn to_string_literal(
225    value: pest::iterators::Pair<Rule>,
226    typ: Option<Type>,
227) -> Result<Literal, MessageParseError> {
228    assert_eq!(value.as_rule(), Rule::string_literal);
229    let string_value = unescape_string(value.clone());
230
231    // If no type is provided, default to string
232    let Some(typ) = typ else {
233        return Ok(Literal {
234            literal_type: Some(LiteralType::String(string_value)),
235            nullable: false,
236            type_variation_reference: 0,
237        });
238    };
239
240    let Some(kind) = typ.kind else {
241        return Ok(Literal {
242            literal_type: Some(LiteralType::String(string_value)),
243            nullable: false,
244            type_variation_reference: 0,
245        });
246    };
247
248    match &kind {
249        Kind::Date(d) => {
250            // Parse date in ISO 8601 format: YYYY-MM-DD
251            let date_days = parse_date_to_days(&string_value, value.as_span())?;
252            Ok(Literal {
253                literal_type: Some(LiteralType::Date(date_days)),
254                nullable: d.nullability != Nullability::Required as i32,
255                type_variation_reference: d.type_variation_reference,
256            })
257        }
258        #[allow(deprecated)]
259        Kind::Time(t) => {
260            // Parse time in ISO 8601 format: HH:MM:SS[.fff]
261            let time_microseconds = parse_time_to_microseconds(&string_value, value.as_span())?;
262            Ok(Literal {
263                literal_type: Some(LiteralType::Time(time_microseconds)),
264                nullable: t.nullability != Nullability::Required as i32,
265                type_variation_reference: t.type_variation_reference,
266            })
267        }
268        #[allow(deprecated)]
269        Kind::Timestamp(ts) => {
270            // Parse timestamp in ISO 8601 format: YYYY-MM-DDTHH:MM:SS[.fff] or YYYY-MM-DD HH:MM:SS[.fff]
271            let timestamp_microseconds =
272                parse_timestamp_to_microseconds(&string_value, value.as_span())?;
273            Ok(Literal {
274                literal_type: Some(LiteralType::Timestamp(timestamp_microseconds)),
275                nullable: ts.nullability != Nullability::Required as i32,
276                type_variation_reference: ts.type_variation_reference,
277            })
278        }
279        _ => {
280            // For other types, treat as string
281            Ok(Literal {
282                literal_type: Some(LiteralType::String(string_value)),
283                nullable: false,
284                type_variation_reference: 0,
285            })
286        }
287    }
288}
289
290/// Parse a date string using chrono to days since Unix epoch
291fn parse_date_to_days(date_str: &str, span: pest::Span) -> Result<i32, MessageParseError> {
292    // Try multiple date formats for flexibility
293    let formats = ["%Y-%m-%d", "%Y/%m/%d"];
294
295    for format in &formats {
296        if let Ok(date) = NaiveDate::parse_from_str(date_str, format) {
297            // Calculate days since Unix epoch (1970-01-01)
298            let epoch = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap();
299            let days = date.signed_duration_since(epoch).num_days();
300            return Ok(days as i32);
301        }
302    }
303
304    Err(MessageParseError {
305        message: "date_parse_format",
306        kind: ErrorKind::InvalidValue,
307        error: Box::new(pest::error::Error::new_from_span(
308            pest::error::ErrorVariant::CustomError {
309                message: format!(
310                    "Invalid date format: '{date_str}'. Expected YYYY-MM-DD or YYYY/MM/DD"
311                ),
312            },
313            span,
314        )),
315    })
316}
317
318/// Parse a time string using chrono to microseconds since midnight
319fn parse_time_to_microseconds(time_str: &str, span: pest::Span) -> Result<i64, MessageParseError> {
320    // Try multiple time formats for flexibility
321    let formats = ["%H:%M:%S%.f", "%H:%M:%S"];
322
323    for format in &formats {
324        if let Ok(time) = NaiveTime::parse_from_str(time_str, format) {
325            // Convert to microseconds since midnight
326            let midnight = NaiveTime::from_hms_opt(0, 0, 0).unwrap();
327            let duration = time.signed_duration_since(midnight);
328            return Ok(duration.num_microseconds().unwrap_or(0));
329        }
330    }
331
332    Err(MessageParseError {
333        message: "time_parse_format",
334        kind: ErrorKind::InvalidValue,
335        error: Box::new(pest::error::Error::new_from_span(
336            pest::error::ErrorVariant::CustomError {
337                message: format!(
338                    "Invalid time format: '{time_str}'. Expected HH:MM:SS or HH:MM:SS.fff"
339                ),
340            },
341            span,
342        )),
343    })
344}
345
346/// Parse a timestamp string using chrono to microseconds since Unix epoch
347fn parse_timestamp_to_microseconds(
348    timestamp_str: &str,
349    span: pest::Span,
350) -> Result<i64, MessageParseError> {
351    // Try multiple timestamp formats for flexibility
352    let formats = [
353        "%Y-%m-%dT%H:%M:%S%.f", // ISO 8601 with T and fractional seconds
354        "%Y-%m-%dT%H:%M:%S",    // ISO 8601 with T
355        "%Y-%m-%d %H:%M:%S%.f", // Space separator with fractional seconds
356        "%Y-%m-%d %H:%M:%S",    // Space separator
357        "%Y/%m/%dT%H:%M:%S%.f", // Alternative date format with T
358        "%Y/%m/%dT%H:%M:%S",    // Alternative date format with T
359        "%Y/%m/%d %H:%M:%S%.f", // Alternative date format with space
360        "%Y/%m/%d %H:%M:%S",    // Alternative date format with space
361    ];
362
363    for format in &formats {
364        if let Ok(datetime) = NaiveDateTime::parse_from_str(timestamp_str, format) {
365            // Calculate microseconds since Unix epoch (1970-01-01 00:00:00)
366            let epoch = DateTime::from_timestamp(0, 0).unwrap().naive_utc();
367            let duration = datetime.signed_duration_since(epoch);
368            return Ok(duration.num_microseconds().unwrap_or(0));
369        }
370    }
371
372    Err(MessageParseError {
373        message: "timestamp_parse_format",
374        kind: ErrorKind::InvalidValue,
375        error: Box::new(pest::error::Error::new_from_span(
376            pest::error::ErrorVariant::CustomError {
377                message: format!(
378                    "Invalid timestamp format: '{timestamp_str}'. Expected YYYY-MM-DDTHH:MM:SS or YYYY-MM-DD HH:MM:SS"
379                ),
380            },
381            span,
382        )),
383    })
384}
385
386impl ScopedParsePair for Literal {
387    fn rule() -> Rule {
388        Rule::literal
389    }
390
391    fn message() -> &'static str {
392        "Literal"
393    }
394
395    fn parse_pair(
396        extensions: &SimpleExtensions,
397        pair: pest::iterators::Pair<Rule>,
398    ) -> Result<Self, MessageParseError> {
399        assert_eq!(pair.as_rule(), Self::rule());
400        let mut pairs = pair.into_inner();
401        let value = pairs.next().unwrap(); // First item is always the value
402        let typ = pairs.next(); // Second item is optional type
403        assert!(pairs.next().is_none());
404        let typ = match typ {
405            Some(t) => Some(Type::parse_pair(extensions, t)?),
406            None => None,
407        };
408        match value.as_rule() {
409            Rule::integer => to_int_literal(value, typ),
410            Rule::float => to_float_literal(value, typ),
411            Rule::boolean => to_boolean_literal(value, typ),
412            Rule::string_literal => to_string_literal(value, typ),
413            _ => unreachable!("Literal unexpected rule: {:?}", value.as_rule()),
414        }
415    }
416}
417
418impl ScopedParsePair for ScalarFunction {
419    fn rule() -> Rule {
420        Rule::function_call
421    }
422
423    fn message() -> &'static str {
424        "ScalarFunction"
425    }
426
427    fn parse_pair(
428        extensions: &SimpleExtensions,
429        pair: pest::iterators::Pair<Rule>,
430    ) -> Result<Self, MessageParseError> {
431        assert_eq!(pair.as_rule(), Self::rule());
432        let span = pair.as_span();
433        let mut iter = RuleIter::from(pair.into_inner());
434
435        // Parse compound function name (required) — e.g. "equal" or "equal:any_any"
436        let name = iter.parse_next::<CompoundName>();
437
438        // Parse optional anchor (e.g., #1)
439        let anchor = iter
440            .try_pop(Rule::anchor)
441            .map(|n| unwrap_single_pair(n).as_str().parse::<u32>().unwrap());
442
443        // Parse optional URN anchor (e.g., @1)
444        let _urn_anchor = iter
445            .try_pop(Rule::urn_anchor)
446            .map(|n| unwrap_single_pair(n).as_str().parse::<u32>().unwrap());
447
448        // Parse argument list (required)
449        let argument_list = iter.pop(Rule::argument_list);
450        let mut arguments = Vec::new();
451        for e in argument_list.into_inner() {
452            arguments.push(FunctionArgument {
453                arg_type: Some(ArgType::Value(Expression::parse_pair(extensions, e)?)),
454            });
455        }
456
457        // Parse optional output type (e.g., :i64)
458        let output_type = match iter.try_pop(Rule::r#type) {
459            Some(t) => Some(Type::parse_pair(extensions, t)?),
460            None => None,
461        };
462
463        iter.done();
464        let anchor = get_and_validate_anchor(
465            extensions,
466            ExtensionKind::Function,
467            anchor,
468            name.full(),
469            span,
470        )?;
471        Ok(ScalarFunction {
472            function_reference: anchor,
473            arguments,
474            options: vec![], // TODO: Function Options
475            output_type,
476            #[allow(deprecated)]
477            args: vec![],
478        })
479    }
480}
481
482impl ScopedParsePair for Cast {
483    fn rule() -> Rule {
484        Rule::cast_expression
485    }
486
487    fn message() -> &'static str {
488        "Cast"
489    }
490
491    fn parse_pair(
492        extensions: &SimpleExtensions,
493        pair: pest::iterators::Pair<Rule>,
494    ) -> Result<Self, MessageParseError> {
495        assert_eq!(pair.as_rule(), Self::rule());
496        let mut pairs = pair.into_inner();
497
498        let expr_pair = pairs.next().unwrap();
499
500        // Optional failure behavior prefix: ? = RETURN_NULL, ! = THROW_EXCEPTION
501        let next = pairs.next().unwrap();
502        let (failure_behavior, type_pair) = if next.as_rule() == Rule::cast_failure_behavior {
503            let fb = match next.as_str() {
504                "?" => cast::FailureBehavior::ReturnNull as i32,
505                "!" => cast::FailureBehavior::ThrowException as i32,
506                _ => unreachable!("Grammar guarantees cast_failure_behavior is ? or !"),
507            };
508            (fb, pairs.next().unwrap())
509        } else {
510            (cast::FailureBehavior::Unspecified as i32, next)
511        };
512
513        assert!(pairs.next().is_none());
514
515        let input = Expression::parse_pair(extensions, expr_pair)?;
516        let target_type = Type::parse_pair(extensions, type_pair)?;
517
518        Ok(Cast {
519            r#type: Some(target_type),
520            input: Some(Box::new(input)),
521            failure_behavior,
522        })
523    }
524}
525
526impl ScopedParsePair for Expression {
527    fn rule() -> Rule {
528        Rule::expression
529    }
530
531    fn message() -> &'static str {
532        "Expression"
533    }
534
535    fn parse_pair(
536        extensions: &SimpleExtensions,
537        pair: pest::iterators::Pair<Rule>,
538    ) -> Result<Self, MessageParseError> {
539        assert_eq!(pair.as_rule(), Self::rule());
540        let inner = unwrap_single_pair(pair);
541        match inner.as_rule() {
542            Rule::literal => Ok(Expression {
543                rex_type: Some(RexType::Literal(Literal::parse_pair(extensions, inner)?)),
544            }),
545            Rule::function_call => Ok(Expression {
546                rex_type: Some(RexType::ScalarFunction(ScalarFunction::parse_pair(
547                    extensions, inner,
548                )?)),
549            }),
550            Rule::reference => Ok(Expression {
551                rex_type: Some(RexType::Selection(Box::new(FieldReference::parse_pair(
552                    inner,
553                )))),
554            }),
555            Rule::if_then => Ok(Expression {
556                rex_type: Some(RexType::IfThen(Box::new(IfThen::parse_pair(
557                    extensions, inner,
558                )?))),
559            }),
560            Rule::cast_expression => Ok(Expression {
561                rex_type: Some(RexType::Cast(Box::new(Cast::parse_pair(
562                    extensions, inner,
563                )?))),
564            }),
565            _ => unreachable!(
566                "Grammar guarantees expression can only be literal, function_call, reference, if_then, or cast_expression, got: {:?}",
567                inner.as_rule()
568            ),
569        }
570    }
571}
572
573impl ScopedParsePair for IfClause {
574    fn rule() -> Rule {
575        Rule::if_clause
576    }
577
578    fn message() -> &'static str {
579        "IfClause"
580    }
581
582    fn parse_pair(
583        extensions: &SimpleExtensions,
584        pair: pest::iterators::Pair<Rule>,
585    ) -> Result<Self, MessageParseError> {
586        assert_eq!(pair.as_rule(), Self::rule());
587        let mut pairs = pair.into_inner(); // should have 2 children, 2 expressions
588
589        let condition = pairs.next().unwrap();
590        let result = pairs.next().unwrap();
591        assert!(pairs.next().is_none());
592
593        let ex1 = Some(Expression::parse_pair(extensions, condition)?);
594        let ex2 = Some(Expression::parse_pair(extensions, result)?);
595
596        Ok(IfClause {
597            r#if: ex1,
598            then: ex2,
599        })
600    }
601}
602
603impl ScopedParsePair for IfThen {
604    fn rule() -> Rule {
605        Rule::if_then
606    }
607    fn message() -> &'static str {
608        "IfThen"
609    }
610
611    fn parse_pair(
612        extensions: &SimpleExtensions,
613        pair: pest::iterators::Pair<Rule>,
614    ) -> Result<Self, MessageParseError> {
615        assert_eq!(pair.as_rule(), Self::rule());
616
617        let mut iter = RuleIter::from(pair.into_inner()); // should have 2 or more children
618
619        let mut ifs: Vec<IfClause> = Vec::new();
620
621        // gets all of the if clauses
622        while let Some(p) = iter.try_pop(Rule::if_clause) {
623            let if_clause = IfClause::parse_pair(extensions, p)?;
624            ifs.push(if_clause);
625        }
626
627        let pair = iter.try_pop(Rule::expression).unwrap(); // should be else expression
628        iter.done();
629        let else_clause = Some(Box::new(Expression::parse_pair(extensions, pair)?));
630
631        Ok(IfThen {
632            ifs,
633            r#else: else_clause,
634        })
635    }
636}
637pub struct Name(pub String);
638
639impl ParsePair for Name {
640    fn rule() -> Rule {
641        Rule::name
642    }
643
644    fn message() -> &'static str {
645        "Name"
646    }
647
648    fn parse_pair(pair: pest::iterators::Pair<Rule>) -> Self {
649        assert_eq!(pair.as_rule(), Self::rule());
650        let inner = unwrap_single_pair(pair);
651        match inner.as_rule() {
652            Rule::identifier => Name(inner.as_str().to_string()),
653            Rule::quoted_name => Name(unescape_string(inner)),
654            _ => unreachable!("Name unexpected rule: {:?}", inner.as_rule()),
655        }
656    }
657}
658
659impl ParsePair for CompoundName {
660    fn rule() -> Rule {
661        Rule::compound_name
662    }
663
664    fn message() -> &'static str {
665        "CompoundName"
666    }
667
668    fn parse_pair(pair: pest::iterators::Pair<Rule>) -> Self {
669        assert_eq!(pair.as_rule(), Self::rule());
670        CompoundName::new(pair.as_str())
671    }
672}
673
674impl ScopedParsePair for Measure {
675    fn rule() -> Rule {
676        Rule::aggregate_measure
677    }
678
679    fn message() -> &'static str {
680        "Measure"
681    }
682
683    fn parse_pair(
684        extensions: &SimpleExtensions,
685        pair: pest::iterators::Pair<Rule>,
686    ) -> Result<Self, MessageParseError> {
687        assert_eq!(pair.as_rule(), Self::rule());
688
689        // Extract the inner function_call from aggregate_measure
690        let function_call_pair = unwrap_single_pair(pair);
691        assert_eq!(function_call_pair.as_rule(), Rule::function_call);
692
693        // Parse as ScalarFunction, then convert to AggregateFunction
694        let scalar = ScalarFunction::parse_pair(extensions, function_call_pair)?;
695        Ok(Measure {
696            measure: Some(AggregateFunction {
697                function_reference: scalar.function_reference,
698                arguments: scalar.arguments,
699                options: scalar.options,
700                output_type: scalar.output_type,
701                invocation: 0, // TODO: support invocation (ALL, DISTINCT, etc.)
702                phase: 0, // TODO: support phase (INITIAL_TO_RESULT, PARTIAL_TO_INTERMEDIATE, etc.)
703                sorts: vec![], // TODO: support sorts for ordered aggregates
704                #[allow(deprecated)]
705                args: scalar.args,
706            }),
707            filter: None, // TODO: support filter conditions on aggregate measures
708        })
709    }
710}
711
712#[cfg(test)]
713mod tests {
714    use pest::Parser as PestParser;
715
716    use super::*;
717    use crate::parser::ExpressionParser;
718
719    fn parse_exact(rule: Rule, input: &'_ str) -> pest::iterators::Pair<'_, Rule> {
720        let mut pairs = ExpressionParser::parse(rule, input).unwrap();
721        assert_eq!(pairs.as_str(), input);
722        let pair = pairs.next().unwrap();
723        assert_eq!(pairs.next(), None);
724        pair
725    }
726
727    fn assert_parses_to<T: ParsePair + PartialEq + std::fmt::Debug>(input: &str, expected: T) {
728        let pair = parse_exact(T::rule(), input);
729        let actual = T::parse_pair(pair);
730        assert_eq!(actual, expected);
731    }
732
733    fn assert_parses_with<T: ScopedParsePair + PartialEq + std::fmt::Debug>(
734        ext: &SimpleExtensions,
735        input: &str,
736        expected: T,
737    ) {
738        let pair = parse_exact(T::rule(), input);
739        let actual = T::parse_pair(ext, pair).unwrap();
740        assert_eq!(actual, expected);
741    }
742
743    #[test]
744    fn test_parse_field_reference() {
745        assert_parses_to("$1", FieldIndex(1).to_field_reference());
746    }
747
748    #[test]
749    fn test_parse_integer_literal() {
750        let extensions = SimpleExtensions::default();
751        let expected = Literal {
752            literal_type: Some(LiteralType::I64(1)),
753            nullable: false,
754            type_variation_reference: 0,
755        };
756        assert_parses_with(&extensions, "1", expected);
757    }
758
759    #[test]
760    fn test_parse_float_literal() {
761        // First test that the grammar can parse floats
762        let pairs = ExpressionParser::parse(Rule::float, "3.82").unwrap();
763        let parsed_text = pairs.as_str();
764        assert_eq!(parsed_text, "3.82");
765
766        let extensions = SimpleExtensions::default();
767        let expected = Literal {
768            literal_type: Some(LiteralType::Fp64(3.82)),
769            nullable: false,
770            type_variation_reference: 0,
771        };
772        assert_parses_with(&extensions, "3.82", expected);
773    }
774
775    #[test]
776    fn test_parse_negative_float_literal() {
777        let extensions = SimpleExtensions::default();
778        let expected = Literal {
779            literal_type: Some(LiteralType::Fp64(-2.5)),
780            nullable: false,
781            type_variation_reference: 0,
782        };
783        assert_parses_with(&extensions, "-2.5", expected);
784    }
785
786    #[test]
787    fn test_parse_boolean_true_literal() {
788        let extensions = SimpleExtensions::default();
789        let expected = Literal {
790            literal_type: Some(LiteralType::Boolean(true)),
791            nullable: false,
792            type_variation_reference: 0,
793        };
794        assert_parses_with(&extensions, "true", expected);
795    }
796
797    #[test]
798    fn test_parse_boolean_false_literal() {
799        let extensions = SimpleExtensions::default();
800        let expected = Literal {
801            literal_type: Some(LiteralType::Boolean(false)),
802            nullable: false,
803            type_variation_reference: 0,
804        };
805        assert_parses_with(&extensions, "false", expected);
806    }
807
808    #[test]
809    fn test_parse_nullable_boolean_literal() {
810        let extensions = SimpleExtensions::default();
811        let expected_true = Literal {
812            literal_type: Some(LiteralType::Boolean(true)),
813            nullable: true,
814            type_variation_reference: 0,
815        };
816        let expected_false = Literal {
817            literal_type: Some(LiteralType::Boolean(false)),
818            nullable: true,
819            type_variation_reference: 0,
820        };
821        assert_parses_with(&extensions, "true:boolean?", expected_true);
822        assert_parses_with(&extensions, "false:boolean?", expected_false);
823    }
824
825    #[test]
826    fn test_parse_nullable_integer_literal() {
827        let extensions = SimpleExtensions::default();
828        let expected_i32 = Literal {
829            literal_type: Some(LiteralType::I32(78)),
830            nullable: true,
831            type_variation_reference: 0,
832        };
833        let expected_i64 = Literal {
834            literal_type: Some(LiteralType::I64(42)),
835            nullable: true,
836            type_variation_reference: 0,
837        };
838        assert_parses_with(&extensions, "78:i32?", expected_i32);
839        assert_parses_with(&extensions, "42:i64?", expected_i64);
840    }
841
842    #[test]
843    fn test_parse_nullable_float_literal() {
844        let extensions = SimpleExtensions::default();
845        let expected_fp64 = Literal {
846            literal_type: Some(LiteralType::Fp64(3.19)),
847            nullable: true,
848            type_variation_reference: 0,
849        };
850        assert_parses_with(&extensions, "3.19:fp64?", expected_fp64);
851    }
852
853    #[test]
854    fn test_parse_float_literal_with_fp32_type() {
855        let extensions = SimpleExtensions::default();
856        let pair = parse_exact(Rule::literal, "3.82:fp32");
857        let result = Literal::parse_pair(&extensions, pair).unwrap();
858
859        match result.literal_type {
860            Some(LiteralType::Fp32(val)) => assert!((val - 3.82).abs() < f32::EPSILON),
861            _ => panic!("Expected Fp32 literal type"),
862        }
863    }
864
865    #[test]
866    fn test_parse_date_literal() {
867        let extensions = SimpleExtensions::default();
868        let pair = parse_exact(Rule::literal, "'2023-12-25':date");
869        let result = Literal::parse_pair(&extensions, pair).unwrap();
870
871        match result.literal_type {
872            Some(LiteralType::Date(days)) => {
873                // 2023-12-25 should be a positive number of days since 1970-01-01
874                assert!(
875                    days > 0,
876                    "Expected positive days since epoch, got: {}",
877                    days
878                );
879            }
880            _ => panic!("Expected Date literal type, got: {:?}", result.literal_type),
881        }
882    }
883
884    #[test]
885    fn test_parse_time_literal() {
886        let extensions = SimpleExtensions::default();
887        let pair = parse_exact(Rule::literal, "'14:30:45':time");
888        let result = Literal::parse_pair(&extensions, pair).unwrap();
889
890        match result.literal_type {
891            #[allow(deprecated)]
892            Some(LiteralType::Time(microseconds)) => {
893                // 14:30:45 = (14*3600 + 30*60 + 45) * 1_000_000 microseconds
894                let expected = (14 * 3600 + 30 * 60 + 45) * 1_000_000;
895                assert_eq!(microseconds, expected);
896            }
897            _ => panic!("Expected Time literal type, got: {:?}", result.literal_type),
898        }
899    }
900
901    #[test]
902    fn test_parse_timestamp_literal_with_t() {
903        let extensions = SimpleExtensions::default();
904        let pair = parse_exact(Rule::literal, "'2023-01-01T12:00:00':timestamp");
905        let result = Literal::parse_pair(&extensions, pair).unwrap();
906
907        match result.literal_type {
908            #[allow(deprecated)]
909            Some(LiteralType::Timestamp(microseconds)) => {
910                assert!(
911                    microseconds > 0,
912                    "Expected positive microseconds since epoch"
913                );
914            }
915            _ => panic!(
916                "Expected Timestamp literal type, got: {:?}",
917                result.literal_type
918            ),
919        }
920    }
921
922    #[test]
923    fn test_parse_timestamp_literal_with_space() {
924        let extensions = SimpleExtensions::default();
925        let pair = parse_exact(Rule::literal, "'2023-01-01 12:00:00':timestamp");
926        let result = Literal::parse_pair(&extensions, pair).unwrap();
927
928        match result.literal_type {
929            #[allow(deprecated)]
930            Some(LiteralType::Timestamp(microseconds)) => {
931                assert!(
932                    microseconds > 0,
933                    "Expected positive microseconds since epoch"
934                );
935            }
936            _ => panic!(
937                "Expected Timestamp literal type, got: {:?}",
938                result.literal_type
939            ),
940        }
941    }
942
943    /// Helper function to create a literal boolean expression
944    fn make_literal_bool(value: bool) -> Expression {
945        Expression {
946            rex_type: Some(RexType::Literal(Literal {
947                literal_type: Some(LiteralType::Boolean(value)),
948                nullable: false,
949                type_variation_reference: 0,
950            })),
951        }
952    }
953
954    #[test]
955    fn test_parse_if_then_single_clause() {
956        let extensions = SimpleExtensions::default();
957        let input = "if_then(true -> 42, _ -> 0)";
958        let pair = parse_exact(Rule::if_then, input);
959        let result = IfThen::parse_pair(&extensions, pair).unwrap();
960
961        assert_eq!(result.ifs.len(), 1);
962        assert!(result.r#else.is_some());
963    }
964
965    #[test]
966    fn test_parse_if_then_with_typed_literals() {
967        let extensions = SimpleExtensions::default();
968        let input = "if_then(true -> 100:i32, _ -> -100:i32)";
969        let pair = parse_exact(Rule::if_then, input);
970        let result = IfThen::parse_pair(&extensions, pair).unwrap();
971
972        assert_eq!(result.ifs.len(), 1);
973        assert!(result.r#else.is_some());
974    }
975
976    #[test]
977    fn test_parse_if_then_with_date_literals() {
978        let extensions = SimpleExtensions::default();
979        let input = "if_then(true -> '2023-12-25':date, _ -> '1970-01-01':date)";
980        let pair = parse_exact(Rule::if_then, input);
981        let result = IfThen::parse_pair(&extensions, pair).unwrap();
982
983        assert_eq!(result.ifs.len(), 1);
984        assert!(result.r#else.is_some());
985    }
986
987    #[test]
988    fn test_parse_if_then_with_time_literals() {
989        let extensions = SimpleExtensions::default();
990        let input = "if_then(true -> '14:30:45':time, _ -> '00:00:00':time)";
991        let pair = parse_exact(Rule::if_then, input);
992        let result = IfThen::parse_pair(&extensions, pair).unwrap();
993
994        assert_eq!(result.ifs.len(), 1);
995        assert!(result.r#else.is_some());
996    }
997
998    #[test]
999    fn test_parse_if_then_with_timestamp_literals() {
1000        let extensions = SimpleExtensions::default();
1001        let input = "if_then(true -> '2023-01-01T12:00:00':timestamp, _ -> '1970-01-01T00:00:00':timestamp)";
1002        let pair = parse_exact(Rule::if_then, input);
1003        let result = IfThen::parse_pair(&extensions, pair).unwrap();
1004
1005        assert_eq!(result.ifs.len(), 1);
1006        assert!(result.r#else.is_some());
1007    }
1008
1009    #[test]
1010    fn test_parse_if_clause_with_whitespace_variations() {
1011        let extensions = SimpleExtensions::default();
1012
1013        // Test with various whitespace patterns
1014        let inputs = vec!["true->false", "true -> false", "true  ->  false"];
1015
1016        for input in inputs {
1017            let pair = parse_exact(Rule::if_clause, input);
1018            let result = IfClause::parse_pair(&extensions, pair).unwrap();
1019            assert!(result.r#if.is_some());
1020            assert!(result.then.is_some());
1021        }
1022    }
1023
1024    #[test]
1025    fn test_if_clause_structure() {
1026        let extensions = SimpleExtensions::default();
1027        let pair = parse_exact(Rule::if_clause, "42 -> 100");
1028        let result = IfClause::parse_pair(&extensions, pair).unwrap();
1029
1030        // Verify the if clause has both condition and result
1031        let if_expr = result.r#if.as_ref().unwrap();
1032        let then_expr = result.then.as_ref().unwrap();
1033
1034        // Check that they are literal expressions
1035        match (&if_expr.rex_type, &then_expr.rex_type) {
1036            (Some(RexType::Literal(_)), Some(RexType::Literal(_))) => {
1037                // Success - both are literals as expected
1038            }
1039            _ => panic!("Expected both if and then to be literals"),
1040        }
1041    }
1042
1043    #[test]
1044    fn test_if_then_structure() {
1045        let extensions = SimpleExtensions::default();
1046        let input = "if_then(true -> 1, false -> 2, _ -> 0)";
1047        let pair = parse_exact(Rule::if_then, input);
1048        let result = IfThen::parse_pair(&extensions, pair).unwrap();
1049
1050        // Verify structure
1051        assert_eq!(result.ifs.len(), 2);
1052
1053        // Check each if clause
1054        for clause in &result.ifs {
1055            assert!(clause.r#if.is_some(), "If clause condition should exist");
1056            assert!(clause.then.is_some(), "If clause result should exist");
1057        }
1058
1059        // Check else clause
1060        assert!(result.r#else.is_some(), "Else clause should exist");
1061    }
1062
1063    #[test]
1064    fn test_parse_if_then_mixed_types_in_conditions() {
1065        let extensions = SimpleExtensions::default();
1066        // Different types in conditions (not results)
1067        let input = "if_then(true -> 1, true -> 'yes', 'yes' -> true, 42 -> 2, $0 -> 3, _ -> 0)";
1068        let pair = parse_exact(Rule::if_then, input);
1069        let result = IfThen::parse_pair(&extensions, pair).unwrap();
1070
1071        assert_eq!(result.ifs.len(), 5);
1072        assert!(result.r#else.is_some());
1073    }
1074
1075    #[test]
1076    fn test_if_then_preserves_clause_order() {
1077        let extensions = SimpleExtensions::default();
1078        let input = "if_then(1 -> 10, 2 -> 20, 3 -> 30, _ -> 0)";
1079        let pair = parse_exact(Rule::if_then, input);
1080        let result = IfThen::parse_pair(&extensions, pair).unwrap();
1081
1082        assert_eq!(result.ifs.len(), 3);
1083
1084        // Verify the clauses are in order by checking the literal values
1085        for (i, clause) in result.ifs.iter().enumerate() {
1086            if let Some(Expression {
1087                rex_type: Some(RexType::Literal(lit)),
1088            }) = &clause.r#if
1089                && let Some(LiteralType::I64(val)) = &lit.literal_type
1090            {
1091                assert_eq!(*val, (i as i64) + 1);
1092            }
1093        }
1094    }
1095
1096    #[test]
1097    fn test_parse_if_then() {
1098        let extensions = SimpleExtensions::default();
1099
1100        let c1 = IfClause {
1101            r#if: Some(make_literal_bool(true)),
1102            then: Some(make_literal_bool(true)),
1103        };
1104
1105        let c2 = IfClause {
1106            r#if: Some(make_literal_bool(false)),
1107            then: Some(make_literal_bool(false)),
1108        };
1109
1110        let if_clause = IfThen {
1111            ifs: vec![c1, c2],
1112            r#else: Some(Box::new(make_literal_bool(false))),
1113        };
1114        assert_parses_with(
1115            &extensions,
1116            "if_then(true -> true , false -> false, _ -> false)",
1117            if_clause,
1118        );
1119    }
1120
1121    // ---- Tests for CompoundName grammar rule ----
1122
1123    fn parse_compound_name(input: &str) -> CompoundName {
1124        let pair = parse_exact(Rule::compound_name, input);
1125        CompoundName::parse_pair(pair)
1126    }
1127
1128    #[test]
1129    fn test_compound_name_plain() {
1130        assert_eq!(parse_compound_name("add").full(), "add");
1131    }
1132
1133    #[test]
1134    fn test_compound_name_with_signature() {
1135        assert_eq!(parse_compound_name("equal:any_any").full(), "equal:any_any");
1136        assert_eq!(
1137            parse_compound_name("regexp_match_substring:str_str_i64").full(),
1138            "regexp_match_substring:str_str_i64"
1139        );
1140        assert_eq!(parse_compound_name("add:i64_i64").full(), "add:i64_i64");
1141    }
1142
1143    #[test]
1144    fn test_compound_name_stops_at_opening_paren() {
1145        // where is the paren ???
1146        // In a function call, the compound_name must stop before the '('.
1147        // Verify the grammar does not consume the paren.
1148        let pairs = ExpressionParser::parse(Rule::compound_name, "equal:any_any").unwrap();
1149        assert_eq!(pairs.as_str(), "equal:any_any");
1150    }
1151
1152    // ---- Tests for ScalarFunction parsing with compound names ----
1153
1154    fn make_extensions_for_fn_tests() -> SimpleExtensions {
1155        let mut exts = SimpleExtensions::default();
1156        exts.add_extension_urn("urn".to_string(), 1).unwrap();
1157        exts.add_extension(
1158            crate::extensions::simple::ExtensionKind::Function,
1159            1,
1160            1,
1161            "equal:any_any".to_string(),
1162        )
1163        .unwrap();
1164        exts.add_extension(
1165            crate::extensions::simple::ExtensionKind::Function,
1166            1,
1167            2,
1168            "equal:str_str".to_string(),
1169        )
1170        .unwrap();
1171        exts.add_extension(
1172            crate::extensions::simple::ExtensionKind::Function,
1173            1,
1174            3,
1175            "add:i64_i64".to_string(),
1176        )
1177        .unwrap();
1178        exts
1179    }
1180
1181    #[test]
1182    fn test_scalar_function_full_compound_name() {
1183        // Full compound name without anchor
1184        let exts = make_extensions_for_fn_tests();
1185        let pair = parse_exact(Rule::function_call, "equal:any_any($0, $1)");
1186        let f = ScalarFunction::parse_pair(&exts, pair).unwrap();
1187        assert_eq!(f.function_reference, 1);
1188        assert_eq!(f.arguments.len(), 2);
1189    }
1190
1191    #[test]
1192    fn test_scalar_function_second_overload() {
1193        let exts = make_extensions_for_fn_tests();
1194        let pair = parse_exact(Rule::function_call, "equal:str_str($0, $1)");
1195        let f = ScalarFunction::parse_pair(&exts, pair).unwrap();
1196
1197        assert_eq!(f.arguments.len(), 2);
1198        assert_eq!(f.function_reference, 2);
1199    }
1200
1201    #[test]
1202    fn test_scalar_function_base_name_unique_overload() {
1203        // "add" has only one overload; base-name lookup should succeed
1204        let exts = make_extensions_for_fn_tests();
1205        let pair = parse_exact(Rule::function_call, "add($0, $1)");
1206        let f = ScalarFunction::parse_pair(&exts, pair).unwrap();
1207
1208        assert_eq!(f.arguments.len(), 2);
1209        assert_eq!(f.function_reference, 3);
1210    }
1211
1212    #[test]
1213    fn test_scalar_function_base_name_ambiguous_fails() {
1214        // "equal" has two overloads; base-name lookup should fail
1215        let exts = make_extensions_for_fn_tests();
1216        let pair = parse_exact(Rule::function_call, "equal($0, $1)");
1217        let result = ScalarFunction::parse_pair(&exts, pair);
1218        assert!(result.is_err(), "ambiguous base name should fail");
1219    }
1220
1221    #[test]
1222    fn test_scalar_function_compound_name_with_anchor() {
1223        let exts = make_extensions_for_fn_tests();
1224        let pair = parse_exact(Rule::function_call, "equal:any_any#1($0, $1)");
1225        let f = ScalarFunction::parse_pair(&exts, pair).unwrap();
1226        assert_eq!(f.function_reference, 1);
1227        assert_eq!(f.arguments.len(), 2);
1228    }
1229
1230    #[test]
1231    fn test_scalar_function_base_name_with_anchor() {
1232        // Base name + explicit anchor should resolve (anchor 1 stores equal:any_any)
1233        let exts = make_extensions_for_fn_tests();
1234        let pair = parse_exact(Rule::function_call, "equal#1($0, $1)");
1235        let f = ScalarFunction::parse_pair(&exts, pair).unwrap();
1236        assert_eq!(f.function_reference, 1);
1237        assert_eq!(f.arguments.len(), 2);
1238    }
1239
1240    #[test]
1241    fn test_scalar_function_wrong_name_for_anchor_fails() {
1242        let exts = make_extensions_for_fn_tests();
1243        let pair = parse_exact(Rule::function_call, "like#1($0)");
1244        let result = ScalarFunction::parse_pair(&exts, pair);
1245        assert!(result.is_err(), "mismatched name/anchor should fail");
1246    }
1247
1248    #[test]
1249    fn test_parse_cast_expression_basic() {
1250        let extensions = SimpleExtensions::default();
1251        let pair = parse_exact(Rule::cast_expression, "(78:i32)::i16");
1252        let result = Cast::parse_pair(&extensions, pair).unwrap();
1253
1254        // Input should be 78:i32
1255        let input = result.input.as_ref().unwrap();
1256        match &input.rex_type {
1257            Some(RexType::Literal(lit)) => match &lit.literal_type {
1258                Some(LiteralType::I32(v)) => assert_eq!(*v, 78),
1259                other => panic!("Expected I32 literal, got: {:?}", other),
1260            },
1261            other => panic!("Expected literal, got: {:?}", other),
1262        }
1263
1264        // Target type should be i16
1265        let target = result.r#type.as_ref().unwrap();
1266        match &target.kind {
1267            Some(substrait::proto::r#type::Kind::I16(_)) => {}
1268            other => panic!("Expected i16 type, got: {:?}", other),
1269        }
1270
1271        assert_eq!(result.failure_behavior, 0);
1272    }
1273
1274    #[test]
1275    fn test_parse_cast_expression_via_expression_rule() {
1276        let extensions = SimpleExtensions::default();
1277        let pair = parse_exact(Rule::expression, "(78:i32)::i16");
1278        let result = Expression::parse_pair(&extensions, pair).unwrap();
1279
1280        match result.rex_type {
1281            Some(RexType::Cast(_)) => {}
1282            other => panic!("Expected Cast rex type, got: {:?}", other),
1283        }
1284    }
1285
1286    #[test]
1287    fn test_parse_cast_expression_nested() {
1288        let extensions = SimpleExtensions::default();
1289        let pair = parse_exact(Rule::cast_expression, "((78:i32)::i16)::i32");
1290        let result = Cast::parse_pair(&extensions, pair).unwrap();
1291
1292        // Input should itself be a Cast
1293        let input = result.input.as_ref().unwrap();
1294        match &input.rex_type {
1295            Some(RexType::Cast(inner)) => {
1296                let inner_input = inner.input.as_ref().unwrap();
1297                match &inner_input.rex_type {
1298                    Some(RexType::Literal(lit)) => match &lit.literal_type {
1299                        Some(LiteralType::I32(v)) => assert_eq!(*v, 78),
1300                        other => panic!("Expected I32 literal, got: {:?}", other),
1301                    },
1302                    other => panic!("Expected literal, got: {:?}", other),
1303                }
1304            }
1305            other => panic!("Expected inner Cast, got: {:?}", other),
1306        }
1307
1308        match &result.r#type.as_ref().unwrap().kind {
1309            Some(substrait::proto::r#type::Kind::I32(_)) => {}
1310            other => panic!("Expected i32 outer type, got: {:?}", other),
1311        }
1312    }
1313
1314    #[test]
1315    fn test_parse_cast_expression_with_boolean() {
1316        let extensions = SimpleExtensions::default();
1317        let pair = parse_exact(Rule::cast_expression, "(true)::i32");
1318        let result = Cast::parse_pair(&extensions, pair).unwrap();
1319
1320        let input = result.input.as_ref().unwrap();
1321        match &input.rex_type {
1322            Some(RexType::Literal(lit)) => match &lit.literal_type {
1323                Some(LiteralType::Boolean(v)) => assert!(*v),
1324                other => panic!("Expected Boolean literal, got: {:?}", other),
1325            },
1326            other => panic!("Expected literal, got: {:?}", other),
1327        }
1328    }
1329
1330    #[test]
1331    fn test_parse_cast_expression_with_whitespace() {
1332        let extensions = SimpleExtensions::default();
1333        // Grammar allows optional whitespace around the expression and ::
1334        let pair = parse_exact(Rule::cast_expression, "( 78:i32 ) :: i16");
1335        let result = Cast::parse_pair(&extensions, pair).unwrap();
1336        assert!(result.input.is_some());
1337        assert!(result.r#type.is_some());
1338    }
1339
1340    #[test]
1341    fn test_parse_cast_unspecified_failure_behavior() {
1342        let extensions = SimpleExtensions::default();
1343        let pair = parse_exact(Rule::cast_expression, "(78:i32)::i16");
1344        let result = Cast::parse_pair(&extensions, pair).unwrap();
1345        assert_eq!(
1346            result.failure_behavior,
1347            cast::FailureBehavior::Unspecified as i32
1348        );
1349    }
1350
1351    #[test]
1352    fn test_parse_cast_return_null_failure_behavior() {
1353        let extensions = SimpleExtensions::default();
1354        let pair = parse_exact(Rule::cast_expression, "(78:i32)::?i16");
1355        let result = Cast::parse_pair(&extensions, pair).unwrap();
1356        assert_eq!(
1357            result.failure_behavior,
1358            cast::FailureBehavior::ReturnNull as i32
1359        );
1360    }
1361
1362    #[test]
1363    fn test_parse_cast_throw_exception_failure_behavior() {
1364        let extensions = SimpleExtensions::default();
1365        let pair = parse_exact(Rule::cast_expression, "(78:i32)::!i16");
1366        let result = Cast::parse_pair(&extensions, pair).unwrap();
1367        assert_eq!(
1368            result.failure_behavior,
1369            cast::FailureBehavior::ThrowException as i32
1370        );
1371    }
1372}