Skip to main content

interstice_abi/interstice_value/
validate.rs

1use std::collections::HashMap;
2
3use crate::{IntersticeType, IntersticeTypeDef, IntersticeValue};
4
5pub fn validate_value(
6    value: &IntersticeValue,
7    ty: &IntersticeType,
8    type_definitions: &HashMap<String, IntersticeTypeDef>,
9) -> bool {
10    match value {
11        IntersticeValue::Void => {
12            if let IntersticeType::Void = ty {
13                true
14            } else {
15                false
16            }
17        }
18        IntersticeValue::Bool(_) => {
19            if let IntersticeType::Bool = ty {
20                true
21            } else {
22                false
23            }
24        }
25        IntersticeValue::U32(_) => {
26            if let IntersticeType::U32 = ty {
27                true
28            } else {
29                false
30            }
31        }
32        IntersticeValue::U8(_) => {
33            if let IntersticeType::U8 = ty {
34                true
35            } else {
36                false
37            }
38        }
39        IntersticeValue::U64(_) => {
40            if let IntersticeType::U64 = ty {
41                true
42            } else {
43                false
44            }
45        }
46        IntersticeValue::I32(_) => {
47            if let IntersticeType::I32 = ty {
48                true
49            } else {
50                false
51            }
52        }
53        IntersticeValue::I64(_) => {
54            if let IntersticeType::I64 = ty {
55                true
56            } else {
57                false
58            }
59        }
60        IntersticeValue::F32(_) => {
61            if let IntersticeType::F32 = ty {
62                true
63            } else {
64                false
65            }
66        }
67        IntersticeValue::F64(_) => {
68            if let IntersticeType::F64 = ty {
69                true
70            } else {
71                false
72            }
73        }
74        IntersticeValue::String(_) => {
75            if let IntersticeType::String = ty {
76                true
77            } else {
78                false
79            }
80        }
81        IntersticeValue::Vec(v) => {
82            if let IntersticeType::Vec(inner) = ty {
83                v.iter().all(|x| validate_value(x, inner, type_definitions))
84            } else {
85                false
86            }
87        }
88        IntersticeValue::Option(None) => {
89            if let IntersticeType::Option(_) = ty {
90                true
91            } else {
92                false
93            }
94        }
95        IntersticeValue::Option(Some(v)) => {
96            if let IntersticeType::Option(inner) = ty {
97                validate_value(v, inner, type_definitions)
98            } else {
99                false
100            }
101        }
102        IntersticeValue::Tuple(interstice_values) => {
103            if let IntersticeType::Tuple(inner) = ty {
104                inner
105                    .iter()
106                    .zip(interstice_values)
107                    .all(|(inner_ty, inner_val)| {
108                        validate_value(inner_val, inner_ty, type_definitions)
109                    })
110            } else {
111                false
112            }
113        }
114        IntersticeValue::Struct { name, fields } => {
115            if let IntersticeType::Named(type_name) = ty {
116                if type_name != name {
117                    return false;
118                }
119                if let Some(IntersticeTypeDef::Struct {
120                    name: _name_def,
121                    fields: fields_def,
122                }) = type_definitions.get(type_name)
123                {
124                    // TODO: here the order of the field definition matter, make it not
125                    fields.iter().zip(fields_def).all(|(field, field_def)| {
126                        field.name == field_def.name
127                            && validate_value(&field.value, &field_def.field_type, type_definitions)
128                    })
129                } else {
130                    false
131                }
132            } else {
133                false
134            }
135        }
136        IntersticeValue::Enum {
137            name,
138            variant,
139            value,
140        } => {
141            if let IntersticeType::Named(type_name) = ty {
142                if type_name != name {
143                    return false;
144                }
145                if let Some(IntersticeTypeDef::Enum {
146                    name: _name_def,
147                    variants,
148                }) = type_definitions.get(type_name)
149                {
150                    for variant_def in variants {
151                        if &variant_def.name == variant {
152                            return validate_value(
153                                value,
154                                &variant_def.field_type,
155                                type_definitions,
156                            );
157                        }
158                    }
159                    false
160                } else {
161                    false
162                }
163            } else {
164                false
165            }
166        }
167    }
168}