Coverage Report

Created: 2025-07-23 07:29

/rust/registry/src/index.crates.io-6f17d22bba15001f/num-bigint-0.4.4/src/bigint/convert.rs
Line
Count
Source (jump to first uncovered line)
1
use super::Sign::{self, Minus, NoSign, Plus};
2
use super::{BigInt, ToBigInt};
3
4
use crate::std_alloc::Vec;
5
#[cfg(has_try_from)]
6
use crate::TryFromBigIntError;
7
use crate::{BigUint, ParseBigIntError, ToBigUint};
8
9
use core::cmp::Ordering::{Equal, Greater, Less};
10
#[cfg(has_try_from)]
11
use core::convert::TryFrom;
12
use core::str::{self, FromStr};
13
use num_traits::{FromPrimitive, Num, One, ToPrimitive, Zero};
14
15
impl FromStr for BigInt {
16
    type Err = ParseBigIntError;
17
18
    #[inline]
19
0
    fn from_str(s: &str) -> Result<BigInt, ParseBigIntError> {
20
0
        BigInt::from_str_radix(s, 10)
21
0
    }
22
}
23
24
impl Num for BigInt {
25
    type FromStrRadixErr = ParseBigIntError;
26
27
    /// Creates and initializes a [`BigInt`].
28
    #[inline]
29
0
    fn from_str_radix(mut s: &str, radix: u32) -> Result<BigInt, ParseBigIntError> {
30
0
        let sign = if s.starts_with('-') {
31
0
            let tail = &s[1..];
32
0
            if !tail.starts_with('+') {
33
0
                s = tail
34
0
            }
35
0
            Minus
36
        } else {
37
0
            Plus
38
        };
39
0
        let bu = BigUint::from_str_radix(s, radix)?;
40
0
        Ok(BigInt::from_biguint(sign, bu))
41
0
    }
42
}
43
44
impl ToPrimitive for BigInt {
45
    #[inline]
46
0
    fn to_i64(&self) -> Option<i64> {
47
0
        match self.sign {
48
0
            Plus => self.data.to_i64(),
49
0
            NoSign => Some(0),
50
            Minus => {
51
0
                let n = self.data.to_u64()?;
52
0
                let m: u64 = 1 << 63;
53
0
                match n.cmp(&m) {
54
0
                    Less => Some(-(n as i64)),
55
0
                    Equal => Some(core::i64::MIN),
56
0
                    Greater => None,
57
                }
58
            }
59
        }
60
0
    }
61
62
    #[inline]
63
0
    fn to_i128(&self) -> Option<i128> {
64
0
        match self.sign {
65
0
            Plus => self.data.to_i128(),
66
0
            NoSign => Some(0),
67
            Minus => {
68
0
                let n = self.data.to_u128()?;
69
0
                let m: u128 = 1 << 127;
70
0
                match n.cmp(&m) {
71
0
                    Less => Some(-(n as i128)),
72
0
                    Equal => Some(core::i128::MIN),
73
0
                    Greater => None,
74
                }
75
            }
76
        }
77
0
    }
78
79
    #[inline]
80
0
    fn to_u64(&self) -> Option<u64> {
81
0
        match self.sign {
82
0
            Plus => self.data.to_u64(),
83
0
            NoSign => Some(0),
84
0
            Minus => None,
85
        }
86
0
    }
87
88
    #[inline]
89
0
    fn to_u128(&self) -> Option<u128> {
90
0
        match self.sign {
91
0
            Plus => self.data.to_u128(),
92
0
            NoSign => Some(0),
93
0
            Minus => None,
94
        }
95
0
    }
96
97
    #[inline]
98
0
    fn to_f32(&self) -> Option<f32> {
99
0
        let n = self.data.to_f32()?;
100
0
        Some(if self.sign == Minus { -n } else { n })
101
0
    }
102
103
    #[inline]
104
0
    fn to_f64(&self) -> Option<f64> {
105
0
        let n = self.data.to_f64()?;
106
0
        Some(if self.sign == Minus { -n } else { n })
107
0
    }
108
}
109
110
macro_rules! impl_try_from_bigint {
111
    ($T:ty, $to_ty:path) => {
112
        #[cfg(has_try_from)]
113
        impl TryFrom<&BigInt> for $T {
114
            type Error = TryFromBigIntError<()>;
115
116
            #[inline]
117
0
            fn try_from(value: &BigInt) -> Result<$T, TryFromBigIntError<()>> {
118
0
                $to_ty(value).ok_or(TryFromBigIntError::new(()))
119
0
            }
Unexecuted instantiation: <u8 as core::convert::TryFrom<&num_bigint::bigint::BigInt>>::try_from
Unexecuted instantiation: <u16 as core::convert::TryFrom<&num_bigint::bigint::BigInt>>::try_from
Unexecuted instantiation: <u32 as core::convert::TryFrom<&num_bigint::bigint::BigInt>>::try_from
Unexecuted instantiation: <u64 as core::convert::TryFrom<&num_bigint::bigint::BigInt>>::try_from
Unexecuted instantiation: <usize as core::convert::TryFrom<&num_bigint::bigint::BigInt>>::try_from
Unexecuted instantiation: <u128 as core::convert::TryFrom<&num_bigint::bigint::BigInt>>::try_from
Unexecuted instantiation: <i8 as core::convert::TryFrom<&num_bigint::bigint::BigInt>>::try_from
Unexecuted instantiation: <i16 as core::convert::TryFrom<&num_bigint::bigint::BigInt>>::try_from
Unexecuted instantiation: <i32 as core::convert::TryFrom<&num_bigint::bigint::BigInt>>::try_from
Unexecuted instantiation: <i64 as core::convert::TryFrom<&num_bigint::bigint::BigInt>>::try_from
Unexecuted instantiation: <isize as core::convert::TryFrom<&num_bigint::bigint::BigInt>>::try_from
Unexecuted instantiation: <i128 as core::convert::TryFrom<&num_bigint::bigint::BigInt>>::try_from
120
        }
121
122
        #[cfg(has_try_from)]
123
        impl TryFrom<BigInt> for $T {
124
            type Error = TryFromBigIntError<BigInt>;
125
126
            #[inline]
127
0
            fn try_from(value: BigInt) -> Result<$T, TryFromBigIntError<BigInt>> {
128
0
                <$T>::try_from(&value).map_err(|_| TryFromBigIntError::new(value))
Unexecuted instantiation: <u8 as core::convert::TryFrom<num_bigint::bigint::BigInt>>::try_from::{closure#0}
Unexecuted instantiation: <u16 as core::convert::TryFrom<num_bigint::bigint::BigInt>>::try_from::{closure#0}
Unexecuted instantiation: <u32 as core::convert::TryFrom<num_bigint::bigint::BigInt>>::try_from::{closure#0}
Unexecuted instantiation: <u64 as core::convert::TryFrom<num_bigint::bigint::BigInt>>::try_from::{closure#0}
Unexecuted instantiation: <usize as core::convert::TryFrom<num_bigint::bigint::BigInt>>::try_from::{closure#0}
Unexecuted instantiation: <u128 as core::convert::TryFrom<num_bigint::bigint::BigInt>>::try_from::{closure#0}
Unexecuted instantiation: <i8 as core::convert::TryFrom<num_bigint::bigint::BigInt>>::try_from::{closure#0}
Unexecuted instantiation: <i16 as core::convert::TryFrom<num_bigint::bigint::BigInt>>::try_from::{closure#0}
Unexecuted instantiation: <i32 as core::convert::TryFrom<num_bigint::bigint::BigInt>>::try_from::{closure#0}
Unexecuted instantiation: <i64 as core::convert::TryFrom<num_bigint::bigint::BigInt>>::try_from::{closure#0}
Unexecuted instantiation: <isize as core::convert::TryFrom<num_bigint::bigint::BigInt>>::try_from::{closure#0}
Unexecuted instantiation: <i128 as core::convert::TryFrom<num_bigint::bigint::BigInt>>::try_from::{closure#0}
129
0
            }
Unexecuted instantiation: <u8 as core::convert::TryFrom<num_bigint::bigint::BigInt>>::try_from
Unexecuted instantiation: <u16 as core::convert::TryFrom<num_bigint::bigint::BigInt>>::try_from
Unexecuted instantiation: <u32 as core::convert::TryFrom<num_bigint::bigint::BigInt>>::try_from
Unexecuted instantiation: <u64 as core::convert::TryFrom<num_bigint::bigint::BigInt>>::try_from
Unexecuted instantiation: <usize as core::convert::TryFrom<num_bigint::bigint::BigInt>>::try_from
Unexecuted instantiation: <u128 as core::convert::TryFrom<num_bigint::bigint::BigInt>>::try_from
Unexecuted instantiation: <i8 as core::convert::TryFrom<num_bigint::bigint::BigInt>>::try_from
Unexecuted instantiation: <i16 as core::convert::TryFrom<num_bigint::bigint::BigInt>>::try_from
Unexecuted instantiation: <i32 as core::convert::TryFrom<num_bigint::bigint::BigInt>>::try_from
Unexecuted instantiation: <i64 as core::convert::TryFrom<num_bigint::bigint::BigInt>>::try_from
Unexecuted instantiation: <isize as core::convert::TryFrom<num_bigint::bigint::BigInt>>::try_from
Unexecuted instantiation: <i128 as core::convert::TryFrom<num_bigint::bigint::BigInt>>::try_from
130
        }
131
    };
132
}
133
134
impl_try_from_bigint!(u8, ToPrimitive::to_u8);
135
impl_try_from_bigint!(u16, ToPrimitive::to_u16);
136
impl_try_from_bigint!(u32, ToPrimitive::to_u32);
137
impl_try_from_bigint!(u64, ToPrimitive::to_u64);
138
impl_try_from_bigint!(usize, ToPrimitive::to_usize);
139
impl_try_from_bigint!(u128, ToPrimitive::to_u128);
140
141
impl_try_from_bigint!(i8, ToPrimitive::to_i8);
142
impl_try_from_bigint!(i16, ToPrimitive::to_i16);
143
impl_try_from_bigint!(i32, ToPrimitive::to_i32);
144
impl_try_from_bigint!(i64, ToPrimitive::to_i64);
145
impl_try_from_bigint!(isize, ToPrimitive::to_isize);
146
impl_try_from_bigint!(i128, ToPrimitive::to_i128);
147
148
impl FromPrimitive for BigInt {
149
    #[inline]
150
0
    fn from_i64(n: i64) -> Option<BigInt> {
151
0
        Some(BigInt::from(n))
152
0
    }
153
154
    #[inline]
155
0
    fn from_i128(n: i128) -> Option<BigInt> {
156
0
        Some(BigInt::from(n))
157
0
    }
158
159
    #[inline]
160
0
    fn from_u64(n: u64) -> Option<BigInt> {
161
0
        Some(BigInt::from(n))
162
0
    }
163
164
    #[inline]
165
0
    fn from_u128(n: u128) -> Option<BigInt> {
166
0
        Some(BigInt::from(n))
167
0
    }
168
169
    #[inline]
170
0
    fn from_f64(n: f64) -> Option<BigInt> {
171
0
        if n >= 0.0 {
172
0
            BigUint::from_f64(n).map(BigInt::from)
173
        } else {
174
0
            let x = BigUint::from_f64(-n)?;
175
0
            Some(-BigInt::from(x))
176
        }
177
0
    }
178
}
179
180
impl From<i64> for BigInt {
181
    #[inline]
182
0
    fn from(n: i64) -> Self {
183
0
        if n >= 0 {
184
0
            BigInt::from(n as u64)
185
        } else {
186
0
            let u = core::u64::MAX - (n as u64) + 1;
187
0
            BigInt {
188
0
                sign: Minus,
189
0
                data: BigUint::from(u),
190
0
            }
191
        }
192
0
    }
193
}
194
195
impl From<i128> for BigInt {
196
    #[inline]
197
0
    fn from(n: i128) -> Self {
198
0
        if n >= 0 {
199
0
            BigInt::from(n as u128)
200
        } else {
201
0
            let u = core::u128::MAX - (n as u128) + 1;
202
0
            BigInt {
203
0
                sign: Minus,
204
0
                data: BigUint::from(u),
205
0
            }
206
        }
207
0
    }
208
}
209
210
macro_rules! impl_bigint_from_int {
211
    ($T:ty) => {
212
        impl From<$T> for BigInt {
213
            #[inline]
214
0
            fn from(n: $T) -> Self {
215
0
                BigInt::from(n as i64)
216
0
            }
Unexecuted instantiation: <num_bigint::bigint::BigInt as core::convert::From<i8>>::from
Unexecuted instantiation: <num_bigint::bigint::BigInt as core::convert::From<i16>>::from
Unexecuted instantiation: <num_bigint::bigint::BigInt as core::convert::From<i32>>::from
Unexecuted instantiation: <num_bigint::bigint::BigInt as core::convert::From<isize>>::from
217
        }
218
    };
219
}
220
221
impl_bigint_from_int!(i8);
222
impl_bigint_from_int!(i16);
223
impl_bigint_from_int!(i32);
224
impl_bigint_from_int!(isize);
225
226
impl From<u64> for BigInt {
227
    #[inline]
228
0
    fn from(n: u64) -> Self {
229
0
        if n > 0 {
230
0
            BigInt {
231
0
                sign: Plus,
232
0
                data: BigUint::from(n),
233
0
            }
234
        } else {
235
0
            BigInt::zero()
236
        }
237
0
    }
238
}
239
240
impl From<u128> for BigInt {
241
    #[inline]
242
0
    fn from(n: u128) -> Self {
243
0
        if n > 0 {
244
0
            BigInt {
245
0
                sign: Plus,
246
0
                data: BigUint::from(n),
247
0
            }
248
        } else {
249
0
            BigInt::zero()
250
        }
251
0
    }
252
}
253
254
macro_rules! impl_bigint_from_uint {
255
    ($T:ty) => {
256
        impl From<$T> for BigInt {
257
            #[inline]
258
0
            fn from(n: $T) -> Self {
259
0
                BigInt::from(n as u64)
260
0
            }
Unexecuted instantiation: <num_bigint::bigint::BigInt as core::convert::From<u8>>::from
Unexecuted instantiation: <num_bigint::bigint::BigInt as core::convert::From<u16>>::from
Unexecuted instantiation: <num_bigint::bigint::BigInt as core::convert::From<usize>>::from
Unexecuted instantiation: <num_bigint::bigint::BigInt as core::convert::From<u32>>::from
261
        }
262
    };
263
}
264
265
impl_bigint_from_uint!(u8);
266
impl_bigint_from_uint!(u16);
267
impl_bigint_from_uint!(u32);
268
impl_bigint_from_uint!(usize);
269
270
impl From<BigUint> for BigInt {
271
    #[inline]
272
0
    fn from(n: BigUint) -> Self {
273
0
        if n.is_zero() {
274
0
            BigInt::zero()
275
        } else {
276
0
            BigInt {
277
0
                sign: Plus,
278
0
                data: n,
279
0
            }
280
        }
281
0
    }
282
}
283
284
impl ToBigInt for BigInt {
285
    #[inline]
286
0
    fn to_bigint(&self) -> Option<BigInt> {
287
0
        Some(self.clone())
288
0
    }
289
}
290
291
impl ToBigInt for BigUint {
292
    #[inline]
293
0
    fn to_bigint(&self) -> Option<BigInt> {
294
0
        if self.is_zero() {
295
0
            Some(Zero::zero())
296
        } else {
297
0
            Some(BigInt {
298
0
                sign: Plus,
299
0
                data: self.clone(),
300
0
            })
301
        }
302
0
    }
303
}
304
305
impl ToBigUint for BigInt {
306
    #[inline]
307
0
    fn to_biguint(&self) -> Option<BigUint> {
308
0
        match self.sign() {
309
0
            Plus => Some(self.data.clone()),
310
0
            NoSign => Some(Zero::zero()),
311
0
            Minus => None,
312
        }
313
0
    }
314
}
315
316
#[cfg(has_try_from)]
317
impl TryFrom<&BigInt> for BigUint {
318
    type Error = TryFromBigIntError<()>;
319
320
    #[inline]
321
0
    fn try_from(value: &BigInt) -> Result<BigUint, TryFromBigIntError<()>> {
322
0
        value
323
0
            .to_biguint()
324
0
            .ok_or_else(|| TryFromBigIntError::new(()))
325
0
    }
326
}
327
328
#[cfg(has_try_from)]
329
impl TryFrom<BigInt> for BigUint {
330
    type Error = TryFromBigIntError<BigInt>;
331
332
    #[inline]
333
0
    fn try_from(value: BigInt) -> Result<BigUint, TryFromBigIntError<BigInt>> {
334
0
        if value.sign() == Sign::Minus {
335
0
            Err(TryFromBigIntError::new(value))
336
        } else {
337
0
            Ok(value.data)
338
        }
339
0
    }
340
}
341
342
macro_rules! impl_to_bigint {
343
    ($T:ty, $from_ty:path) => {
344
        impl ToBigInt for $T {
345
            #[inline]
346
0
            fn to_bigint(&self) -> Option<BigInt> {
347
0
                $from_ty(*self)
348
0
            }
Unexecuted instantiation: <isize as num_bigint::bigint::ToBigInt>::to_bigint
Unexecuted instantiation: <i8 as num_bigint::bigint::ToBigInt>::to_bigint
Unexecuted instantiation: <i16 as num_bigint::bigint::ToBigInt>::to_bigint
Unexecuted instantiation: <i32 as num_bigint::bigint::ToBigInt>::to_bigint
Unexecuted instantiation: <i64 as num_bigint::bigint::ToBigInt>::to_bigint
Unexecuted instantiation: <i128 as num_bigint::bigint::ToBigInt>::to_bigint
Unexecuted instantiation: <usize as num_bigint::bigint::ToBigInt>::to_bigint
Unexecuted instantiation: <u8 as num_bigint::bigint::ToBigInt>::to_bigint
Unexecuted instantiation: <u16 as num_bigint::bigint::ToBigInt>::to_bigint
Unexecuted instantiation: <u32 as num_bigint::bigint::ToBigInt>::to_bigint
Unexecuted instantiation: <u64 as num_bigint::bigint::ToBigInt>::to_bigint
Unexecuted instantiation: <u128 as num_bigint::bigint::ToBigInt>::to_bigint
Unexecuted instantiation: <f32 as num_bigint::bigint::ToBigInt>::to_bigint
Unexecuted instantiation: <f64 as num_bigint::bigint::ToBigInt>::to_bigint
349
        }
350
    };
351
}
352
353
impl_to_bigint!(isize, FromPrimitive::from_isize);
354
impl_to_bigint!(i8, FromPrimitive::from_i8);
355
impl_to_bigint!(i16, FromPrimitive::from_i16);
356
impl_to_bigint!(i32, FromPrimitive::from_i32);
357
impl_to_bigint!(i64, FromPrimitive::from_i64);
358
impl_to_bigint!(i128, FromPrimitive::from_i128);
359
360
impl_to_bigint!(usize, FromPrimitive::from_usize);
361
impl_to_bigint!(u8, FromPrimitive::from_u8);
362
impl_to_bigint!(u16, FromPrimitive::from_u16);
363
impl_to_bigint!(u32, FromPrimitive::from_u32);
364
impl_to_bigint!(u64, FromPrimitive::from_u64);
365
impl_to_bigint!(u128, FromPrimitive::from_u128);
366
367
impl_to_bigint!(f32, FromPrimitive::from_f32);
368
impl_to_bigint!(f64, FromPrimitive::from_f64);
369
370
impl From<bool> for BigInt {
371
0
    fn from(x: bool) -> Self {
372
0
        if x {
373
0
            One::one()
374
        } else {
375
0
            Zero::zero()
376
        }
377
0
    }
378
}
379
380
#[inline]
381
0
pub(super) fn from_signed_bytes_be(digits: &[u8]) -> BigInt {
382
0
    let sign = match digits.first() {
383
0
        Some(v) if *v > 0x7f => Sign::Minus,
384
0
        Some(_) => Sign::Plus,
385
0
        None => return BigInt::zero(),
386
    };
387
388
0
    if sign == Sign::Minus {
389
        // two's-complement the content to retrieve the magnitude
390
0
        let mut digits = Vec::from(digits);
391
0
        twos_complement_be(&mut digits);
392
0
        BigInt::from_biguint(sign, BigUint::from_bytes_be(&digits))
393
    } else {
394
0
        BigInt::from_biguint(sign, BigUint::from_bytes_be(digits))
395
    }
396
0
}
397
398
#[inline]
399
0
pub(super) fn from_signed_bytes_le(digits: &[u8]) -> BigInt {
400
0
    let sign = match digits.last() {
401
0
        Some(v) if *v > 0x7f => Sign::Minus,
402
0
        Some(_) => Sign::Plus,
403
0
        None => return BigInt::zero(),
404
    };
405
406
0
    if sign == Sign::Minus {
407
        // two's-complement the content to retrieve the magnitude
408
0
        let mut digits = Vec::from(digits);
409
0
        twos_complement_le(&mut digits);
410
0
        BigInt::from_biguint(sign, BigUint::from_bytes_le(&digits))
411
    } else {
412
0
        BigInt::from_biguint(sign, BigUint::from_bytes_le(digits))
413
    }
414
0
}
415
416
#[inline]
417
0
pub(super) fn to_signed_bytes_be(x: &BigInt) -> Vec<u8> {
418
0
    let mut bytes = x.data.to_bytes_be();
419
0
    let first_byte = bytes.first().cloned().unwrap_or(0);
420
0
    if first_byte > 0x7f
421
0
        && !(first_byte == 0x80 && bytes.iter().skip(1).all(Zero::is_zero) && x.sign == Sign::Minus)
422
0
    {
423
0
        // msb used by magnitude, extend by 1 byte
424
0
        bytes.insert(0, 0);
425
0
    }
426
0
    if x.sign == Sign::Minus {
427
0
        twos_complement_be(&mut bytes);
428
0
    }
429
0
    bytes
430
0
}
431
432
#[inline]
433
0
pub(super) fn to_signed_bytes_le(x: &BigInt) -> Vec<u8> {
434
0
    let mut bytes = x.data.to_bytes_le();
435
0
    let last_byte = bytes.last().cloned().unwrap_or(0);
436
0
    if last_byte > 0x7f
437
0
        && !(last_byte == 0x80
438
0
            && bytes.iter().rev().skip(1).all(Zero::is_zero)
439
0
            && x.sign == Sign::Minus)
440
0
    {
441
0
        // msb used by magnitude, extend by 1 byte
442
0
        bytes.push(0);
443
0
    }
444
0
    if x.sign == Sign::Minus {
445
0
        twos_complement_le(&mut bytes);
446
0
    }
447
0
    bytes
448
0
}
449
450
/// Perform in-place two's complement of the given binary representation,
451
/// in little-endian byte order.
452
#[inline]
453
0
fn twos_complement_le(digits: &mut [u8]) {
454
0
    twos_complement(digits)
455
0
}
456
457
/// Perform in-place two's complement of the given binary representation
458
/// in big-endian byte order.
459
#[inline]
460
0
fn twos_complement_be(digits: &mut [u8]) {
461
0
    twos_complement(digits.iter_mut().rev())
462
0
}
463
464
/// Perform in-place two's complement of the given digit iterator
465
/// starting from the least significant byte.
466
#[inline]
467
0
fn twos_complement<'a, I>(digits: I)
468
0
where
469
0
    I: IntoIterator<Item = &'a mut u8>,
470
0
{
471
0
    let mut carry = true;
472
0
    for d in digits {
473
0
        *d = !*d;
474
0
        if carry {
475
0
            *d = d.wrapping_add(1);
476
0
            carry = d.is_zero();
477
0
        }
478
    }
479
0
}
Unexecuted instantiation: num_bigint::bigint::convert::twos_complement::<core::iter::adapters::rev::Rev<core::slice::iter::IterMut<u8>>>
Unexecuted instantiation: num_bigint::bigint::convert::twos_complement::<core::iter::adapters::rev::Rev<core::slice::iter::IterMut<u8>>>
Unexecuted instantiation: num_bigint::bigint::convert::twos_complement::<&mut [u8]>