dcbor/
cbor_codable.rs

1import_stdlib!();
2
3use crate::CBOR;
4
5/// # CBOR Encoding and Decoding Traits
6///
7/// These traits provide functionality for converting between Rust types and CBOR data.
8/// They form the foundation of the dCBOR serialization infrastructure.
9///
10/// The main traits are:
11///
12/// - `CBOREncodable`: For types that can be encoded to CBOR
13/// - `CBORDecodable`: For types that can be decoded from CBOR
14/// - `CBORCodable`: For types that can do both (a combination of the above)
15///
16/// These traits allow for ergonomic conversions using Rust's type system and
17/// enable seamless integration with dCBOR's deterministic encoding rules.
18/// A trait for types that can be encoded to CBOR.
19///
20/// This trait is automatically implemented for any type that implements `Into<CBOR>` and `Clone`.
21/// It provides convenient methods for converting instances into CBOR objects and binary data.
22///
23/// ## Example
24///
25/// ```
26/// use dcbor::prelude::*;
27///
28/// // Custom type that implements Into<CBOR>
29/// #[derive(Clone)]
30/// struct Person {
31///     name: String,
32///     age: u8,
33/// }
34///
35/// // Implement conversion to CBOR
36/// impl From<Person> for CBOR {
37///     fn from(person: Person) -> Self {
38///         let mut map = Map::new();
39///         map.insert("name", person.name);
40///         map.insert("age", person.age);
41///         map.into()
42///     }
43/// }
44///
45/// // The CBOREncodable trait is automatically implemented
46/// let person = Person { name: "Alice".to_string(), age: 30 };
47/// 
48/// // Convert to CBOR with to_cbor()
49/// let cbor = person.to_cbor();
50/// 
51/// // Convert directly to binary CBOR data
52/// let data = person.to_cbor_data();
53/// ```
54pub trait CBOREncodable: Into<CBOR> + Clone {
55    /// Converts this value to a CBOR object.
56    ///
57    /// This is a convenience method that avoids consuming the original value.
58    fn to_cbor(&self) -> CBOR {
59        self.clone().into()
60    }
61
62    /// Converts this value directly to binary CBOR data.
63    ///
64    /// This is a shorthand for `self.to_cbor().to_cbor_data()`.
65    fn to_cbor_data(&self) -> Vec<u8> {
66        self.to_cbor().to_cbor_data()
67    }
68}
69
70impl<T> CBOREncodable for T where T: Into<CBOR> + Clone { }
71
72/// A trait for types that can be decoded from CBOR.
73///
74/// This trait is automatically implemented for any type that implements `TryFrom<CBOR>`.
75/// It serves as a marker trait to indicate that a type supports being created from CBOR data.
76///
77/// ## Example
78///
79/// ```no_run
80/// use dcbor::prelude::*;
81/// use anyhow::{Result, bail};
82///
83/// // Custom type that implements TryFrom<CBOR>
84/// struct Person {
85///     name: String,
86///     age: u8,
87/// }
88///
89/// // Implement conversion from CBOR
90/// impl TryFrom<CBOR> for Person {
91///     type Error = anyhow::Error;
92///
93///     fn try_from(cbor: CBOR) -> Result<Self> {
94///         if let CBORCase::Map(map) = cbor.into_case() {
95///             let name: String = map.extract("name")?;
96///             let age: u8 = map.extract("age")?;
97///             Ok(Person { name, age })
98///         } else {
99///             bail!("Expected a CBOR map")
100///         }
101///     }
102/// }
103///
104/// // The CBORDecodable trait is automatically implemented
105/// // Convert a CBOR object to our type
106/// 
107/// // Create a sample CBOR map
108/// let mut map = Map::new();
109/// map.insert("name", "Alice");
110/// map.insert("age", 42);
111/// let cbor = map.to_cbor();
112/// 
113/// // Parse from CBOR to our type
114/// let person: Person = cbor.try_into().unwrap();
115/// ```
116pub trait CBORDecodable: TryFrom<CBOR> { }
117
118impl<T> CBORDecodable for T where T: TryFrom<CBOR> { }
119
120/// A trait for types that can be both encoded to and decoded from CBOR.
121///
122/// This trait is automatically implemented for any type that implements both
123/// `CBOREncodable` and `CBORDecodable`. It serves as a convenience marker trait
124/// to indicate full CBOR serialization support.
125///
126/// ## Example
127///
128/// ```
129/// use dcbor::prelude::*;
130/// use anyhow::{Result, bail};
131///
132/// // Custom type that implements both conversion directions
133/// #[derive(Clone)]
134/// struct Person {
135///     name: String,
136///     age: u8,
137/// }
138///
139/// // Implement conversion to CBOR
140/// impl From<Person> for CBOR {
141///     fn from(person: Person) -> Self {
142///         let mut map = Map::new();
143///         map.insert("name", person.name);
144///         map.insert("age", person.age);
145///         map.into()
146///     }
147/// }
148///
149/// // Implement conversion from CBOR
150/// impl TryFrom<CBOR> for Person {
151///     type Error = anyhow::Error;
152///
153///     fn try_from(cbor: CBOR) -> Result<Self> {
154///         if let CBORCase::Map(map) = cbor.into_case() {
155///             let name: String = map.extract("name")?;
156///             let age: u8 = map.extract("age")?;
157///             Ok(Person { name, age })
158///         } else {
159///             bail!("Expected a CBOR map")
160///         }
161///     }
162/// }
163///
164/// // Person now automatically implements CBORCodable
165/// let person = Person { name: "Alice".to_string(), age: 30 };
166/// let cbor = person.to_cbor(); // Using CBOREncodable
167///
168/// // Create a round-trip copy
169/// let person_copy: Person = cbor.try_into().unwrap(); // Using CBORDecodable
170/// ```
171pub trait CBORCodable { }
172
173impl<T> CBORCodable for T where T: CBORDecodable + CBOREncodable { }