Skip to content

Commit 9db2177

Browse files
committed
change Variant serde (de|)serialization
1 parent e68e1c0 commit 9db2177

File tree

3 files changed

+206
-1
lines changed

3 files changed

+206
-1
lines changed

Cargo.lock

Lines changed: 117 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rust/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ serde_crate = { workspace = true, optional = true }
2020

2121
[dev-dependencies]
2222
amplify = { workspace = true, features = ["proc_attr", "hex"] }
23+
ciborium = "0.2.2"
24+
serde_json = "1.0.140"
25+
serde_yaml = "0.9.34"
2326
strict_encoding_test = { path = "./test_helpers" }
2427

2528
[target.'cfg(target_arch = "wasm32")'.dependencies]

rust/src/util.rs

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,67 @@ impl Display for Sizing {
8484
}
8585

8686
#[derive(Clone, Eq, Debug)]
87-
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))]
8887
pub struct Variant {
8988
pub name: VariantName,
9089
pub tag: u8,
9190
}
9291
impl_strict_struct!(Variant, STRICT_TYPES_LIB; name, tag);
9392

93+
#[cfg(feature = "serde")]
94+
mod _serde {
95+
use std::str::FromStr;
96+
97+
use serde_crate::ser::SerializeStruct;
98+
use serde_crate::{Deserialize, Deserializer, Serialize, Serializer};
99+
100+
use super::*;
101+
102+
impl Serialize for Variant {
103+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
104+
where S: Serializer {
105+
if serializer.is_human_readable() {
106+
serializer.serialize_str(&format!("{}:{}", self.name, self.tag))
107+
} else {
108+
let mut s = serializer.serialize_struct("Variant", 2)?;
109+
s.serialize_field("name", &self.name)?;
110+
s.serialize_field("tag", &self.tag)?;
111+
s.end()
112+
}
113+
}
114+
}
115+
116+
impl<'de> Deserialize<'de> for Variant {
117+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
118+
where D: Deserializer<'de> {
119+
if deserializer.is_human_readable() {
120+
let s = String::deserialize(deserializer)?;
121+
let parts: Vec<&str> = s.split(':').collect();
122+
if parts.len() != 2 {
123+
return Err(serde::de::Error::custom(format!(
124+
"Invalid variant format: '{}'. Expected 'name:tag'",
125+
s
126+
)));
127+
}
128+
let name = VariantName::from_str(parts[0]).map_err(|e| {
129+
serde::de::Error::custom(format!("Invalid variant name: {}", e))
130+
})?;
131+
let tag = parts[1]
132+
.parse::<u8>()
133+
.map_err(|e| serde::de::Error::custom(format!("Invalid variant tag: {}", e)))?;
134+
Ok(Variant { name, tag })
135+
} else {
136+
#[cfg_attr(feature = "serde", derive(Deserialize), serde(crate = "serde_crate"))]
137+
struct VariantFields {
138+
name: VariantName,
139+
tag: u8,
140+
}
141+
let VariantFields { name, tag } = VariantFields::deserialize(deserializer)?;
142+
Ok(Variant { name, tag })
143+
}
144+
}
145+
}
146+
}
147+
94148
impl Variant {
95149
pub fn named(tag: u8, name: VariantName) -> Variant { Variant { name, tag } }
96150

@@ -138,3 +192,34 @@ impl Display for Variant {
138192
Ok(())
139193
}
140194
}
195+
196+
#[cfg(test)]
197+
mod test {
198+
#![allow(unused)]
199+
200+
use std::io::Cursor;
201+
202+
use crate::*;
203+
204+
#[cfg(feature = "serde")]
205+
#[test]
206+
fn variant_serde_roundtrip() {
207+
let variant_orig = Variant::strict_dumb();
208+
209+
// CBOR
210+
let mut buf = Vec::new();
211+
ciborium::into_writer(&variant_orig, &mut buf).unwrap();
212+
let variant_post: Variant = ciborium::from_reader(Cursor::new(&buf)).unwrap();
213+
assert_eq!(variant_orig, variant_post);
214+
215+
// JSON
216+
let variant_str = serde_json::to_string(&variant_orig).unwrap();
217+
let variant_post: Variant = serde_json::from_str(&variant_str).unwrap();
218+
assert_eq!(variant_orig, variant_post);
219+
220+
// YAML
221+
let variant_str = serde_yaml::to_string(&variant_orig).unwrap();
222+
let variant_post: Variant = serde_yaml::from_str(&variant_str).unwrap();
223+
assert_eq!(variant_orig, variant_post);
224+
}
225+
}

0 commit comments

Comments
 (0)