Skip to main content

geam_core/runtime/error/
invariant.rs

1use crate::plan::execution::function::FunctionReturnFamily;
2use crate::plan::{CustomType, ValueType};
3use ecow::EcoString;
4
5#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
6pub enum InvariantError {
7    #[error("function return family mismatch (expected {expected}, got {actual})")]
8    FunctionReturnFamilyMismatch {
9        expected: FunctionReturnFamily,
10        actual: FunctionReturnFamily,
11    },
12    #[error("tuple index family mismatch (expected {expected:?}, got {actual:?})")]
13    TupleIndexFamilyMismatch {
14        expected: ValueType,
15        actual: ValueType,
16    },
17    #[error(
18        "custom field family mismatch in {custom_type:?}::{constructor} field {field_index} (expected {expected:?}, got {actual:?})"
19    )]
20    CustomFieldFamilyMismatch {
21        custom_type: CustomType,
22        constructor: EcoString,
23        field_index: usize,
24        expected: ValueType,
25        actual: ValueType,
26    },
27    #[error("list index out of bounds for {item_type:?} list (index {index}, length {length})")]
28    ListIndexOutOfBounds {
29        item_type: ValueType,
30        index: usize,
31        length: usize,
32    },
33}
34
35#[cfg(test)]
36mod tests {
37    use super::InvariantError;
38    use crate::plan::execution::function::FunctionReturnFamily;
39    use crate::plan::{CustomType, CustomTypeName, ValueType};
40
41    #[test]
42    fn function_return_family_mismatch_display() {
43        let error = InvariantError::FunctionReturnFamilyMismatch {
44            expected: FunctionReturnFamily::Int,
45            actual: FunctionReturnFamily::String,
46        };
47
48        assert_eq!(
49            error.to_string(),
50            "function return family mismatch (expected Int, got String)",
51        );
52    }
53
54    #[test]
55    fn tuple_index_family_mismatch_display() {
56        let error = InvariantError::TupleIndexFamilyMismatch {
57            expected: ValueType::Tuple(vec![ValueType::Int]),
58            actual: ValueType::String,
59        };
60
61        assert_eq!(
62            error.to_string(),
63            "tuple index family mismatch (expected Tuple([Int]), got String)",
64        );
65    }
66
67    #[test]
68    fn list_index_out_of_bounds_display() {
69        let error = InvariantError::ListIndexOutOfBounds {
70            item_type: ValueType::Int,
71            index: 1,
72            length: 1,
73        };
74
75        assert_eq!(
76            error.to_string(),
77            "list index out of bounds for Int list (index 1, length 1)",
78        );
79    }
80
81    #[test]
82    fn custom_field_family_mismatch_display() {
83        let error = InvariantError::CustomFieldFamilyMismatch {
84            custom_type: CustomType::new(
85                CustomTypeName::new("app".into(), "main".into(), "Box".into()),
86                vec![ValueType::Int],
87            ),
88            constructor: "Box".into(),
89            field_index: 0,
90            expected: ValueType::Int,
91            actual: ValueType::String,
92        };
93
94        assert_eq!(
95            error.to_string(),
96            "custom field family mismatch in CustomType { name: CustomTypeName { package: \"app\", module: \"main\", name: \"Box\" }, arguments: [Int] }::Box field 0 (expected Int, got String)",
97        );
98    }
99}