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