1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
use serde::de::{Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer};
use serde_cbor::tags::Tagged;
use serde_cbor::Value;
use serde_derive::{Deserialize, Serialize};
use std::error::Error;
/// https://tools.ietf.org/html/rfc7049#section-2.4.1
#[derive(Debug, PartialEq)]
struct Date(String);
impl Serialize for Date {
fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
Tagged::new(Some(0), &self.0).serialize(s)
}
}
impl<'de> Deserialize<'de> for Date {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let tagged = Tagged::<String>::deserialize(deserializer)?;
match tagged.tag {
Some(0) | None => Ok(Date(tagged.value)),
Some(_) => Err(serde::de::Error::custom("unexpected tag")),
}
}
}
/// https://tools.ietf.org/html/rfc7049#section-2.4.4.3
#[derive(Debug, PartialEq)]
struct Uri(String);
impl Serialize for Uri {
fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
Tagged::new(Some(32), &self.0).serialize(s)
}
}
impl<'de> Deserialize<'de> for Uri {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let tagged = Tagged::<String>::deserialize(deserializer)?;
match tagged.tag {
// allow deserialization even if there is no tag. Allows roundtrip via other formats such as json
Some(0) | None => Ok(Uri(tagged.value)),
Some(_) => Err(serde::de::Error::custom("unexpected tag")),
}
}
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct Bookmark {
title: String,
link: Uri,
created: Date,
}
fn main() -> Result<(), Box<dyn Error>> {
let bookmark = Bookmark {
title: "The Example Domain".into(),
link: Uri("http://example.org/".into()),
created: Date("2003-12-13T18:30:02Z".into()),
};
// serialize the struct to bytes
let bytes1 = serde_cbor::to_vec(&bookmark)?;
// deserialize to a serde_cbor::Value
let value1: Value = serde_cbor::from_slice(&bytes1)?;
println!("{:?}", value1);
// serialize the value to bytes
let bytes2 = serde_cbor::to_vec(&value1)?;
// deserialize to a serde_cbor::Value
let value2: Value = serde_cbor::from_slice(&bytes2)?;
println!("{:?}", value2);
// deserialize to a Bookmark
let result: Bookmark = serde_cbor::from_slice(&bytes2)?;
// check that the roundtrip was successful
assert_eq!(value1, value2);
assert_eq!(bookmark, result);
// check that going via a format that does not support tags does work
// let json = serde_json::to_vec(&bookmark)?;
// let result: Bookmark = serde_json::from_slice(&json)?;
// assert_eq!(bookmark, result);
Ok(())
}
|