Skip to content

Commit d48e800

Browse files
committed
feat(rust): primitive and common types
1 parent 20b0fe1 commit d48e800

File tree

14 files changed

+1561
-0
lines changed

14 files changed

+1561
-0
lines changed

schema_salad/rust/salad-core/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ compact_str = { version = "0.9" }
1212
fxhash = { version = "0.2" }
1313
proc-macro2 = { version = "1.0" }
1414
quote = { version = "1.0" }
15+
salad-types = { path = "crates/types" }
1516
serde = { version = "1.0" }
1617
serde_yaml_ng = { version = "0.10" }
1718
syn = { version = "2.0" }
@@ -29,4 +30,5 @@ name = "salad_core"
2930
path = "src/lib.rs"
3031

3132
[dependencies]
33+
salad-types.workspace = true
3234

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
[package]
2+
name = "salad-types"
3+
version = "0.1.0"
4+
license.workspace = true
5+
authors.workspace = true
6+
edition.workspace = true
7+
publish = false
8+
9+
[dependencies]
10+
compact_str = { workspace = true, features = ["serde"] }
11+
fxhash = { workspace = true }
12+
serde = { workspace = true }
13+
14+
[dev-dependencies]
15+
serde_yaml_ng = { workspace = true }
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../LICENSE
Lines changed: 356 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,356 @@
1+
use std::{collections::hash_map, slice};
2+
3+
use compact_str::CompactString;
4+
use serde::de;
5+
6+
use super::{SaladAny, SaladObject};
7+
8+
/// Deserializer for converting SaladAny values into SaladTypes
9+
pub(super) struct SaladAnyDeserializer<'de>(pub &'de SaladAny);
10+
11+
impl<'de> de::Deserializer<'de> for SaladAnyDeserializer<'de> {
12+
type Error = de::value::Error;
13+
14+
fn deserialize_any<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
15+
match self.0 {
16+
SaladAny::Bool(b) => visitor.visit_bool(*b),
17+
SaladAny::Int(i) => visitor.visit_i32(*i),
18+
SaladAny::Long(l) => {
19+
if super::INT_RANGE.contains(l) {
20+
visitor.visit_i32(*l as i32)
21+
} else {
22+
visitor.visit_i64(*l)
23+
}
24+
}
25+
SaladAny::Float(f) => visitor.visit_f32(*f),
26+
SaladAny::Double(d) => {
27+
if super::FLOAT_RANGE.contains(d) {
28+
visitor.visit_f32(*d as f32)
29+
} else {
30+
visitor.visit_f64(*d)
31+
}
32+
}
33+
SaladAny::String(s) => visitor.visit_str(s),
34+
SaladAny::Object(o) => visitor.visit_map(SaladObjectMapAccess::new(o)),
35+
SaladAny::List(l) => visitor.visit_seq(SaladAnyListSeqAccess::new(l)),
36+
}
37+
}
38+
39+
fn deserialize_bool<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
40+
static ERR_MSG: &str = "boolean";
41+
42+
match self.0 {
43+
SaladAny::Bool(b) => visitor.visit_bool(*b),
44+
SaladAny::Int(1) | SaladAny::Long(1) => visitor.visit_bool(true),
45+
SaladAny::Int(0) | SaladAny::Long(0) => visitor.visit_bool(false),
46+
47+
// Errors
48+
SaladAny::Int(i) => Err(de::Error::invalid_type(
49+
de::Unexpected::Signed(*i as i64),
50+
&ERR_MSG,
51+
)),
52+
SaladAny::Long(l) => Err(de::Error::invalid_type(de::Unexpected::Signed(*l), &ERR_MSG)),
53+
SaladAny::Float(f) => Err(de::Error::invalid_type(
54+
de::Unexpected::Float(*f as f64),
55+
&ERR_MSG,
56+
)),
57+
SaladAny::Double(d) => Err(de::Error::invalid_type(de::Unexpected::Float(*d), &ERR_MSG)),
58+
SaladAny::String(s) => Err(de::Error::invalid_type(de::Unexpected::Str(s), &ERR_MSG)),
59+
SaladAny::Object(_) => Err(de::Error::invalid_type(de::Unexpected::Map, &ERR_MSG)),
60+
SaladAny::List(_) => Err(de::Error::invalid_type(de::Unexpected::Seq, &ERR_MSG)),
61+
}
62+
}
63+
64+
fn deserialize_i32<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
65+
static ERR_MSG: &str = "signed integer";
66+
67+
match self.0 {
68+
SaladAny::Int(i) => visitor.visit_i32(*i),
69+
SaladAny::Long(l) if super::INT_RANGE.contains(l) => visitor.visit_i32(*l as i32),
70+
71+
// Errors
72+
SaladAny::Bool(b) => Err(de::Error::invalid_type(de::Unexpected::Bool(*b), &ERR_MSG)),
73+
SaladAny::Long(l) => Err(de::Error::invalid_type(de::Unexpected::Signed(*l), &ERR_MSG)),
74+
SaladAny::Float(f) => Err(de::Error::invalid_type(
75+
de::Unexpected::Float(*f as f64),
76+
&ERR_MSG,
77+
)),
78+
SaladAny::Double(d) => Err(de::Error::invalid_type(de::Unexpected::Float(*d), &ERR_MSG)),
79+
SaladAny::String(s) => Err(de::Error::invalid_type(de::Unexpected::Str(s), &ERR_MSG)),
80+
SaladAny::Object(_) => Err(de::Error::invalid_type(de::Unexpected::Map, &ERR_MSG)),
81+
SaladAny::List(_) => Err(de::Error::invalid_type(de::Unexpected::Seq, &ERR_MSG)),
82+
}
83+
}
84+
85+
fn deserialize_i64<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
86+
static ERR_MSG: &str = "signed long integer";
87+
88+
match self.0 {
89+
SaladAny::Long(l) => visitor.visit_i64(*l),
90+
SaladAny::Int(i) => visitor.visit_i64(*i as i64),
91+
92+
// Errors
93+
SaladAny::Bool(b) => Err(de::Error::invalid_type(de::Unexpected::Bool(*b), &ERR_MSG)),
94+
SaladAny::Float(f) => Err(de::Error::invalid_type(
95+
de::Unexpected::Float(*f as f64),
96+
&ERR_MSG,
97+
)),
98+
SaladAny::Double(d) => Err(de::Error::invalid_type(de::Unexpected::Float(*d), &ERR_MSG)),
99+
SaladAny::String(s) => Err(de::Error::invalid_type(de::Unexpected::Str(s), &ERR_MSG)),
100+
SaladAny::Object(_) => Err(de::Error::invalid_type(de::Unexpected::Map, &ERR_MSG)),
101+
SaladAny::List(_) => Err(de::Error::invalid_type(de::Unexpected::Seq, &ERR_MSG)),
102+
}
103+
}
104+
105+
fn deserialize_f32<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
106+
static ERR_MSG: &str = "float";
107+
108+
match self.0 {
109+
SaladAny::Float(f) => visitor.visit_f32(*f),
110+
SaladAny::Double(d) if super::FLOAT_RANGE.contains(d) => visitor.visit_f32(*d as f32),
111+
112+
// Errors
113+
SaladAny::Bool(b) => Err(de::Error::invalid_type(de::Unexpected::Bool(*b), &ERR_MSG)),
114+
SaladAny::Int(i) => Err(de::Error::invalid_type(
115+
de::Unexpected::Signed(*i as i64),
116+
&ERR_MSG,
117+
)),
118+
SaladAny::Long(l) => Err(de::Error::invalid_type(de::Unexpected::Signed(*l), &ERR_MSG)),
119+
SaladAny::Double(d) => Err(de::Error::invalid_type(de::Unexpected::Float(*d), &ERR_MSG)),
120+
SaladAny::String(s) => Err(de::Error::invalid_type(de::Unexpected::Str(s), &ERR_MSG)),
121+
SaladAny::Object(_) => Err(de::Error::invalid_type(de::Unexpected::Map, &ERR_MSG)),
122+
SaladAny::List(_) => Err(de::Error::invalid_type(de::Unexpected::Seq, &ERR_MSG)),
123+
}
124+
}
125+
126+
fn deserialize_f64<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
127+
static ERR_MSG: &str = "double";
128+
129+
match self.0 {
130+
SaladAny::Double(d) => visitor.visit_f64(*d),
131+
SaladAny::Float(f) => visitor.visit_f64(*f as f64),
132+
133+
// Errors
134+
SaladAny::Bool(b) => Err(de::Error::invalid_type(de::Unexpected::Bool(*b), &ERR_MSG)),
135+
SaladAny::Int(i) => Err(de::Error::invalid_type(
136+
de::Unexpected::Signed(*i as i64),
137+
&ERR_MSG,
138+
)),
139+
SaladAny::Long(l) => Err(de::Error::invalid_type(de::Unexpected::Signed(*l), &ERR_MSG)),
140+
SaladAny::String(s) => Err(de::Error::invalid_type(de::Unexpected::Str(s), &ERR_MSG)),
141+
SaladAny::Object(_) => Err(de::Error::invalid_type(de::Unexpected::Map, &ERR_MSG)),
142+
SaladAny::List(_) => Err(de::Error::invalid_type(de::Unexpected::Seq, &ERR_MSG)),
143+
}
144+
}
145+
146+
fn deserialize_str<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
147+
static ERR_MSG: &str = "UTF-8 string";
148+
149+
match self.0 {
150+
SaladAny::String(s) => visitor.visit_str(s),
151+
152+
// Errors
153+
SaladAny::Bool(b) => Err(de::Error::invalid_type(de::Unexpected::Bool(*b), &ERR_MSG)),
154+
SaladAny::Int(i) => Err(de::Error::invalid_type(
155+
de::Unexpected::Signed(*i as i64),
156+
&ERR_MSG,
157+
)),
158+
SaladAny::Long(l) => Err(de::Error::invalid_type(de::Unexpected::Signed(*l), &ERR_MSG)),
159+
SaladAny::Float(f) => Err(de::Error::invalid_type(
160+
de::Unexpected::Float(*f as f64),
161+
&ERR_MSG,
162+
)),
163+
SaladAny::Double(d) => Err(de::Error::invalid_type(de::Unexpected::Float(*d), &ERR_MSG)),
164+
SaladAny::Object(_) => Err(de::Error::invalid_type(de::Unexpected::Map, &ERR_MSG)),
165+
SaladAny::List(_) => Err(de::Error::invalid_type(de::Unexpected::Seq, &ERR_MSG)),
166+
}
167+
}
168+
169+
fn deserialize_map<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
170+
static ERR_MSG: &str = "key-value map object";
171+
172+
match self.0 {
173+
SaladAny::Object(o) => visitor.visit_map(SaladObjectMapAccess::new(o)),
174+
175+
// Errors
176+
SaladAny::Bool(b) => Err(de::Error::invalid_type(de::Unexpected::Bool(*b), &ERR_MSG)),
177+
SaladAny::Int(i) => Err(de::Error::invalid_type(
178+
de::Unexpected::Signed(*i as i64),
179+
&ERR_MSG,
180+
)),
181+
SaladAny::Long(l) => Err(de::Error::invalid_type(de::Unexpected::Signed(*l), &ERR_MSG)),
182+
SaladAny::Float(f) => Err(de::Error::invalid_type(
183+
de::Unexpected::Float(*f as f64),
184+
&ERR_MSG,
185+
)),
186+
SaladAny::Double(d) => Err(de::Error::invalid_type(de::Unexpected::Float(*d), &ERR_MSG)),
187+
SaladAny::String(s) => Err(de::Error::invalid_type(de::Unexpected::Str(s), &ERR_MSG)),
188+
SaladAny::List(_) => Err(de::Error::invalid_type(de::Unexpected::Seq, &ERR_MSG)),
189+
}
190+
}
191+
192+
fn deserialize_seq<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
193+
static ERR_MSG: &str = "list of primitives/objects";
194+
195+
match self.0 {
196+
SaladAny::List(l) => visitor.visit_seq(SaladAnyListSeqAccess::new(l)),
197+
198+
// Errors
199+
SaladAny::Bool(b) => Err(de::Error::invalid_type(de::Unexpected::Bool(*b), &ERR_MSG)),
200+
SaladAny::Int(i) => Err(de::Error::invalid_type(
201+
de::Unexpected::Signed(*i as i64),
202+
&ERR_MSG,
203+
)),
204+
SaladAny::Long(l) => Err(de::Error::invalid_type(de::Unexpected::Signed(*l), &ERR_MSG)),
205+
SaladAny::Float(f) => Err(de::Error::invalid_type(
206+
de::Unexpected::Float(*f as f64),
207+
&ERR_MSG,
208+
)),
209+
SaladAny::Double(d) => Err(de::Error::invalid_type(de::Unexpected::Float(*d), &ERR_MSG)),
210+
SaladAny::String(s) => Err(de::Error::invalid_type(de::Unexpected::Str(s), &ERR_MSG)),
211+
SaladAny::Object(_) => Err(de::Error::invalid_type(de::Unexpected::Map, &ERR_MSG)),
212+
}
213+
}
214+
215+
// Unimplemented methods with a default implementation
216+
serde::forward_to_deserialize_any! {
217+
i8 i16 u8 u16 u32 u64 char string bytes byte_buf option unit
218+
unit_struct newtype_struct tuple tuple_struct struct enum identifier ignored_any
219+
}
220+
}
221+
222+
/// Map access implementation for SaladObject deserialization
223+
pub(super) struct SaladObjectMapAccess<'de> {
224+
iter: hash_map::Iter<'de, CompactString, SaladAny>,
225+
value: Option<&'de SaladAny>,
226+
}
227+
228+
impl<'de> SaladObjectMapAccess<'de> {
229+
pub fn new(obj: &'de SaladObject) -> Self {
230+
Self {
231+
iter: obj.map.iter(),
232+
value: None,
233+
}
234+
}
235+
}
236+
237+
impl<'de> de::Deserializer<'de> for SaladObjectMapAccess<'de> {
238+
type Error = de::value::Error;
239+
240+
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
241+
where
242+
V: de::Visitor<'de>,
243+
{
244+
visitor.visit_map(self)
245+
}
246+
247+
fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
248+
where
249+
V: de::Visitor<'de>,
250+
{
251+
visitor.visit_map(self)
252+
}
253+
254+
// Forward all other methods to deserialize_any
255+
serde::forward_to_deserialize_any! {
256+
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
257+
byte_buf option unit unit_struct newtype_struct seq tuple
258+
tuple_struct struct enum identifier ignored_any
259+
}
260+
}
261+
262+
impl<'de> de::MapAccess<'de> for SaladObjectMapAccess<'de> {
263+
type Error = de::value::Error;
264+
265+
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
266+
where
267+
K: de::DeserializeSeed<'de>,
268+
{
269+
match self.iter.next() {
270+
Some((k, v)) => {
271+
self.value = Some(v);
272+
seed.deserialize(CompactStringDeserializer(k)).map(Some)
273+
}
274+
None => {
275+
self.value = None;
276+
Ok(None)
277+
}
278+
}
279+
}
280+
281+
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
282+
where
283+
V: de::DeserializeSeed<'de>,
284+
{
285+
let value = self.value.ok_or_else(|| de::Error::custom("value is missing"))?;
286+
seed.deserialize(SaladAnyDeserializer(value))
287+
}
288+
}
289+
290+
/// Deserializer for CompactString values
291+
struct CompactStringDeserializer<'de>(&'de CompactString);
292+
293+
impl<'de> de::Deserializer<'de> for CompactStringDeserializer<'de> {
294+
type Error = de::value::Error;
295+
296+
fn deserialize_any<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
297+
visitor.visit_borrowed_str(self.0.as_str())
298+
}
299+
300+
fn deserialize_str<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
301+
visitor.visit_borrowed_str(self.0.as_str())
302+
}
303+
304+
fn deserialize_string<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
305+
visitor.visit_string(self.0.to_string())
306+
}
307+
308+
fn deserialize_bytes<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
309+
visitor.visit_borrowed_bytes(self.0.as_bytes())
310+
}
311+
312+
fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Self::Error>
313+
where
314+
V: de::Visitor<'de>,
315+
{
316+
visitor.visit_byte_buf(self.0.as_bytes().to_vec())
317+
}
318+
319+
fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error>
320+
where
321+
V: de::Visitor<'de>,
322+
{
323+
visitor.visit_borrowed_str(self.0.as_str())
324+
}
325+
326+
// Forward all other methods to deserialize_any
327+
serde::forward_to_deserialize_any! {
328+
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char option unit unit_struct
329+
newtype_struct seq tuple tuple_struct map struct enum ignored_any
330+
}
331+
}
332+
333+
/// Sequence access implementation for SaladAny list deserialization
334+
struct SaladAnyListSeqAccess<'de> {
335+
iter: slice::Iter<'de, SaladAny>,
336+
}
337+
338+
impl<'de> SaladAnyListSeqAccess<'de> {
339+
pub fn new(list: &'de [SaladAny]) -> Self {
340+
Self { iter: list.iter() }
341+
}
342+
}
343+
344+
impl<'de> de::SeqAccess<'de> for SaladAnyListSeqAccess<'de> {
345+
type Error = de::value::Error;
346+
347+
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
348+
where
349+
T: de::DeserializeSeed<'de>,
350+
{
351+
self.iter
352+
.next()
353+
.map(|v| seed.deserialize(SaladAnyDeserializer(v)))
354+
.transpose()
355+
}
356+
}

0 commit comments

Comments
 (0)