data_anchor_utils/
encoding.rs1#[derive(Debug, thiserror::Error)]
2pub enum DataAnchorEncodingError {
3 #[error("Postcard encoding error: {0}")]
4 Postcard(#[from] postcard::Error),
5
6 #[error("Bincode encoding error: {0}")]
7 Bincode(#[from] bincode::Error),
8
9 #[error("JSON encoding error: {0}")]
10 Json(#[from] serde_json::Error),
11
12 #[cfg(feature = "borsh")]
13 #[error("Borsh encoding error: {0}")]
14 Borsh(#[from] borsh::io::Error),
15}
16
17pub type DataAnchorEncodingResult<T = ()> = Result<T, DataAnchorEncodingError>;
18
19#[cfg(not(feature = "borsh"))]
20mod _no_borsh {
21
22 pub trait Encodable: serde::ser::Serialize {}
23
24 impl<T: serde::ser::Serialize> Encodable for T {}
25
26 pub trait Decodable: serde::de::DeserializeOwned {}
27
28 impl<T: serde::de::DeserializeOwned> Decodable for T {}
29}
30
31#[cfg(not(feature = "borsh"))]
32pub use _no_borsh::*;
33
34#[cfg(feature = "borsh")]
35mod _with_borsh {
36 pub trait Encodable: serde::ser::Serialize + borsh::BorshSerialize {}
37
38 impl<T: serde::ser::Serialize + borsh::BorshSerialize> Encodable for T {}
39
40 pub trait Decodable: serde::de::DeserializeOwned + borsh::BorshDeserialize {}
41
42 impl<T: serde::de::DeserializeOwned + borsh::BorshDeserialize> Decodable for T {}
43}
44
45#[cfg(feature = "borsh")]
46pub use _with_borsh::*;
47
48pub trait DataAnchorEncoding {
49 fn encode<T: Encodable>(&self, data: &T) -> DataAnchorEncodingResult<Vec<u8>>;
50 fn decode<T: Decodable>(&self, data: &[u8]) -> DataAnchorEncodingResult<T>;
51}
52
53#[derive(Debug, Clone, Copy, std::default::Default)]
54pub struct Postcard;
55
56pub use Postcard as Default;
57
58impl DataAnchorEncoding for Postcard {
59 fn encode<T: Encodable>(&self, data: &T) -> DataAnchorEncodingResult<Vec<u8>> {
60 Ok(postcard::to_allocvec(data)?)
61 }
62
63 fn decode<T: Decodable>(&self, data: &[u8]) -> DataAnchorEncodingResult<T> {
64 Ok(postcard::from_bytes(data)?)
65 }
66}
67
68#[derive(Debug, Clone, Copy, std::default::Default)]
69pub struct Bincode;
70
71impl DataAnchorEncoding for Bincode {
72 fn encode<T: Encodable>(&self, data: &T) -> DataAnchorEncodingResult<Vec<u8>> {
73 Ok(bincode::serialize(data)?)
74 }
75
76 fn decode<T: Decodable>(&self, data: &[u8]) -> DataAnchorEncodingResult<T> {
77 Ok(bincode::deserialize(data)?)
78 }
79}
80
81#[derive(Debug, Clone, Copy, std::default::Default)]
82pub struct Json;
83
84impl DataAnchorEncoding for Json {
85 fn encode<T: Encodable>(&self, data: &T) -> DataAnchorEncodingResult<Vec<u8>> {
86 Ok(serde_json::to_vec(data)?)
87 }
88
89 fn decode<T: Decodable>(&self, data: &[u8]) -> DataAnchorEncodingResult<T> {
90 Ok(serde_json::from_slice(data)?)
91 }
92}
93
94#[cfg(feature = "borsh")]
95#[derive(Debug, Clone, Copy, std::default::Default)]
96pub struct Borsh;
97
98#[cfg(feature = "borsh")]
99impl DataAnchorEncoding for Borsh {
100 fn encode<T: Encodable>(&self, data: &T) -> DataAnchorEncodingResult<Vec<u8>> {
101 Ok(borsh::to_vec(data)?)
102 }
103
104 fn decode<T: Decodable>(&self, data: &[u8]) -> DataAnchorEncodingResult<T> {
105 Ok(borsh::from_slice(data)?)
106 }
107}
108
109#[cfg(test)]
110mod tests {
111 use rstest::rstest;
112
113 use super::*;
114
115 #[derive(
116 Debug,
117 PartialEq,
118 serde::Serialize,
119 serde::Deserialize,
120 borsh::BorshSerialize,
121 borsh::BorshDeserialize,
122 )]
123 pub struct TestStruct {
124 pub field1: String,
125 pub field2: u32,
126 }
127
128 #[rstest]
129 #[case::string("Hello, World!".to_string())]
130 #[case::bytes(vec![20, 30])]
131 #[case::tuple((1, 2, 3))]
132 #[case::bool(true)]
133 #[case::json(TestStruct {
134 field1: "Test".to_string(),
135 field2: 42,
136 })]
137 fn test_encoding<T, E>(
138 #[case] data: T,
139 #[values(Default, Postcard, Bincode, Json, Borsh)] encoding: E,
140 ) where
141 T: Encodable + Decodable + PartialEq + std::fmt::Debug,
142 E: DataAnchorEncoding,
143 {
144 let encoded = encoding.encode(&data).unwrap();
145 let decoded: T = encoding.decode(&encoded).unwrap();
146 assert_eq!(data, decoded);
147 }
148}