1use crate::Num;
2use bincode::{
3 de::{BorrowDecoder, Decoder},
4 enc::Encoder,
5 error::{DecodeError, EncodeError},
6 BorrowDecode, Decode, Encode,
7};
8
9impl<const N: i64> Encode for Num<N> {
10 fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
11 Encode::encode(&N, encoder)?;
12 Ok(())
13 }
14}
15
16impl<const N: i64, Context> Decode<Context> for Num<N> {
17 fn decode<D: Decoder<Context = Context>>(decoder: &mut D) -> Result<Self, DecodeError> {
18 let n: i64 = bincode::Decode::<Context>::decode(decoder)?;
19 if n != N {
20 return Err(DecodeError::OtherString(format!("not {N}")));
21 }
22 Ok(Default::default())
23 }
24}
25
26impl<'de, const N: i64, Context> BorrowDecode<'de, Context> for Num<N> {
27 fn borrow_decode<D: BorrowDecoder<'de, Context = Context>>(
28 decoder: &mut D,
29 ) -> Result<Self, DecodeError> {
30 let n: i64 = bincode::BorrowDecode::<Context>::borrow_decode(decoder)?;
31 if n != N {
32 return Err(DecodeError::OtherString(format!("not {N}")));
33 }
34 Ok(Default::default())
35 }
36}
37
38#[cfg(test)]
39mod tests {
40 use crate::Num;
41 use bincode::{Decode as BincodeDecode, Encode as BincodeEncode};
42
43 #[test]
44 fn test_bincode_typed_num() {
45 #[derive(Debug, PartialEq, Eq, BincodeEncode, BincodeDecode)]
46 struct BincodeConfig<const V: i64> {
47 version: Num<V>,
48 data: String,
49 }
50
51 const TEST_VERSION: i64 = 42;
52 const ANOTHER_VERSION: i64 = 43;
53
54 let config_correct_version = BincodeConfig::<TEST_VERSION> {
55 version: Num,
56 data: "test_data".to_string(),
57 };
58
59 let bincode_config = bincode::config::standard();
60
61 let encoded_vec = bincode::encode_to_vec(&config_correct_version, bincode_config).unwrap();
62
63 let (decoded_correct, len_correct): (BincodeConfig<TEST_VERSION>, usize) =
64 bincode::decode_from_slice(&encoded_vec, bincode_config).unwrap();
65 assert_eq!(decoded_correct, config_correct_version);
66 assert_eq!(len_correct, encoded_vec.len());
67
68 let decode_result_wrong_version: Result<(BincodeConfig<ANOTHER_VERSION>, usize), _> =
69 bincode::decode_from_slice(&encoded_vec, bincode_config);
70
71 assert!(decode_result_wrong_version.is_err());
72 if let Err(e) = decode_result_wrong_version {
73 match e {
74 bincode::error::DecodeError::OtherString(s) => {
75 assert_eq!(s, format!("not {}", ANOTHER_VERSION));
76 }
77 _ => panic!("Expected OtherString error, got {:?}", e),
78 }
79 }
80 }
81
82 #[test]
83 fn test_bincode_typed_num_negative() {
84 #[derive(Debug, PartialEq, Eq, BincodeEncode, BincodeDecode)]
85 struct BincodeConfigNegative<const V: i64> {
86 version: Num<V>,
87 payload: Vec<u8>,
88 }
89
90 const TEST_NEGATIVE_VERSION: i64 = -5;
91 const ANOTHER_NEGATIVE_VERSION: i64 = -6;
92
93 let config_correct_negative_version = BincodeConfigNegative::<TEST_NEGATIVE_VERSION> {
94 version: Num,
95 payload: vec![1, 2, 3],
96 };
97
98 let bincode_config = bincode::config::standard();
99
100 let encoded_vec_negative =
101 bincode::encode_to_vec(&config_correct_negative_version, bincode_config).unwrap();
102
103 let (decoded_correct_negative, len_correct_negative): (
104 BincodeConfigNegative<TEST_NEGATIVE_VERSION>,
105 usize,
106 ) = bincode::decode_from_slice(&encoded_vec_negative, bincode_config).unwrap();
107 assert_eq!(decoded_correct_negative, config_correct_negative_version);
108 assert_eq!(len_correct_negative, encoded_vec_negative.len());
109
110 let decode_result_wrong_negative_version: Result<
111 (BincodeConfigNegative<ANOTHER_NEGATIVE_VERSION>, usize),
112 _,
113 > = bincode::decode_from_slice(&encoded_vec_negative, bincode_config);
114
115 assert!(decode_result_wrong_negative_version.is_err());
116 if let Err(e) = decode_result_wrong_negative_version {
117 match e {
118 bincode::error::DecodeError::OtherString(s) => {
119 assert_eq!(s, format!("not {}", ANOTHER_NEGATIVE_VERSION));
120 }
121 _ => panic!("Expected OtherString error, got {:?}", e),
122 }
123 }
124 }
125 #[test]
126 fn test_bincode_typed_num_i64_min() {
127 #[derive(Debug, PartialEq, Eq, BincodeEncode, BincodeDecode)]
128 struct BincodeConfigMin {
129 version: Num<{ i64::MIN }>,
130 data: String,
131 }
132
133 #[derive(Debug, PartialEq, Eq, BincodeEncode, BincodeDecode)]
134 struct BincodeConfigMinMinusOne {
135 version: Num<{ i64::MIN + 1 }>,
136 data: String,
137 }
138
139 let config_min = BincodeConfigMin {
140 version: Num,
141 data: "test_data_min".to_string(),
142 };
143
144 let bincode_config = bincode::config::standard();
145
146 let encoded_vec_min = bincode::encode_to_vec(&config_min, bincode_config).unwrap();
147
148 let (decoded_min, len_min): (BincodeConfigMin, usize) =
149 bincode::decode_from_slice(&encoded_vec_min, bincode_config).unwrap();
150 assert_eq!(decoded_min, config_min);
151 assert_eq!(len_min, encoded_vec_min.len());
152
153 let config_min_minus_one = BincodeConfigMinMinusOne {
154 version: Num,
155 data: "test_data_min_minus_one".to_string(),
156 };
157
158 let encoded_vec_min_minus_one =
159 bincode::encode_to_vec(&config_min_minus_one, bincode_config).unwrap();
160
161 let decode_result_min_minus_one: Result<(BincodeConfigMin, usize), _> =
162 bincode::decode_from_slice(&encoded_vec_min_minus_one, bincode_config);
163
164 assert!(decode_result_min_minus_one.is_err());
165 if let Err(e) = decode_result_min_minus_one {
166 match e {
167 bincode::error::DecodeError::OtherString(s) => {
168 assert_eq!(s, format!("not {}", i64::MIN));
169 }
170 _ => panic!("Expected OtherString error, got {:?}", e),
171 }
172 }
173 }
174
175 #[test]
176 fn test_bincode_typed_num_i64_max() {
177 #[derive(Debug, PartialEq, Eq, BincodeEncode, BincodeDecode)]
178 struct BincodeConfigMax {
179 version: Num<{ i64::MAX }>,
180 data: String,
181 }
182
183 #[derive(Debug, PartialEq, Eq, BincodeEncode, BincodeDecode)]
184 struct BincodeConfigMaxMinusOne {
185 version: Num<{ i64::MAX - 1 }>,
186 data: String,
187 }
188
189 let config_max = BincodeConfigMax {
190 version: Num,
191 data: "test_data_max".to_string(),
192 };
193
194 let bincode_config = bincode::config::standard();
195
196 let encoded_vec_max = bincode::encode_to_vec(&config_max, bincode_config).unwrap();
197
198 let (decoded_max, len_max): (BincodeConfigMax, usize) =
199 bincode::decode_from_slice(&encoded_vec_max, bincode_config).unwrap();
200 assert_eq!(decoded_max, config_max);
201 assert_eq!(len_max, encoded_vec_max.len());
202
203 let config_max_minus_one = BincodeConfigMaxMinusOne {
204 version: Num,
205 data: "test_data_max_minus_one".to_string(),
206 };
207
208 let encoded_vec_max_minus_one =
209 bincode::encode_to_vec(&config_max_minus_one, bincode_config).unwrap();
210
211 let decode_result_max_minus_one: Result<(BincodeConfigMax, usize), _> =
212 bincode::decode_from_slice(&encoded_vec_max_minus_one, bincode_config);
213
214 assert!(decode_result_max_minus_one.is_err());
215 if let Err(e) = decode_result_max_minus_one {
216 match e {
217 bincode::error::DecodeError::OtherString(s) => {
218 assert_eq!(s, format!("not {}", i64::MAX));
219 }
220 _ => panic!("Expected OtherString error, got {:?}", e),
221 }
222 }
223 }
224}