+89
-4
crates/jacquard-common/src/opt_serde_bytes_helper.rs
+89
-4
crates/jacquard-common/src/opt_serde_bytes_helper.rs
···
1
1
//! Custom serde helpers for bytes::Bytes using serde_bytes
2
2
3
+
use base64::{
4
+
Engine,
5
+
prelude::{BASE64_STANDARD, BASE64_STANDARD_NO_PAD, BASE64_URL_SAFE, BASE64_URL_SAFE_NO_PAD},
6
+
};
3
7
use bytes::Bytes;
4
-
use serde::{Deserializer, Serializer};
8
+
use core::fmt;
9
+
use serde::{
10
+
Deserializer, Serializer,
11
+
de::{self, MapAccess, Visitor},
12
+
};
5
13
6
14
/// Serialize Bytes as a CBOR byte string
7
15
pub fn serialize<S>(bytes: &Option<Bytes>, serializer: S) -> Result<S::Ok, S::Error>
···
9
17
S: Serializer,
10
18
{
11
19
if let Some(bytes) = bytes {
12
-
serde_bytes::serialize(bytes.as_ref(), serializer)
20
+
if serializer.is_human_readable() {
21
+
// JSON: {"$bytes": "base64 string"}
22
+
use serde::ser::SerializeMap;
23
+
let mut map = serializer.serialize_map(Some(1))?;
24
+
map.serialize_entry("$bytes", &BASE64_STANDARD.encode(bytes))?;
25
+
map.end()
26
+
} else {
27
+
// CBOR: raw bytes
28
+
serde_bytes::serialize(bytes.as_ref(), serializer)
29
+
}
13
30
} else {
14
31
serializer.serialize_none()
15
32
}
···
20
37
where
21
38
D: Deserializer<'de>,
22
39
{
23
-
let vec: Option<Vec<u8>> = serde_bytes::deserialize(deserializer)?;
24
-
Ok(vec.map(Bytes::from))
40
+
if deserializer.is_human_readable() {
41
+
Ok(deserializer.deserialize_map(OptBytesVisitor)?)
42
+
} else {
43
+
let vec: Option<Vec<u8>> = serde_bytes::deserialize(deserializer)?;
44
+
Ok(vec.map(Bytes::from))
45
+
}
46
+
}
47
+
48
+
struct OptBytesVisitor;
49
+
50
+
impl<'de> Visitor<'de> for OptBytesVisitor {
51
+
type Value = Option<Bytes>;
52
+
53
+
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
54
+
formatter.write_str("a base64-encoded string")
55
+
}
56
+
57
+
fn visit_none<E>(self) -> Result<Self::Value, E>
58
+
where
59
+
E: de::Error,
60
+
{
61
+
Ok(None)
62
+
}
63
+
64
+
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
65
+
where
66
+
D: Deserializer<'de>,
67
+
{
68
+
let vec: Vec<u8> = serde_bytes::deserialize(deserializer)?;
69
+
Ok(Some(Bytes::from(vec)))
70
+
}
71
+
72
+
fn visit_unit<E>(self) -> Result<Self::Value, E> {
73
+
Ok(None)
74
+
}
75
+
76
+
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
77
+
where
78
+
A: MapAccess<'de>,
79
+
{
80
+
let mut bytes = None;
81
+
82
+
while let Some(key) = map.next_key()? {
83
+
match key {
84
+
"$bytes" => {
85
+
if bytes.is_some() {
86
+
return Err(de::Error::duplicate_field("$bytes"));
87
+
}
88
+
let bytes_str: String = map.next_value()?;
89
+
// First one should just work. rest are insurance.
90
+
bytes = if let Ok(bytes) = BASE64_STANDARD.decode(&bytes_str) {
91
+
Some(Bytes::from_owner(bytes))
92
+
} else if let Ok(bytes) = BASE64_STANDARD_NO_PAD.decode(&bytes_str) {
93
+
Some(Bytes::from_owner(bytes))
94
+
} else if let Ok(bytes) = BASE64_URL_SAFE.decode(&bytes_str) {
95
+
Some(Bytes::from_owner(bytes))
96
+
} else if let Ok(bytes) = BASE64_URL_SAFE_NO_PAD.decode(&bytes_str) {
97
+
Some(Bytes::from_owner(bytes))
98
+
} else {
99
+
return Err(de::Error::custom("invalid base64 string"));
100
+
}
101
+
}
102
+
_ => {
103
+
return Err(de::Error::unknown_field(key, &["$bytes"]));
104
+
}
105
+
}
106
+
}
107
+
108
+
Ok(bytes)
109
+
}
25
110
}
+71
-4
crates/jacquard-common/src/serde_bytes_helper.rs
+71
-4
crates/jacquard-common/src/serde_bytes_helper.rs
···
1
1
//! Custom serde helpers for bytes::Bytes using serde_bytes
2
2
3
+
use core::fmt;
4
+
5
+
use base64::{
6
+
Engine,
7
+
prelude::{BASE64_STANDARD, BASE64_STANDARD_NO_PAD, BASE64_URL_SAFE, BASE64_URL_SAFE_NO_PAD},
8
+
};
3
9
use bytes::Bytes;
4
-
use serde::{Deserializer, Serializer};
10
+
use serde::{
11
+
Deserializer, Serializer,
12
+
de::{self, MapAccess, Visitor},
13
+
};
5
14
6
15
/// Serialize Bytes as a CBOR byte string
7
16
pub fn serialize<S>(bytes: &Bytes, serializer: S) -> Result<S::Ok, S::Error>
8
17
where
9
18
S: Serializer,
10
19
{
11
-
serde_bytes::serialize(bytes.as_ref(), serializer)
20
+
if serializer.is_human_readable() {
21
+
// JSON: {"$bytes": "base64 string"}
22
+
use serde::ser::SerializeMap;
23
+
let mut map = serializer.serialize_map(Some(1))?;
24
+
map.serialize_entry("$bytes", &BASE64_STANDARD.encode(bytes))?;
25
+
map.end()
26
+
} else {
27
+
// CBOR: raw bytes
28
+
serde_bytes::serialize(bytes.as_ref(), serializer)
29
+
}
12
30
}
13
31
14
32
/// Deserialize Bytes from a CBOR byte string
···
16
34
where
17
35
D: Deserializer<'de>,
18
36
{
19
-
let vec: Vec<u8> = serde_bytes::deserialize(deserializer)?;
20
-
Ok(Bytes::from(vec))
37
+
if deserializer.is_human_readable() {
38
+
Ok(deserializer.deserialize_map(BytesVisitor)?)
39
+
} else {
40
+
let vec: Vec<u8> = serde_bytes::deserialize(deserializer)?;
41
+
Ok(Bytes::from(vec))
42
+
}
43
+
}
44
+
45
+
struct BytesVisitor;
46
+
47
+
impl<'de> Visitor<'de> for BytesVisitor {
48
+
type Value = Bytes;
49
+
50
+
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
51
+
formatter.write_str("a base64-encoded string")
52
+
}
53
+
54
+
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
55
+
where
56
+
A: MapAccess<'de>,
57
+
{
58
+
let mut bytes = None;
59
+
60
+
while let Some(key) = map.next_key()? {
61
+
match key {
62
+
"$bytes" => {
63
+
if bytes.is_some() {
64
+
return Err(de::Error::duplicate_field("$bytes"));
65
+
}
66
+
let bytes_str: String = map.next_value()?;
67
+
// First one should just work. rest are insurance.
68
+
bytes = if let Ok(bytes) = BASE64_STANDARD.decode(&bytes_str) {
69
+
Some(Bytes::from_owner(bytes))
70
+
} else if let Ok(bytes) = BASE64_STANDARD_NO_PAD.decode(&bytes_str) {
71
+
Some(Bytes::from_owner(bytes))
72
+
} else if let Ok(bytes) = BASE64_URL_SAFE.decode(&bytes_str) {
73
+
Some(Bytes::from_owner(bytes))
74
+
} else if let Ok(bytes) = BASE64_URL_SAFE_NO_PAD.decode(&bytes_str) {
75
+
Some(Bytes::from_owner(bytes))
76
+
} else {
77
+
return Err(de::Error::custom("invalid base64 string"));
78
+
}
79
+
}
80
+
_ => {
81
+
return Err(de::Error::unknown_field(key, &["$bytes"]));
82
+
}
83
+
}
84
+
}
85
+
86
+
bytes.ok_or_else(|| de::Error::missing_field("$bytes"))
87
+
}
21
88
}
+6
-4
crates/jacquard-lexicon/src/codegen/structs.rs
+6
-4
crates/jacquard-lexicon/src/codegen/structs.rs
···
294
294
nsid: &str,
295
295
parent_type_name: &str,
296
296
obj: &LexObject<'static>,
297
-
is_builder: bool,
297
+
_is_builder: bool,
298
298
) -> Result<TokenStream> {
299
299
let required = obj.required.as_ref().map(|r| r.as_slice()).unwrap_or(&[]);
300
+
let nullable = obj.nullable.as_ref().map(|n| n.as_slice()).unwrap_or(&[]);
300
301
301
302
let mut fields = Vec::new();
302
303
for (field_name, field_type) in &obj.properties {
303
304
let is_required = required.contains(field_name);
305
+
let is_nullable = nullable.contains(field_name);
304
306
let field_tokens = self.generate_field(
305
307
nsid,
306
308
parent_type_name,
307
309
field_name,
308
310
field_type,
309
311
is_required,
310
-
is_builder,
312
+
is_nullable,
311
313
)?;
312
314
fields.push(field_tokens);
313
315
}
···
323
325
field_name: &str,
324
326
field_type: &LexObjectProperty<'static>,
325
327
is_required: bool,
326
-
_is_builder: bool,
328
+
is_nullable: bool,
327
329
) -> Result<TokenStream> {
328
330
if field_name.is_empty() {
329
331
eprintln!(
···
337
339
self.property_to_rust_type(nsid, parent_type_name, field_name, field_type)?;
338
340
let needs_lifetime = self.property_needs_lifetime(field_type);
339
341
340
-
let rust_type = if is_required {
342
+
let rust_type = if is_required && !is_nullable {
341
343
rust_type
342
344
} else {
343
345
quote! { std::option::Option<#rust_type> }