typed_num/
bincode.rs

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}