interstice_abi/interstice_value/
validate.rs1use 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 validate_value_detailed(value, ty, type_definitions).is_ok()
11}
12
13pub fn validate_value_detailed(
14 value: &IntersticeValue,
15 ty: &IntersticeType,
16 type_definitions: &HashMap<String, IntersticeTypeDef>,
17) -> Result<(), String> {
18 match value {
19 IntersticeValue::Void => {
20 if let IntersticeType::Void = ty { Ok(()) } else { Err(format!("expected Void, got {:?}", ty)) }
21 }
22 IntersticeValue::Bool(_) => {
23 if let IntersticeType::Bool = ty { Ok(()) } else { Err(format!("expected Bool, got {:?}", ty)) }
24 }
25 IntersticeValue::U32(_) => {
26 if let IntersticeType::U32 = ty { Ok(()) } else { Err(format!("expected U32, got {:?}", ty)) }
27 }
28 IntersticeValue::U8(_) => {
29 if let IntersticeType::U8 = ty { Ok(()) } else { Err(format!("expected U8, got {:?}", ty)) }
30 }
31 IntersticeValue::U64(_) => {
32 if let IntersticeType::U64 = ty { Ok(()) } else { Err(format!("expected U64, got {:?}", ty)) }
33 }
34 IntersticeValue::I32(_) => {
35 if let IntersticeType::I32 = ty { Ok(()) } else { Err(format!("expected I32, got {:?}", ty)) }
36 }
37 IntersticeValue::I64(_) => {
38 if let IntersticeType::I64 = ty { Ok(()) } else { Err(format!("expected I64, got {:?}", ty)) }
39 }
40 IntersticeValue::F32(_) => {
41 if let IntersticeType::F32 = ty { Ok(()) } else { Err(format!("expected F32, got {:?}", ty)) }
42 }
43 IntersticeValue::F64(_) => {
44 if let IntersticeType::F64 = ty { Ok(()) } else { Err(format!("expected F64, got {:?}", ty)) }
45 }
46 IntersticeValue::String(_) => {
47 if let IntersticeType::String = ty { Ok(()) } else { Err(format!("expected String, got {:?}", ty)) }
48 }
49 IntersticeValue::Vec(v) => {
50 if let IntersticeType::Vec(inner) = ty {
51 for (i, x) in v.iter().enumerate() {
52 validate_value_detailed(x, inner, type_definitions)
53 .map_err(|e| format!("Vec[{}]: {}", i, e))?;
54 }
55 Ok(())
56 } else {
57 Err(format!("expected Vec, got {:?}", ty))
58 }
59 }
60 IntersticeValue::Option(None) => {
61 if let IntersticeType::Option(_) = ty { Ok(()) } else { Err(format!("expected Option, got {:?}", ty)) }
62 }
63 IntersticeValue::Option(Some(v)) => {
64 if let IntersticeType::Option(inner) = ty {
65 validate_value_detailed(v, inner, type_definitions)
66 .map_err(|e| format!("Option<Some>: {}", e))
67 } else {
68 Err(format!("expected Option, got {:?}", ty))
69 }
70 }
71 IntersticeValue::Tuple(interstice_values) => {
72 if let IntersticeType::Tuple(inner) = ty {
73 for (i, (inner_ty, inner_val)) in inner.iter().zip(interstice_values).enumerate() {
74 validate_value_detailed(inner_val, inner_ty, type_definitions)
75 .map_err(|e| format!("Tuple[{}]: {}", i, e))?;
76 }
77 Ok(())
78 } else {
79 Err(format!("expected Tuple, got {:?}", ty))
80 }
81 }
82 IntersticeValue::Struct { name, fields } => {
83 if let IntersticeType::Named(type_name) = ty {
84 if type_name != name {
85 return Err(format!("struct name mismatch: expected '{}', got '{}'", type_name, name));
86 }
87 if let Some(IntersticeTypeDef::Struct {
88 name: _name_def,
89 fields: fields_def,
90 }) = type_definitions.get(type_name)
91 {
92 for (field, field_def) in fields.iter().zip(fields_def) {
94 if field.name != field_def.name {
95 return Err(format!(
96 "struct '{}' field name mismatch: expected '{}', got '{}'",
97 type_name, field_def.name, field.name
98 ));
99 }
100 validate_value_detailed(&field.value, &field_def.field_type, type_definitions)
101 .map_err(|e| format!("struct '{}' field '{}': {}", type_name, field.name, e))?;
102 }
103 Ok(())
104 } else {
105 Err(format!(
106 "type '{}' not found in type_definitions (available: [{}])",
107 type_name,
108 type_definitions.keys().cloned().collect::<Vec<_>>().join(", ")
109 ))
110 }
111 } else {
112 Err(format!("expected Named type for struct '{}', got {:?}", name, ty))
113 }
114 }
115 IntersticeValue::Enum {
116 name,
117 variant,
118 value,
119 } => {
120 if let IntersticeType::Named(type_name) = ty {
121 if type_name != name {
122 return Err(format!("enum name mismatch: expected '{}', got '{}'", type_name, name));
123 }
124 if let Some(IntersticeTypeDef::Enum {
125 name: _name_def,
126 variants,
127 }) = type_definitions.get(type_name)
128 {
129 for variant_def in variants {
130 if &variant_def.name == variant {
131 return validate_value_detailed(
132 value,
133 &variant_def.field_type,
134 type_definitions,
135 )
136 .map_err(|e| format!("enum '{}' variant '{}': {}", type_name, variant, e));
137 }
138 }
139 Err(format!("enum '{}' has no variant '{}'", type_name, variant))
140 } else {
141 Err(format!(
142 "type '{}' not found in type_definitions (available: [{}])",
143 type_name,
144 type_definitions.keys().cloned().collect::<Vec<_>>().join(", ")
145 ))
146 }
147 } else {
148 Err(format!("expected Named type for enum '{}', got {:?}", name, ty))
149 }
150 }
151 }
152}