1use std::collections::HashMap;
13
14use reifydb_type::{
15 fragment::Fragment,
16 params::Params,
17 value::{
18 Value,
19 blob::Blob,
20 decimal::parse::parse_decimal,
21 identity::IdentityId,
22 temporal::parse::{
23 date::parse_date, datetime::parse_datetime, duration::parse_duration, time::parse_time,
24 },
25 uuid::parse::{parse_uuid4, parse_uuid7},
26 },
27};
28use serde::{Deserialize, Serialize};
29
30#[derive(Debug, Serialize, Deserialize)]
32pub struct WireValue {
33 #[serde(rename = "type")]
34 pub type_name: String,
35 pub value: String,
36}
37
38#[derive(Debug, Serialize, Deserialize)]
44#[serde(untagged)]
45pub enum WireParams {
46 Positional(Vec<WireValue>),
47 Named(HashMap<String, WireValue>),
48}
49
50fn wire_value_to_value(wire: WireValue) -> Result<Value, String> {
51 let v = wire.value.as_str();
52 match wire.type_name.as_str() {
53 "None" => Ok(Value::none()),
54 "Boolean" => v
55 .parse::<bool>()
56 .map(Value::Boolean)
57 .map_err(|e| format!("invalid Boolean value '{}': {}", v, e)),
58 "Float4" => {
59 v.parse::<f32>().map(Value::float4).map_err(|e| format!("invalid Float4 value '{}': {}", v, e))
60 }
61 "Float8" => {
62 v.parse::<f64>().map(Value::float8).map_err(|e| format!("invalid Float8 value '{}': {}", v, e))
63 }
64 "Int1" => v.parse::<i8>().map(Value::Int1).map_err(|e| format!("invalid Int1 value '{}': {}", v, e)),
65 "Int2" => v.parse::<i16>().map(Value::Int2).map_err(|e| format!("invalid Int2 value '{}': {}", v, e)),
66 "Int4" => v.parse::<i32>().map(Value::Int4).map_err(|e| format!("invalid Int4 value '{}': {}", v, e)),
67 "Int8" => v.parse::<i64>().map(Value::Int8).map_err(|e| format!("invalid Int8 value '{}': {}", v, e)),
68 "Int16" => {
69 v.parse::<i128>().map(Value::Int16).map_err(|e| format!("invalid Int16 value '{}': {}", v, e))
70 }
71 "Utf8" => Ok(Value::Utf8(v.to_string())),
72 "Uint1" => v.parse::<u8>().map(Value::Uint1).map_err(|e| format!("invalid Uint1 value '{}': {}", v, e)),
73 "Uint2" => {
74 v.parse::<u16>().map(Value::Uint2).map_err(|e| format!("invalid Uint2 value '{}': {}", v, e))
75 }
76 "Uint4" => {
77 v.parse::<u32>().map(Value::Uint4).map_err(|e| format!("invalid Uint4 value '{}': {}", v, e))
78 }
79 "Uint8" => {
80 v.parse::<u64>().map(Value::Uint8).map_err(|e| format!("invalid Uint8 value '{}': {}", v, e))
81 }
82 "Uint16" => {
83 v.parse::<u128>().map(Value::Uint16).map_err(|e| format!("invalid Uint16 value '{}': {}", v, e))
84 }
85 "Uuid4" => parse_uuid4(Fragment::internal(v))
86 .map(Value::Uuid4)
87 .map_err(|e| format!("invalid Uuid4 value '{}': {:?}", v, e)),
88 "Uuid7" => parse_uuid7(Fragment::internal(v))
89 .map(Value::Uuid7)
90 .map_err(|e| format!("invalid Uuid7 value '{}': {:?}", v, e)),
91 "Date" => parse_date(Fragment::internal(v))
92 .map(Value::Date)
93 .map_err(|e| format!("invalid Date value '{}': {:?}", v, e)),
94 "DateTime" => parse_datetime(Fragment::internal(v))
95 .map(Value::DateTime)
96 .map_err(|e| format!("invalid DateTime value '{}': {:?}", v, e)),
97 "Time" => parse_time(Fragment::internal(v))
98 .map(Value::Time)
99 .map_err(|e| format!("invalid Time value '{}': {:?}", v, e)),
100 "Duration" => parse_duration(Fragment::internal(v))
101 .map(Value::Duration)
102 .map_err(|e| format!("invalid Duration value '{}': {:?}", v, e)),
103 "Blob" => Blob::from_hex(Fragment::internal(v))
104 .map(Value::Blob)
105 .map_err(|e| format!("invalid Blob value '{}': {:?}", v, e)),
106 "Decimal" => parse_decimal(Fragment::internal(v))
107 .map(Value::Decimal)
108 .map_err(|e| format!("invalid Decimal value '{}': {:?}", v, e)),
109 "IdentityId" => parse_uuid7(Fragment::internal(v))
110 .map(|u| Value::IdentityId(IdentityId::new(u)))
111 .map_err(|e| format!("invalid IdentityId value '{}': {:?}", v, e)),
112 _ => Err(format!("unknown type '{}'", wire.type_name)),
113 }
114}
115
116impl WireParams {
117 pub fn into_params(self) -> Result<Params, String> {
118 match self {
119 WireParams::Positional(items) => {
120 let mut values = Vec::with_capacity(items.len());
121 for item in items {
122 values.push(wire_value_to_value(item)?);
123 }
124 Ok(Params::Positional(values))
125 }
126 WireParams::Named(map) => {
127 let mut result = HashMap::with_capacity(map.len());
128 for (key, wire) in map {
129 result.insert(key, wire_value_to_value(wire)?);
130 }
131 Ok(Params::Named(result))
132 }
133 }
134 }
135}