Auto merge of #171 - erickt:serde, r=hauleth

Add support for Serde 0.7.

Serde 0.7 dropped it's dependency on num, so this patch moves the implementations here. For the sake of a better implementation, this just serializes BigUint as a `Vec<u32>`, `BigInt` as a `(u8, Vec<u32>)`, `Complex<T>` as a `(T, T)`, and `Ratio<T>` as a `(T, T)`.
This commit is contained in:
Homu 2016-02-27 20:17:18 +09:00
commit 9b0d4c91cb
5 changed files with 137 additions and 1 deletions

View File

@ -14,8 +14,9 @@ complex, rational, range iterators, generic integers, and more!
"""
[dependencies]
rustc-serialize = { version = "0.3.13", optional = true }
rand = { version = "0.3.8", optional = true }
rustc-serialize = { version = "0.3.13", optional = true }
serde = { version = "^0.7.0", optional = true }
[dev-dependencies]
# Some tests of non-rand functionality still use rand because the tests

View File

@ -79,6 +79,9 @@ use std::{f32, f64};
use std::{u8, i64, u64};
use std::ascii::AsciiExt;
#[cfg(feature = "serde")]
use serde;
// Some of the tests of non-RNG-based functionality are randomized using the
// RNG-based functionality, so the RNG-based functionality needs to be enabled
// for tests.
@ -1723,6 +1726,27 @@ impl BigUint {
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for BigUint {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where
S: serde::Serializer
{
self.data.serialize(serializer)
}
}
#[cfg(feature = "serde")]
impl serde::Deserialize for BigUint {
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error> where
D: serde::Deserializer,
{
let data = try!(Vec::deserialize(deserializer));
Ok(BigUint {
data: data,
})
}
}
// `DoubleBigDigit` size dependent
/// Returns the greatest power of the radix <= big_digit::BASE
#[inline]
@ -1809,6 +1833,36 @@ impl Mul<Sign> for Sign {
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for Sign {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where
S: serde::Serializer
{
match *self {
Sign::Minus => (-1i8).serialize(serializer),
Sign::NoSign => 0i8.serialize(serializer),
Sign::Plus => 1i8.serialize(serializer),
}
}
}
#[cfg(feature = "serde")]
impl serde::Deserialize for Sign {
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error> where
D: serde::Deserializer,
{
use serde::de::Error;
let sign: i8 = try!(serde::Deserialize::deserialize(deserializer));
match sign {
-1 => Ok(Sign::Minus),
0 => Ok(Sign::NoSign),
1 => Ok(Sign::Plus),
_ => Err(D::Error::invalid_value("sign must be -1, 0, or 1")),
}
}
}
/// A big signed integer type.
#[derive(Clone, Debug, Hash)]
#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))]
@ -2398,6 +2452,28 @@ impl From<BigUint> for BigInt {
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for BigInt {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where
S: serde::Serializer
{
(self.sign, &self.data).serialize(serializer)
}
}
#[cfg(feature = "serde")]
impl serde::Deserialize for BigInt {
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error> where
D: serde::Deserializer,
{
let (sign, data) = try!(serde::Deserialize::deserialize(deserializer));
Ok(BigInt {
sign: sign,
data: data,
})
}
}
/// A generic trait for converting a value to a `BigInt`.
pub trait ToBigInt {
/// Converts the value of `self` to a `BigInt`.

View File

@ -14,6 +14,9 @@
use std::fmt;
use std::ops::{Add, Div, Mul, Neg, Sub};
#[cfg(feature = "serde")]
use serde;
use {Zero, One, Num, Float};
// FIXME #1284: handle complex NaN & infinity etc. This
@ -567,6 +570,29 @@ impl<T> fmt::Display for Complex<T> where
}
}
#[cfg(feature = "serde")]
impl<T> serde::Serialize for Complex<T>
where T: serde::Serialize
{
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where
S: serde::Serializer
{
(&self.re, &self.im).serialize(serializer)
}
}
#[cfg(feature = "serde")]
impl<T> serde::Deserialize for Complex<T> where
T: serde::Deserialize + Num + Clone
{
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error> where
D: serde::Deserializer,
{
let (re, im) = try!(serde::Deserialize::deserialize(deserializer));
Ok(Complex::new(re, im))
}
}
#[cfg(test)]
mod test {
#![allow(non_upper_case_globals)]

View File

@ -66,6 +66,9 @@ extern crate rustc_serialize;
#[cfg(any(feature = "rand", all(feature = "bigint", test)))]
extern crate rand;
#[cfg(feature = "serde")]
extern crate serde;
#[cfg(feature = "bigint")]
pub use bigint::{BigInt, BigUint};
#[cfg(feature = "rational")]

View File

@ -18,6 +18,9 @@ use std::fmt;
use std::ops::{Add, Div, Mul, Neg, Rem, Sub};
use std::str::FromStr;
#[cfg(feature = "serde")]
use serde;
#[cfg(feature = "bigint")]
use bigint::{BigInt, BigUint, Sign};
use traits::{FromPrimitive, Float, PrimInt};
@ -528,6 +531,33 @@ impl<T: FromStr + Clone + Integer> FromStr for Ratio<T> {
}
}
#[cfg(feature = "serde")]
impl<T> serde::Serialize for Ratio<T>
where T: serde::Serialize + Clone + Integer + PartialOrd
{
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where
S: serde::Serializer
{
(self.numer(), self.denom()).serialize(serializer)
}
}
#[cfg(feature = "serde")]
impl<T> serde::Deserialize for Ratio<T>
where T: serde::Deserialize + Clone + Integer + PartialOrd
{
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error> where
D: serde::Deserializer,
{
let (numer, denom) = try!(serde::Deserialize::deserialize(deserializer));
if denom == Zero::zero() {
Err(serde::de::Error::invalid_value("denominator is zero"))
} else {
Ok(Ratio::new_raw(numer, denom))
}
}
}
// FIXME: Bubble up specific errors
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct ParseRatioError { kind: RatioErrorKind }