diff --git a/Cargo.toml b/Cargo.toml index 81834f4..fdacaef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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 diff --git a/src/bigint.rs b/src/bigint.rs index ba19d62..545b943 100644 --- a/src/bigint.rs +++ b/src/bigint.rs @@ -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(&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(deserializer: &mut D) -> Result 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 for Sign { } } +#[cfg(feature = "serde")] +impl serde::Serialize for Sign { + fn serialize(&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(deserializer: &mut D) -> Result 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 for BigInt { } } +#[cfg(feature = "serde")] +impl serde::Serialize for BigInt { + fn serialize(&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(deserializer: &mut D) -> Result 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`. diff --git a/src/complex.rs b/src/complex.rs index 6524eb9..8f8cfae 100644 --- a/src/complex.rs +++ b/src/complex.rs @@ -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 fmt::Display for Complex where } } +#[cfg(feature = "serde")] +impl serde::Serialize for Complex + where T: serde::Serialize +{ + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where + S: serde::Serializer + { + (&self.re, &self.im).serialize(serializer) + } +} + +#[cfg(feature = "serde")] +impl serde::Deserialize for Complex where + T: serde::Deserialize + Num + Clone +{ + fn deserialize(deserializer: &mut D) -> Result 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)] diff --git a/src/lib.rs b/src/lib.rs index 7244f3c..c9a3099 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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")] diff --git a/src/rational.rs b/src/rational.rs index d5c9464..5778839 100644 --- a/src/rational.rs +++ b/src/rational.rs @@ -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 FromStr for Ratio { } } +#[cfg(feature = "serde")] +impl serde::Serialize for Ratio + where T: serde::Serialize + Clone + Integer + PartialOrd +{ + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where + S: serde::Serializer + { + (self.numer(), self.denom()).serialize(serializer) + } +} + +#[cfg(feature = "serde")] +impl serde::Deserialize for Ratio + where T: serde::Deserialize + Clone + Integer + PartialOrd +{ + fn deserialize(deserializer: &mut D) -> Result 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 }