Update FromStr and FromStrRadix to return Result
Fixes build errors with Rust 1.0.0-nightly.
This commit is contained in:
parent
b324415930
commit
42edb63090
|
@ -60,7 +60,10 @@ extern crate "rustc-serialize" as rustc_serialize;
|
||||||
|
|
||||||
use Integer;
|
use Integer;
|
||||||
|
|
||||||
|
use core::num::ParseIntError;
|
||||||
|
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
|
use std::error::{Error, FromError};
|
||||||
use std::iter::repeat;
|
use std::iter::repeat;
|
||||||
use std::num::{Int, ToPrimitive, FromPrimitive, FromStrRadix};
|
use std::num::{Int, ToPrimitive, FromPrimitive, FromStrRadix};
|
||||||
use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Rem, Shl, Shr, Sub};
|
use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Rem, Shl, Shr, Sub};
|
||||||
|
@ -181,8 +184,10 @@ impl fmt::Display for BigUint {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for BigUint {
|
impl FromStr for BigUint {
|
||||||
|
type Err = ParseBigIntError;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_str(s: &str) -> Option<BigUint> {
|
fn from_str(s: &str) -> Result<BigUint, ParseBigIntError> {
|
||||||
FromStrRadix::from_str_radix(s, 10)
|
FromStrRadix::from_str_radix(s, 10)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -815,13 +820,15 @@ fn to_str_radix_signed(me: &BigInt, radix: usize) -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStrRadix for BigUint {
|
impl FromStrRadix for BigUint {
|
||||||
|
type Err = ParseBigIntError;
|
||||||
|
|
||||||
/// Creates and initializes a `BigUint`.
|
/// Creates and initializes a `BigUint`.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_str_radix(s: &str, radix: usize) -> Option<BigUint> {
|
fn from_str_radix(s: &str, radix: usize) -> Result<BigUint, ParseBigIntError> {
|
||||||
let (base, unit_len) = get_radix_base(radix);
|
let (base, unit_len) = get_radix_base(radix);
|
||||||
let base_num = match base.to_biguint() {
|
let base_num = match base.to_biguint() {
|
||||||
Some(base_num) => base_num,
|
Some(base_num) => base_num,
|
||||||
None => { return None; }
|
None => { return Err(ParseBigIntError::Other); }
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut end = s.len();
|
let mut end = s.len();
|
||||||
|
@ -829,22 +836,18 @@ impl FromStrRadix for BigUint {
|
||||||
let mut power: BigUint = One::one();
|
let mut power: BigUint = One::one();
|
||||||
loop {
|
loop {
|
||||||
let start = cmp::max(end, unit_len) - unit_len;
|
let start = cmp::max(end, unit_len) - unit_len;
|
||||||
match FromStrRadix::from_str_radix(&s[start .. end], radix) {
|
let d = try!(FromStrRadix::from_str_radix(&s[start .. end], radix));
|
||||||
|
let d: Option<BigUint> = FromPrimitive::from_uint(d);
|
||||||
|
match d {
|
||||||
Some(d) => {
|
Some(d) => {
|
||||||
let d: Option<BigUint> = FromPrimitive::from_uint(d);
|
// FIXME(#5992): assignment operator overloads
|
||||||
match d {
|
// n += d * &power;
|
||||||
Some(d) => {
|
n = n + d * &power;
|
||||||
// FIXME(#5992): assignment operator overloads
|
|
||||||
// n += d * &power;
|
|
||||||
n = n + d * &power;
|
|
||||||
}
|
|
||||||
None => { return None; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
None => { return None; }
|
None => { return Err(ParseBigIntError::Other); }
|
||||||
}
|
}
|
||||||
if end <= unit_len {
|
if end <= unit_len {
|
||||||
return Some(n);
|
return Ok(n);
|
||||||
}
|
}
|
||||||
end -= unit_len;
|
end -= unit_len;
|
||||||
// FIXME(#5992): assignment operator overloads
|
// FIXME(#5992): assignment operator overloads
|
||||||
|
@ -956,7 +959,7 @@ impl BigUint {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn parse_bytes(buf: &[u8], radix: usize) -> Option<BigUint> {
|
pub fn parse_bytes(buf: &[u8], radix: usize) -> Option<BigUint> {
|
||||||
str::from_utf8(buf).ok().and_then(|s| FromStrRadix::from_str_radix(s, radix))
|
str::from_utf8(buf).ok().and_then(|s| FromStrRadix::from_str_radix(s, radix).ok())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -1110,8 +1113,10 @@ impl<S: hash::Hasher + hash::Writer> hash::Hash<S> for BigInt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for BigInt {
|
impl FromStr for BigInt {
|
||||||
|
type Err = ParseBigIntError;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_str(s: &str) -> Option<BigInt> {
|
fn from_str(s: &str) -> Result<BigInt, ParseBigIntError> {
|
||||||
FromStrRadix::from_str_radix(s, 10)
|
FromStrRadix::from_str_radix(s, 10)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1521,10 +1526,12 @@ impl_to_bigint!(u32, FromPrimitive::from_u32);
|
||||||
impl_to_bigint!(u64, FromPrimitive::from_u64);
|
impl_to_bigint!(u64, FromPrimitive::from_u64);
|
||||||
|
|
||||||
impl FromStrRadix for BigInt {
|
impl FromStrRadix for BigInt {
|
||||||
|
type Err = ParseBigIntError;
|
||||||
|
|
||||||
/// Creates and initializes a BigInt.
|
/// Creates and initializes a BigInt.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_str_radix(s: &str, radix: usize) -> Option<BigInt> {
|
fn from_str_radix(s: &str, radix: usize) -> Result<BigInt, ParseBigIntError> {
|
||||||
if s.is_empty() { return None; }
|
if s.is_empty() { return Err(ParseBigIntError::Other); }
|
||||||
let mut sign = Plus;
|
let mut sign = Plus;
|
||||||
let mut start = 0;
|
let mut start = 0;
|
||||||
if s.starts_with("-") {
|
if s.starts_with("-") {
|
||||||
|
@ -1703,7 +1710,7 @@ impl BigInt {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn parse_bytes(buf: &[u8], radix: usize) -> Option<BigInt> {
|
pub fn parse_bytes(buf: &[u8], radix: usize) -> Option<BigInt> {
|
||||||
str::from_utf8(buf).ok().and_then(|s| FromStrRadix::from_str_radix(s, radix))
|
str::from_utf8(buf).ok().and_then(|s| FromStrRadix::from_str_radix(s, radix).ok())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1741,6 +1748,31 @@ impl BigInt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum ParseBigIntError {
|
||||||
|
ParseInt(ParseIntError),
|
||||||
|
Other,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for ParseBigIntError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
&ParseBigIntError::ParseInt(ref e) => e.fmt(f),
|
||||||
|
&ParseBigIntError::Other => "failed to parse provided string".fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for ParseBigIntError {
|
||||||
|
fn description(&self) -> &str { "failed to parse bigint/biguint" }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromError<ParseIntError> for ParseBigIntError {
|
||||||
|
fn from_error(err: ParseIntError) -> ParseBigIntError {
|
||||||
|
ParseBigIntError::ParseInt(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod biguint_tests {
|
mod biguint_tests {
|
||||||
use Integer;
|
use Integer;
|
||||||
|
@ -1929,7 +1961,7 @@ mod biguint_tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_shl() {
|
fn test_shl() {
|
||||||
fn check(s: &str, shift: usize, ans: &str) {
|
fn check(s: &str, shift: usize, ans: &str) {
|
||||||
let opt_biguint: Option<BigUint> = FromStrRadix::from_str_radix(s, 16);
|
let opt_biguint: Option<BigUint> = FromStrRadix::from_str_radix(s, 16).ok();
|
||||||
let bu = to_str_radix(&(opt_biguint.unwrap() << shift), 16);
|
let bu = to_str_radix(&(opt_biguint.unwrap() << shift), 16);
|
||||||
assert_eq!(bu.as_slice(), ans);
|
assert_eq!(bu.as_slice(), ans);
|
||||||
}
|
}
|
||||||
|
@ -2051,7 +2083,7 @@ mod biguint_tests {
|
||||||
fn test_shr() {
|
fn test_shr() {
|
||||||
fn check(s: &str, shift: usize, ans: &str) {
|
fn check(s: &str, shift: usize, ans: &str) {
|
||||||
let opt_biguint: Option<BigUint> =
|
let opt_biguint: Option<BigUint> =
|
||||||
FromStrRadix::from_str_radix(s, 16);
|
FromStrRadix::from_str_radix(s, 16).ok();
|
||||||
let bu = to_str_radix(&(opt_biguint.unwrap() >> shift), 16);
|
let bu = to_str_radix(&(opt_biguint.unwrap() >> shift), 16);
|
||||||
assert_eq!(bu.as_slice(), ans);
|
assert_eq!(bu.as_slice(), ans);
|
||||||
}
|
}
|
||||||
|
@ -2571,12 +2603,12 @@ mod biguint_tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let zed: Option<BigUint> = FromStrRadix::from_str_radix("Z", 10);
|
let zed: Option<BigUint> = FromStrRadix::from_str_radix("Z", 10).ok();
|
||||||
assert_eq!(zed, None);
|
assert_eq!(zed, None);
|
||||||
let blank: Option<BigUint> = FromStrRadix::from_str_radix("_", 2);
|
let blank: Option<BigUint> = FromStrRadix::from_str_radix("_", 2).ok();
|
||||||
assert_eq!(blank, None);
|
assert_eq!(blank, None);
|
||||||
let minus_one: Option<BigUint> = FromStrRadix::from_str_radix("-1",
|
let minus_one: Option<BigUint> = FromStrRadix::from_str_radix("-1",
|
||||||
10);
|
10).ok();
|
||||||
assert_eq!(minus_one, None);
|
assert_eq!(minus_one, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2596,7 +2628,7 @@ mod biguint_tests {
|
||||||
fn check(n: usize, s: &str) {
|
fn check(n: usize, s: &str) {
|
||||||
let n = factor(n);
|
let n = factor(n);
|
||||||
let ans = match FromStrRadix::from_str_radix(s, 10) {
|
let ans = match FromStrRadix::from_str_radix(s, 10) {
|
||||||
Some(x) => x, None => panic!()
|
Ok(x) => x, Err(_) => panic!()
|
||||||
};
|
};
|
||||||
assert_eq!(n, ans);
|
assert_eq!(n, ans);
|
||||||
}
|
}
|
||||||
|
@ -3256,7 +3288,7 @@ mod bigint_tests {
|
||||||
let x: BigInt = FromPrimitive::from_int(n).unwrap();
|
let x: BigInt = FromPrimitive::from_int(n).unwrap();
|
||||||
x
|
x
|
||||||
});
|
});
|
||||||
assert_eq!(FromStrRadix::from_str_radix(s, 10), ans);
|
assert_eq!(FromStrRadix::from_str_radix(s, 10).ok(), ans);
|
||||||
}
|
}
|
||||||
check("10", Some(10));
|
check("10", Some(10));
|
||||||
check("1", Some(1));
|
check("1", Some(1));
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
//!
|
//!
|
||||||
//! [newt]: https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method
|
//! [newt]: https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method
|
||||||
|
|
||||||
#![feature(slicing_syntax)]
|
#![feature(slicing_syntax, core)]
|
||||||
#![cfg_attr(test, deny(warnings))]
|
#![cfg_attr(test, deny(warnings))]
|
||||||
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
|
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
|
||||||
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
||||||
|
@ -54,6 +54,7 @@
|
||||||
#![allow(unstable)]
|
#![allow(unstable)]
|
||||||
|
|
||||||
extern crate "rustc-serialize" as rustc_serialize;
|
extern crate "rustc-serialize" as rustc_serialize;
|
||||||
|
extern crate core;
|
||||||
|
|
||||||
pub use bigint::{BigInt, BigUint};
|
pub use bigint::{BigInt, BigUint};
|
||||||
pub use rational::{Rational, BigRational};
|
pub use rational::{Rational, BigRational};
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
use Integer;
|
use Integer;
|
||||||
|
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
|
use std::error::Error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ops::{Add, Div, Mul, Neg, Rem, Sub};
|
use std::ops::{Add, Div, Mul, Neg, Rem, Sub};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
@ -419,42 +420,60 @@ impl<T: fmt::Display + Eq + One> fmt::Display for Ratio<T> {
|
||||||
|
|
||||||
impl<T: FromStr + Clone + Integer + PartialOrd>
|
impl<T: FromStr + Clone + Integer + PartialOrd>
|
||||||
FromStr for Ratio<T> {
|
FromStr for Ratio<T> {
|
||||||
|
type Err = ParseRatioError;
|
||||||
|
|
||||||
/// Parses `numer/denom` or just `numer`.
|
/// Parses `numer/denom` or just `numer`.
|
||||||
fn from_str(s: &str) -> Option<Ratio<T>> {
|
fn from_str(s: &str) -> Result<Ratio<T>, ParseRatioError> {
|
||||||
let mut split = s.splitn(1, '/');
|
let mut split = s.splitn(1, '/');
|
||||||
|
|
||||||
let num = split.next().and_then(|n| FromStr::from_str(n));
|
let n = try!(split.next().ok_or(ParseRatioError));
|
||||||
let den = split.next().or(Some("1")).and_then(|d| FromStr::from_str(d));
|
let num = try!(FromStr::from_str(n).map_err(|_| ParseRatioError));
|
||||||
|
|
||||||
match (num, den) {
|
let d = split.next().unwrap_or("1");
|
||||||
(Some(n), Some(d)) => Some(Ratio::new(n, d)),
|
let den = try!(FromStr::from_str(d).map_err(|_| ParseRatioError));
|
||||||
_ => None
|
|
||||||
}
|
Ok(Ratio::new(num, den))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: FromStrRadix + Clone + Integer + PartialOrd>
|
impl<T: FromStrRadix + Clone + Integer + PartialOrd>
|
||||||
FromStrRadix for Ratio<T> {
|
FromStrRadix for Ratio<T> {
|
||||||
|
type Err = ParseRatioError;
|
||||||
|
|
||||||
/// Parses `numer/denom` where the numbers are in base `radix`.
|
/// Parses `numer/denom` where the numbers are in base `radix`.
|
||||||
fn from_str_radix(s: &str, radix: usize) -> Option<Ratio<T>> {
|
fn from_str_radix(s: &str, radix: usize) -> Result<Ratio<T>, ParseRatioError> {
|
||||||
let split: Vec<&str> = s.splitn(1, '/').collect();
|
let split: Vec<&str> = s.splitn(1, '/').collect();
|
||||||
if split.len() < 2 {
|
if split.len() < 2 {
|
||||||
None
|
Err(ParseRatioError)
|
||||||
} else {
|
} else {
|
||||||
let a_option: Option<T> = FromStrRadix::from_str_radix(
|
let a_result: Result<T, _> = FromStrRadix::from_str_radix(
|
||||||
split[0],
|
split[0],
|
||||||
radix);
|
radix).map_err(|_| ParseRatioError);
|
||||||
a_option.and_then(|a| {
|
a_result.and_then(|a| {
|
||||||
let b_option: Option<T> =
|
let b_result: Result<T, _> =
|
||||||
FromStrRadix::from_str_radix(split[1], radix);
|
FromStrRadix::from_str_radix(split[1], radix).map_err(|_| ParseRatioError);
|
||||||
b_option.and_then(|b| {
|
b_result.and_then(|b| {
|
||||||
Some(Ratio::new(a.clone(), b.clone()))
|
Ok(Ratio::new(a.clone(), b.clone()))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Bubble up specific errors
|
||||||
|
#[derive(Copy, Debug, PartialEq)]
|
||||||
|
pub struct ParseRatioError;
|
||||||
|
|
||||||
|
impl fmt::Display for ParseRatioError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
"failed to parse provided string".fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for ParseRatioError {
|
||||||
|
fn description(&self) -> &str { "failed to parse bigint/biguint" }
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
|
||||||
|
@ -740,7 +759,7 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_to_from_str() {
|
fn test_to_from_str() {
|
||||||
fn test(r: Rational, s: String) {
|
fn test(r: Rational, s: String) {
|
||||||
assert_eq!(FromStr::from_str(&s[]), Some(r));
|
assert_eq!(FromStr::from_str(&s[]), Ok(r));
|
||||||
assert_eq!(r.to_string(), s);
|
assert_eq!(r.to_string(), s);
|
||||||
}
|
}
|
||||||
test(_1, "1".to_string());
|
test(_1, "1".to_string());
|
||||||
|
@ -753,8 +772,8 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_from_str_fail() {
|
fn test_from_str_fail() {
|
||||||
fn test(s: &str) {
|
fn test(s: &str) {
|
||||||
let rational: Option<Rational> = FromStr::from_str(s);
|
let rational: Result<Rational, _> = FromStr::from_str(s);
|
||||||
assert_eq!(rational, None);
|
assert!(rational.is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
let xs = ["0 /1", "abc", "", "1/", "--1/2","3/2/1"];
|
let xs = ["0 /1", "abc", "", "1/", "--1/2","3/2/1"];
|
||||||
|
|
Loading…
Reference in New Issue