diff --git a/bigint/src/bigint.rs b/bigint/src/bigint.rs index beff1ff..b86ca52 100644 --- a/bigint/src/bigint.rs +++ b/bigint/src/bigint.rs @@ -926,49 +926,6 @@ impl BigInt { BigInt::from_biguint(sign, BigUint::new(digits)) } - /// Creates and initializes a `BigInt` from an array of bytes in two's complement. - /// - /// The digits are in little-endian base 2^8. - #[inline] - pub fn from_signed_bytes_le(digits: &[u8]) -> BigInt { - let sign = match digits.last() { - Some(v) if *v > 0x7f => Sign::Minus, - Some(_) => Sign::Plus, - None => return BigInt::zero(), - }; - - if sign == Sign::Minus { - // two's-complement the content to retrieve the magnitude - let mut digits = Vec::from(digits); - twos_complement_le(&mut digits); - BigInt::from_biguint(sign, BigUint::from_bytes_le(&*digits)) - } else { - BigInt::from_biguint(sign, BigUint::from_bytes_le(digits)) - } - } - - /// Creates and initializes a `BigInt` from an array of bytes in - /// two's complement binary representation. - /// - /// The digits are in big-endian base 2^8. - #[inline] - pub fn from_signed_bytes_be(digits: &[u8]) -> BigInt { - let sign = match digits.first() { - Some(v) if *v > 0x7f => Sign::Minus, - Some(_) => Sign::Plus, - None => return BigInt::zero(), - }; - - if sign == Sign::Minus { - // two's-complement the content to retrieve the magnitude - let mut digits = Vec::from(digits); - twos_complement_be(&mut digits); - BigInt::from_biguint(sign, BigUint::from_bytes_be(&*digits)) - } else { - BigInt::from_biguint(sign, BigUint::from_bytes_be(digits)) - } - } - /// Creates and initializes a `BigInt`. /// /// The digits are in little-endian base 2^32. @@ -1023,6 +980,65 @@ impl BigInt { BigInt::from_biguint(sign, BigUint::from_bytes_le(bytes)) } + /// Creates and initializes a `BigInt` from an array of bytes in + /// two's complement binary representation. + /// + /// The digits are in big-endian base 2^8. + #[inline] + pub fn from_signed_bytes_be(digits: &[u8]) -> BigInt { + let sign = match digits.first() { + Some(v) if *v > 0x7f => Sign::Minus, + Some(_) => Sign::Plus, + None => return BigInt::zero(), + }; + + if sign == Sign::Minus { + // two's-complement the content to retrieve the magnitude + let mut digits = Vec::from(digits); + twos_complement_be(&mut digits); + BigInt::from_biguint(sign, BigUint::from_bytes_be(&*digits)) + } else { + BigInt::from_biguint(sign, BigUint::from_bytes_be(digits)) + } + } + + /// Creates and initializes a `BigInt` from an array of bytes in two's complement. + /// + /// The digits are in little-endian base 2^8. + #[inline] + pub fn from_signed_bytes_le(digits: &[u8]) -> BigInt { + let sign = match digits.last() { + Some(v) if *v > 0x7f => Sign::Minus, + Some(_) => Sign::Plus, + None => return BigInt::zero(), + }; + + if sign == Sign::Minus { + // two's-complement the content to retrieve the magnitude + let mut digits = Vec::from(digits); + twos_complement_le(&mut digits); + BigInt::from_biguint(sign, BigUint::from_bytes_le(&*digits)) + } else { + BigInt::from_biguint(sign, BigUint::from_bytes_le(digits)) + } + } + + /// Creates and initializes a `BigInt`. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::{BigInt, ToBigInt}; + /// + /// assert_eq!(BigInt::parse_bytes(b"1234", 10), ToBigInt::to_bigint(&1234)); + /// assert_eq!(BigInt::parse_bytes(b"ABCD", 16), ToBigInt::to_bigint(&0xABCD)); + /// assert_eq!(BigInt::parse_bytes(b"G", 16), None); + /// ``` + #[inline] + pub fn parse_bytes(buf: &[u8], radix: u32) -> Option { + str::from_utf8(buf).ok().and_then(|s| BigInt::from_str_radix(s, radix).ok()) + } + /// Creates and initializes a `BigInt`. Each u8 of the input slice is /// interpreted as one digit of the number /// and must therefore be less than `radix`. @@ -1063,45 +1079,6 @@ impl BigInt { BigUint::from_radix_le(buf, radix).map(|u| BigInt::from_biguint(sign, u)) } - /// Returns the sign and the byte representation of the `BigInt` in little-endian byte order. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::{ToBigInt, Sign}; - /// - /// let i = -1125.to_bigint().unwrap(); - /// assert_eq!(i.to_bytes_le(), (Sign::Minus, vec![101, 4])); - /// ``` - #[inline] - pub fn to_bytes_le(&self) -> (Sign, Vec) { - (self.sign, self.data.to_bytes_le()) - } - - /// Returns the two's complement byte representation of the `BigInt` in little-endian byte order. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::ToBigInt; - /// - /// let i = -1125.to_bigint().unwrap(); - /// assert_eq!(i.to_signed_bytes_le(), vec![155, 251]); - /// ``` - #[inline] - pub fn to_signed_bytes_le(&self) -> Vec { - let mut bytes = self.data.to_bytes_le(); - let last_byte = bytes.last().map(|v| *v).unwrap_or(0); - if last_byte > 0x7f && !(last_byte == 0x80 && bytes.iter().rev().skip(1).all(Zero::is_zero)) { - // msb used by magnitude, extend by 1 byte - bytes.push(0); - } - if self.sign == Sign::Minus { - twos_complement_le(&mut bytes); - } - bytes - } - /// Returns the sign and the byte representation of the `BigInt` in big-endian byte order. /// /// # Examples @@ -1117,6 +1094,21 @@ impl BigInt { (self.sign, self.data.to_bytes_be()) } + /// Returns the sign and the byte representation of the `BigInt` in little-endian byte order. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::{ToBigInt, Sign}; + /// + /// let i = -1125.to_bigint().unwrap(); + /// assert_eq!(i.to_bytes_le(), (Sign::Minus, vec![101, 4])); + /// ``` + #[inline] + pub fn to_bytes_le(&self) -> (Sign, Vec) { + (self.sign, self.data.to_bytes_le()) + } + /// Returns the two's complement byte representation of the `BigInt` in big-endian byte order. /// /// # Examples @@ -1137,7 +1129,31 @@ impl BigInt { } if self.sign == Sign::Minus { twos_complement_be(&mut bytes); - } + } + bytes + } + + /// Returns the two's complement byte representation of the `BigInt` in little-endian byte order. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::ToBigInt; + /// + /// let i = -1125.to_bigint().unwrap(); + /// assert_eq!(i.to_signed_bytes_le(), vec![155, 251]); + /// ``` + #[inline] + pub fn to_signed_bytes_le(&self) -> Vec { + let mut bytes = self.data.to_bytes_le(); + let last_byte = bytes.last().map(|v| *v).unwrap_or(0); + if last_byte > 0x7f && !(last_byte == 0x80 && bytes.iter().rev().skip(1).all(Zero::is_zero)) { + // msb used by magnitude, extend by 1 byte + bytes.push(0); + } + if self.sign == Sign::Minus { + twos_complement_le(&mut bytes); + } bytes } @@ -1218,22 +1234,6 @@ impl BigInt { self.sign } - /// Creates and initializes a `BigInt`. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::{BigInt, ToBigInt}; - /// - /// assert_eq!(BigInt::parse_bytes(b"1234", 10), ToBigInt::to_bigint(&1234)); - /// assert_eq!(BigInt::parse_bytes(b"ABCD", 16), ToBigInt::to_bigint(&0xABCD)); - /// assert_eq!(BigInt::parse_bytes(b"G", 16), None); - /// ``` - #[inline] - pub fn parse_bytes(buf: &[u8], radix: u32) -> Option { - str::from_utf8(buf).ok().and_then(|s| BigInt::from_str_radix(s, radix).ok()) - } - /// Determines the fewest bits necessary to express the `BigInt`, /// not including the sign. #[inline] diff --git a/bigint/src/biguint.rs b/bigint/src/biguint.rs index ece4861..340aaae 100644 --- a/bigint/src/biguint.rs +++ b/bigint/src/biguint.rs @@ -1088,6 +1088,23 @@ impl BigUint { } + /// Returns the byte representation of the `BigUint` in big-endian byte order. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::BigUint; + /// + /// let i = BigUint::parse_bytes(b"1125", 10).unwrap(); + /// assert_eq!(i.to_bytes_be(), vec![4, 101]); + /// ``` + #[inline] + pub fn to_bytes_be(&self) -> Vec { + let mut v = self.to_bytes_le(); + v.reverse(); + v + } + /// Returns the byte representation of the `BigUint` in little-endian byte order. /// /// # Examples @@ -1107,23 +1124,6 @@ impl BigUint { } } - /// Returns the byte representation of the `BigUint` in big-endian byte order. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::BigUint; - /// - /// let i = BigUint::parse_bytes(b"1125", 10).unwrap(); - /// assert_eq!(i.to_bytes_be(), vec![4, 101]); - /// ``` - #[inline] - pub fn to_bytes_be(&self) -> Vec { - let mut v = self.to_bytes_le(); - v.reverse(); - v - } - /// Returns the integer formatted as a string in the given radix. /// `radix` must be in the range `2...36`. /// @@ -1142,25 +1142,6 @@ impl BigUint { unsafe { String::from_utf8_unchecked(v) } } - /// Returns the integer in the requested base in little-endian digit order. - /// The output is not given in a human readable alphabet but as a zero - /// based u8 number. - /// `radix` must be in the range `2...256`. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::BigUint; - /// - /// assert_eq!(BigUint::from(0xFFFFu64).to_radix_le(159), - /// vec![27, 94, 2]); - /// // 0xFFFF = 65535 = 27 + 94*159 + 2*(159^2) - /// ``` - #[inline] - pub fn to_radix_le(&self, radix: u32) -> Vec { - to_radix_le(self, radix) - } - /// Returns the integer in the requested base in big-endian digit order. /// The output is not given in a human readable alphabet but as a zero /// based u8 number. @@ -1182,6 +1163,25 @@ impl BigUint { v } + /// Returns the integer in the requested base in little-endian digit order. + /// The output is not given in a human readable alphabet but as a zero + /// based u8 number. + /// `radix` must be in the range `2...256`. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::BigUint; + /// + /// assert_eq!(BigUint::from(0xFFFFu64).to_radix_le(159), + /// vec![27, 94, 2]); + /// // 0xFFFF = 65535 = 27 + 94*159 + 2*(159^2) + /// ``` + #[inline] + pub fn to_radix_le(&self, radix: u32) -> Vec { + to_radix_le(self, radix) + } + /// Determines the fewest bits necessary to express the `BigUint`. #[inline] pub fn bits(&self) -> usize {