bc_ur/
ur_codable.rs

1use crate::{URDecodable, UREncodable};
2
3/// A type that can be encoded to and decoded from a UR.
4pub trait URCodable {}
5
6impl<T> URCodable for T where T: UREncodable + URDecodable {}
7
8#[cfg(test)]
9mod tests {
10    use dcbor::prelude::*;
11
12    use super::*;
13
14    #[derive(Debug, PartialEq)]
15    struct Test {
16        s: String,
17    }
18
19    impl Test {
20        fn new(s: &str) -> Self { Self { s: s.to_string() } }
21    }
22
23    impl CBORTagged for Test {
24        fn cbor_tags() -> Vec<Tag> { vec![Tag::new(24, "leaf")] }
25    }
26
27    impl From<Test> for CBOR {
28        // This ensures that asking for the CBOR for this type will always
29        // return a tagged CBOR value.
30        fn from(value: Test) -> Self { value.tagged_cbor() }
31    }
32
33    impl CBORTaggedEncodable for Test {
34        // This is the core of the CBOR encoding for this type. It is the
35        // untagged CBOR encoding.
36        fn untagged_cbor(&self) -> CBOR { self.s.clone().into() }
37    }
38
39    impl TryFrom<CBOR> for Test {
40        type Error = dcbor::Error;
41
42        // This ensures that asking for the CBOR for this type will always
43        // expect a tagged CBOR value.
44        fn try_from(cbor: CBOR) -> dcbor::Result<Self> {
45            Self::from_tagged_cbor(cbor)
46        }
47    }
48
49    impl CBORTaggedDecodable for Test {
50        // This is the core of the CBOR decoding for this type. It is the
51        // untagged CBOR decoding.
52        fn from_untagged_cbor(cbor: CBOR) -> dcbor::Result<Self> {
53            let s: String = cbor.try_into()?;
54            Ok(Self::new(&s))
55        }
56    }
57
58    #[test]
59    fn test_ur_codable() {
60        let test = Test::new("test");
61        let ur = test.ur();
62        let ur_string = ur.string();
63        assert_eq!(ur_string, "ur:leaf/iejyihjkjygupyltla");
64        let test2 = Test::from_ur_string(ur_string).unwrap();
65        assert_eq!(test.s, test2.s);
66    }
67}