1use crate::{Decoder, Encoder, Env, Error, NifResult, Term};
37
38use num_bigint::{BigInt, Sign};
39
40const EXTERNAL_TERM_FORMAT_VERSION: u8 = 131;
42const SMALL_INTEGER: u8 = 97;
43const INTEGER: u8 = 98;
44const SMALL_BIG_EXT: u8 = 110;
45const LARGE_BIG_EXT: u8 = 111;
46
47crate::atoms! {
48 big_int_encoder_invalid_bytes
49}
50
51fn decode_big_integer(input: &[u8]) -> NifResult<BigInt> {
52 if Some(&EXTERNAL_TERM_FORMAT_VERSION) != input.first() {
53 return Err(Error::BadArg);
54 }
55
56 match input[1] {
57 SMALL_INTEGER => Ok(BigInt::from(input[2])),
58
59 INTEGER => Ok(BigInt::from_signed_bytes_be(&input[2..6])),
60
61 SMALL_BIG_EXT => {
62 let n = input[2] as usize;
63 let sign = if input[3] == 0 {
64 Sign::Plus
65 } else {
66 Sign::Minus
67 };
68
69 Ok(BigInt::from_bytes_le(sign, &input[4..n + 4]))
70 }
71
72 LARGE_BIG_EXT => {
73 let n = u32::from_be_bytes([input[2], input[3], input[4], input[5]]) as usize;
74 let sign = if input[6] == 0 {
75 Sign::Plus
76 } else {
77 Sign::Minus
78 };
79
80 Ok(BigInt::from_bytes_le(sign, &input[7..n + 7]))
81 }
82
83 _ => Err(Error::BadArg),
84 }
85}
86
87fn encode_big_integer(big_int: &BigInt) -> Vec<u8> {
88 if let Ok(integer) = i32::try_from(big_int) {
89 let mut out = vec![EXTERNAL_TERM_FORMAT_VERSION, INTEGER];
90 out.extend(integer.to_be_bytes());
91 out
92 } else {
93 let (sign, data) = big_int.to_bytes_le();
94 let sign = u8::from(sign == Sign::Minus);
95
96 let mut out = vec![EXTERNAL_TERM_FORMAT_VERSION];
97 if data.len() < 256 {
98 let n = data.len() as u8;
100 out.push(SMALL_BIG_EXT);
101 out.push(n);
102 } else {
103 let n = (data.len() as u32).to_be_bytes();
105 out.push(LARGE_BIG_EXT);
106 out.extend(n);
107 };
108 out.push(sign);
109 out.extend(data);
110
111 out
112 }
113}
114
115impl<'a> Decoder<'a> for BigInt {
116 fn decode(term: Term<'a>) -> NifResult<Self> {
117 decode_big_integer(term.to_binary().as_slice())
118 }
119}
120
121impl Encoder for BigInt {
122 fn encode<'c>(&self, env: Env<'c>) -> Term<'c> {
123 let binary = encode_big_integer(self);
125 match env.binary_to_term(&binary) {
126 Some((term, _)) => term,
127 None => env.error_tuple(big_int_encoder_invalid_bytes()),
128 }
129 }
130}
131
132#[test]
133fn decode_small_int() {
134 let data = [131, 97, 3];
136
137 let expected = BigInt::from(3);
138
139 assert_eq!(expected, decode_big_integer(&data).unwrap());
140}
141
142#[test]
143fn decode_small_negative_int() {
144 let data = [131, 98, 255, 255, 255, 251];
146
147 let expected = BigInt::from(-5);
148
149 assert_eq!(expected, decode_big_integer(&data).unwrap());
150}
151
152#[test]
153fn decode_normal_int() {
154 let data = [131, 98, 0, 0, 48, 57];
156
157 let expected = BigInt::from(12345);
158
159 assert_eq!(expected, decode_big_integer(&data).unwrap());
160}
161
162#[test]
163fn decode_small_big_int() {
164 let data = [
166 131, 110, 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
167 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 68, 238, 176, 235, 252,
168 240, 96, 176, 91, 142, 219, 66, 30, 177, 137, 199, 21, 191, 153, 182, 169, 73, 73,
169 ];
170
171 let expected = BigInt::from(24).pow(120);
172
173 assert_eq!(expected, decode_big_integer(&data).unwrap());
174}
175
176#[test]
177fn decode_negative_small_big_int() {
178 let data = [
180 131, 110, 62, 1, 145, 35, 189, 92, 121, 166, 54, 134, 249, 187, 212, 168, 99, 15, 199, 18,
181 199, 144, 202, 125, 24, 74, 178, 7, 108, 123, 248, 46, 241, 16, 48, 69, 1, 158, 117, 115,
182 239, 213, 166, 221, 100, 3, 60, 67, 137, 0, 113, 26, 119, 247, 227, 213, 91, 112, 34, 59,
183 186, 211, 12, 168, 222, 95,
184 ];
185
186 let expected = BigInt::from(-17).pow(121);
187
188 assert_eq!(expected, decode_big_integer(&data).unwrap());
189}
190
191#[test]
192fn decode_large_big_int() {
193 let data = [
195 131, 111, 0, 0, 1, 12, 0, 157, 49, 35, 72, 82, 113, 71, 89, 143, 96, 245, 181, 222, 60,
196 192, 44, 126, 212, 89, 42, 70, 17, 126, 228, 141, 27, 155, 90, 226, 45, 64, 172, 156, 24,
197 197, 15, 30, 187, 15, 9, 134, 118, 177, 56, 98, 1, 252, 238, 113, 38, 174, 187, 181, 161,
198 128, 55, 122, 131, 27, 44, 224, 26, 96, 20, 60, 68, 84, 188, 139, 50, 27, 35, 46, 111, 179,
199 103, 3, 199, 16, 76, 202, 27, 108, 124, 189, 232, 63, 190, 120, 107, 231, 233, 67, 46, 164,
200 146, 45, 0, 180, 109, 22, 20, 201, 153, 9, 199, 7, 75, 91, 29, 48, 143, 191, 229, 182, 108,
201 161, 177, 245, 218, 54, 70, 12, 89, 196, 140, 138, 73, 115, 163, 249, 101, 13, 116, 117,
202 122, 72, 14, 71, 112, 6, 243, 124, 189, 51, 36, 199, 143, 80, 129, 8, 175, 54, 95, 104, 6,
203 40, 35, 244, 36, 219, 112, 129, 114, 96, 207, 37, 61, 113, 250, 82, 185, 101, 176, 68, 250,
204 128, 104, 151, 141, 54, 167, 30, 231, 244, 173, 120, 162, 209, 54, 193, 170, 19, 160, 192,
205 6, 233, 134, 70, 73, 142, 77, 174, 157, 177, 249, 210, 65, 164, 1, 27, 205, 204, 128, 251,
206 195, 234, 183, 185, 159, 191, 32, 252, 61, 28, 157, 38, 61, 130, 198, 248, 203, 196, 150,
207 186, 42, 43, 70, 136, 200, 78, 114, 229, 221, 198, 252, 187, 38, 162, 107, 52, 143, 177,
208 133, 185, 168, 30, 64, 0, 151, 20, 186, 82, 147, 226, 1, 2, 141,
209 ];
210
211 let expected = BigInt::from(5).pow(923);
212
213 assert_eq!(expected, decode_big_integer(&data).unwrap());
214}
215
216#[test]
217fn decode_negative_large_big_int() {
218 let data = [
220 131, 111, 0, 0, 1, 58, 1, 81, 128, 217, 64, 63, 89, 203, 140, 179, 117, 112, 210, 237, 68,
221 55, 214, 150, 63, 212, 77, 220, 75, 154, 120, 104, 18, 185, 178, 140, 7, 210, 84, 65, 183,
222 69, 128, 159, 165, 220, 21, 229, 65, 80, 122, 240, 162, 174, 250, 62, 222, 203, 58, 15,
223 215, 204, 106, 9, 213, 233, 208, 173, 124, 143, 108, 209, 19, 246, 224, 143, 58, 151, 72,
224 57, 203, 232, 159, 92, 71, 8, 128, 138, 187, 209, 239, 209, 189, 91, 50, 55, 3, 226, 214,
225 68, 115, 187, 151, 51, 139, 199, 133, 72, 135, 158, 46, 43, 168, 141, 235, 151, 168, 127,
226 2, 17, 73, 195, 85, 131, 34, 150, 45, 210, 55, 18, 192, 113, 207, 229, 131, 213, 56, 48,
227 60, 112, 76, 231, 109, 95, 46, 73, 56, 133, 2, 78, 96, 124, 119, 255, 5, 70, 120, 18, 146,
228 6, 102, 190, 157, 134, 72, 125, 98, 88, 182, 38, 21, 13, 165, 135, 45, 143, 43, 121, 101,
229 213, 130, 203, 180, 216, 230, 52, 163, 168, 125, 130, 100, 246, 179, 75, 211, 165, 66, 252,
230 232, 223, 119, 44, 105, 62, 1, 100, 61, 132, 185, 114, 75, 234, 116, 186, 208, 227, 77, 81,
231 18, 76, 125, 131, 116, 70, 180, 112, 76, 46, 36, 44, 243, 131, 190, 143, 166, 93, 72, 55,
232 1, 92, 19, 242, 248, 90, 209, 160, 223, 191, 15, 167, 89, 34, 45, 252, 219, 235, 190, 232,
233 32, 144, 232, 82, 173, 238, 213, 14, 157, 168, 162, 122, 24, 114, 192, 77, 18, 167, 147,
234 136, 239, 98, 85, 107, 86, 161, 156, 221, 20, 86, 1, 183, 233, 166, 236, 96, 181, 90, 197,
235 147, 189, 201, 71, 78, 206, 232, 115, 109, 222, 150, 213, 195, 164, 66, 123, 47, 151, 111,
236 193, 165, 1, 16, 3,
237 ];
238
239 let expected = BigInt::from(-17).pow(613);
240
241 assert_eq!(expected, decode_big_integer(&data).unwrap());
242}
243
244#[test]
245fn encode_positive_int_as_integer() {
246 let expected = vec![131, 98, 0, 0, 0, 12];
247
248 let input = BigInt::from(12);
249
250 assert_eq!(expected, encode_big_integer(&input));
251}
252
253#[test]
254fn encode_negative_int_as_integer() {
255 let expected = vec![131, 98, 255, 255, 254, 254];
256
257 let input = BigInt::from(-258);
258
259 assert_eq!(expected, encode_big_integer(&input));
260}
261
262#[test]
263fn encode_negative_int_just_outside_32_bites_as_small_big_int() {
264 let expected = vec![131, 110, 4, 1, 1, 0, 0, 128];
265
266 let input = BigInt::from(i32::MIN as i64 - 1);
267
268 assert_eq!(expected, encode_big_integer(&input));
269}
270
271#[test]
272fn encode_small_big_int() {
273 let expected = vec![
275 131, 110, 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
276 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 68, 238, 176, 235, 252,
277 240, 96, 176, 91, 142, 219, 66, 30, 177, 137, 199, 21, 191, 153, 182, 169, 73, 73,
278 ];
279
280 let input = BigInt::from(24).pow(120);
281
282 assert_eq!(expected, encode_big_integer(&input));
283}
284
285#[test]
286fn encode_negative_small_big_int() {
287 let expected = vec![
289 131, 110, 62, 1, 145, 35, 189, 92, 121, 166, 54, 134, 249, 187, 212, 168, 99, 15, 199, 18,
290 199, 144, 202, 125, 24, 74, 178, 7, 108, 123, 248, 46, 241, 16, 48, 69, 1, 158, 117, 115,
291 239, 213, 166, 221, 100, 3, 60, 67, 137, 0, 113, 26, 119, 247, 227, 213, 91, 112, 34, 59,
292 186, 211, 12, 168, 222, 95,
293 ];
294
295 let input = BigInt::from(-17).pow(121);
296
297 assert_eq!(expected, encode_big_integer(&input));
298}
299
300#[test]
301fn encode_large_big_int() {
302 let expected = vec![
304 131, 111, 0, 0, 1, 12, 0, 157, 49, 35, 72, 82, 113, 71, 89, 143, 96, 245, 181, 222, 60,
305 192, 44, 126, 212, 89, 42, 70, 17, 126, 228, 141, 27, 155, 90, 226, 45, 64, 172, 156, 24,
306 197, 15, 30, 187, 15, 9, 134, 118, 177, 56, 98, 1, 252, 238, 113, 38, 174, 187, 181, 161,
307 128, 55, 122, 131, 27, 44, 224, 26, 96, 20, 60, 68, 84, 188, 139, 50, 27, 35, 46, 111, 179,
308 103, 3, 199, 16, 76, 202, 27, 108, 124, 189, 232, 63, 190, 120, 107, 231, 233, 67, 46, 164,
309 146, 45, 0, 180, 109, 22, 20, 201, 153, 9, 199, 7, 75, 91, 29, 48, 143, 191, 229, 182, 108,
310 161, 177, 245, 218, 54, 70, 12, 89, 196, 140, 138, 73, 115, 163, 249, 101, 13, 116, 117,
311 122, 72, 14, 71, 112, 6, 243, 124, 189, 51, 36, 199, 143, 80, 129, 8, 175, 54, 95, 104, 6,
312 40, 35, 244, 36, 219, 112, 129, 114, 96, 207, 37, 61, 113, 250, 82, 185, 101, 176, 68, 250,
313 128, 104, 151, 141, 54, 167, 30, 231, 244, 173, 120, 162, 209, 54, 193, 170, 19, 160, 192,
314 6, 233, 134, 70, 73, 142, 77, 174, 157, 177, 249, 210, 65, 164, 1, 27, 205, 204, 128, 251,
315 195, 234, 183, 185, 159, 191, 32, 252, 61, 28, 157, 38, 61, 130, 198, 248, 203, 196, 150,
316 186, 42, 43, 70, 136, 200, 78, 114, 229, 221, 198, 252, 187, 38, 162, 107, 52, 143, 177,
317 133, 185, 168, 30, 64, 0, 151, 20, 186, 82, 147, 226, 1, 2, 141,
318 ];
319
320 let input = BigInt::from(5).pow(923);
321
322 assert_eq!(expected, encode_big_integer(&input));
323}
324
325#[test]
326fn encode_negative_large_big_int() {
327 let expected = vec![
329 131, 111, 0, 0, 1, 58, 1, 81, 128, 217, 64, 63, 89, 203, 140, 179, 117, 112, 210, 237, 68,
330 55, 214, 150, 63, 212, 77, 220, 75, 154, 120, 104, 18, 185, 178, 140, 7, 210, 84, 65, 183,
331 69, 128, 159, 165, 220, 21, 229, 65, 80, 122, 240, 162, 174, 250, 62, 222, 203, 58, 15,
332 215, 204, 106, 9, 213, 233, 208, 173, 124, 143, 108, 209, 19, 246, 224, 143, 58, 151, 72,
333 57, 203, 232, 159, 92, 71, 8, 128, 138, 187, 209, 239, 209, 189, 91, 50, 55, 3, 226, 214,
334 68, 115, 187, 151, 51, 139, 199, 133, 72, 135, 158, 46, 43, 168, 141, 235, 151, 168, 127,
335 2, 17, 73, 195, 85, 131, 34, 150, 45, 210, 55, 18, 192, 113, 207, 229, 131, 213, 56, 48,
336 60, 112, 76, 231, 109, 95, 46, 73, 56, 133, 2, 78, 96, 124, 119, 255, 5, 70, 120, 18, 146,
337 6, 102, 190, 157, 134, 72, 125, 98, 88, 182, 38, 21, 13, 165, 135, 45, 143, 43, 121, 101,
338 213, 130, 203, 180, 216, 230, 52, 163, 168, 125, 130, 100, 246, 179, 75, 211, 165, 66, 252,
339 232, 223, 119, 44, 105, 62, 1, 100, 61, 132, 185, 114, 75, 234, 116, 186, 208, 227, 77, 81,
340 18, 76, 125, 131, 116, 70, 180, 112, 76, 46, 36, 44, 243, 131, 190, 143, 166, 93, 72, 55,
341 1, 92, 19, 242, 248, 90, 209, 160, 223, 191, 15, 167, 89, 34, 45, 252, 219, 235, 190, 232,
342 32, 144, 232, 82, 173, 238, 213, 14, 157, 168, 162, 122, 24, 114, 192, 77, 18, 167, 147,
343 136, 239, 98, 85, 107, 86, 161, 156, 221, 20, 86, 1, 183, 233, 166, 236, 96, 181, 90, 197,
344 147, 189, 201, 71, 78, 206, 232, 115, 109, 222, 150, 213, 195, 164, 66, 123, 47, 151, 111,
345 193, 165, 1, 16, 3,
346 ];
347
348 let input = BigInt::from(-17).pow(613);
349
350 assert_eq!(expected, encode_big_integer(&input));
351}