wick_packet/
wrapped_type.rs1use serde_json::Value;
2use wick_interface_types::Type;
3
4use crate::Error;
5
6#[derive(Debug, Clone)]
7#[must_use]
8pub struct TypeWrapper(Type, Value);
9
10impl TypeWrapper {
11 pub const fn new(ty: Type, val: Value) -> Self {
13 Self(ty, val)
14 }
15
16 pub const fn type_signature(&self) -> &Type {
17 &self.0
18 }
19
20 #[must_use]
21 #[allow(clippy::missing_const_for_fn)]
22 pub fn into_inner(self) -> Value {
23 self.1
24 }
25
26 #[must_use]
27 pub const fn inner(&self) -> &Value {
28 &self.1
29 }
30}
31
32macro_rules! coersion_err {
33 ($val:expr, $ty:expr) => {
34 return Err(Error::Coersion {
35 value: $val,
36 desired: $ty,
37 })
38 };
39}
40
41pub(crate) fn coerce(val: Value, ty: &Type) -> Result<Value, Error> {
42 let val = match ty {
43 Type::I8
44 | Type::I16
45 | Type::I32
46 | Type::I64
47 | Type::U8
48 | Type::U16
49 | Type::U32
50 | Type::U64
51 | Type::F32
52 | Type::F64 => match &val {
53 Value::Number(_) => val,
54 Value::String(v) => Value::Number(v.parse().map_err(|_| Error::Coersion {
55 value: val,
56 desired: ty.clone(),
57 })?),
58 _ => coersion_err!(val, ty.clone()),
59 },
60 Type::Bool => match &val {
61 Value::Bool(_) => val,
62 _ => coersion_err!(val, ty.clone()), },
64 Type::String => {
65 let string = match val {
66 Value::Null => String::new(),
67 Value::Bool(v) => v.to_string(),
68 Value::Number(v) => v.to_string(),
69 Value::String(v) => v,
70 _ => coersion_err!(val, ty.clone()),
71 };
72
73 Value::String(string)
74 }
75 Type::Datetime => match &val {
76 Value::Number(_) => val,
77 Value::String(_) => val,
78 _ => coersion_err!(val, ty.clone()),
79 },
80 Type::Bytes => match &val {
81 Value::String(_) => val,
82 _ => coersion_err!(val, ty.clone()), },
84 Type::Named(_) => unimplemented!("named types"),
85 Type::List { ty: inner_ty } => {
86 let Value::Array(val) = val else {
87 coersion_err!(val, ty.clone())
88 };
89
90 let mut out = Vec::with_capacity(val.len());
91 for v in val {
92 out.push(coerce(v, inner_ty)?);
93 }
94
95 Value::Array(out)
96 }
97 Type::Optional { ty: inner_ty } => {
98 if val.is_null() {
99 Value::Null
100 } else {
101 coerce(val, inner_ty)?
102 }
103 }
104 Type::Map {
105 value: inner_value_ty, ..
106 } => {
107 let Value::Object(obj) = val else {
108 coersion_err!(val, ty.clone())
109 };
110
111 let mut out = serde_json::Map::with_capacity(obj.len());
112 for (k, v) in obj {
113 out.insert(k, coerce(v, inner_value_ty)?);
114 }
115
116 Value::Object(out)
117 }
118 #[allow(deprecated)]
119 Type::Link { .. } => match &val {
120 Value::String(_) => val,
121 _ => coersion_err!(val, ty.clone()),
122 },
123 Type::Object => val,
124 Type::AnonymousStruct(_) => unimplemented!(),
125 };
126 Ok(val)
127}