1use serde::de::DeserializeOwned;
2
3use crate::error::{DeserializeError, ProcedureError};
4
5pub enum DynInput {
13 Deserializer(Box<dyn erased_serde::Deserializer<'static> + Send>),
15 Value(serde_json::Value),
17}
18
19impl DynInput {
20 pub fn from_value(value: serde_json::Value) -> Self {
22 DynInput::Value(value)
23 }
24
25 pub fn deserialize<T: DeserializeOwned>(self) -> Result<T, ProcedureError> {
27 match self {
28 DynInput::Deserializer(mut de) => erased_serde::deserialize(&mut *de)
29 .map_err(|e| ProcedureError::Deserialize(DeserializeError::from(e))),
30 DynInput::Value(v) => serde_json::from_value(v)
31 .map_err(|e| ProcedureError::Deserialize(DeserializeError::from(e))),
32 }
33 }
34
35 pub fn as_value(&self) -> Option<&serde_json::Value> {
37 match self {
38 DynInput::Value(v) => Some(v),
39 DynInput::Deserializer(_) => None,
40 }
41 }
42
43 pub fn materialize(self) -> Result<DynInput, ProcedureError> {
48 match self {
49 DynInput::Value(_) => Ok(self),
50 DynInput::Deserializer(mut de) => {
51 let v: serde_json::Value = erased_serde::deserialize(&mut *de)
52 .map_err(|e| ProcedureError::Deserialize(DeserializeError::from(e)))?;
53 Ok(DynInput::Value(v))
54 }
55 }
56 }
57}
58
59impl std::fmt::Debug for DynInput {
60 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61 match self {
62 DynInput::Deserializer(_) => f.debug_tuple("DynInput::Deserializer").finish(),
63 DynInput::Value(v) => f.debug_tuple("DynInput::Value").field(v).finish(),
64 }
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71 use serde::Deserialize;
72
73 #[derive(Debug, Deserialize, PartialEq)]
74 struct TestInput {
75 name: String,
76 age: u32,
77 }
78
79 #[test]
80 fn deserialize_from_value() {
81 let input = DynInput::from_value(serde_json::json!({"name": "Alice", "age": 30}));
82 let result: TestInput = input.deserialize().unwrap();
83 assert_eq!(
84 result,
85 TestInput {
86 name: "Alice".into(),
87 age: 30
88 }
89 );
90 }
91
92 #[test]
93 fn deserialize_from_value_type_mismatch() {
94 let input = DynInput::from_value(serde_json::json!({"wrong": "fields"}));
95 let result = input.deserialize::<TestInput>();
96 assert!(result.is_err());
97 assert!(matches!(
98 result.unwrap_err(),
99 ProcedureError::Deserialize(_)
100 ));
101 }
102
103 #[test]
104 fn as_value_on_value_variant() {
105 let input = DynInput::from_value(serde_json::json!(42));
106 assert_eq!(input.as_value(), Some(&serde_json::json!(42)));
107 }
108
109 #[test]
110 fn materialize_value_is_noop() {
111 let input = DynInput::from_value(serde_json::json!({"key": "value"}));
112 let materialized = input.materialize().unwrap();
113 assert_eq!(
114 materialized.as_value(),
115 Some(&serde_json::json!({"key": "value"}))
116 );
117 }
118
119 #[test]
120 fn debug_value_variant() {
121 let input = DynInput::from_value(serde_json::json!(42));
122 let debug = format!("{input:?}");
123 assert!(debug.contains("Value"));
124 }
125
126 #[test]
127 fn dyn_input_is_send() {
128 fn assert_send<T: Send>() {}
129 assert_send::<DynInput>();
130 }
131}