From e9e1a4de37be235750410bfb9af5f2b25e1e0ead Mon Sep 17 00:00:00 2001 From: bluss Date: Sun, 14 Aug 2016 12:53:37 +0200 Subject: [PATCH 1/2] Move serde/serialize impls to separate files --- src/{arraydeserialize.rs => array_serde.rs} | 44 +++++++++++- src/array_serialize.rs | 76 +++++++++++++++++++++ src/arrayserialize.rs | 50 -------------- src/arraytraits.rs | 65 ------------------ src/lib.rs | 6 +- 5 files changed, 120 insertions(+), 121 deletions(-) rename src/{arraydeserialize.rs => array_serde.rs} (72%) create mode 100644 src/array_serialize.rs delete mode 100644 src/arrayserialize.rs diff --git a/src/arraydeserialize.rs b/src/array_serde.rs similarity index 72% rename from src/arraydeserialize.rs rename to src/array_serde.rs index 97633d155..8aef08d6a 100644 --- a/src/arraydeserialize.rs +++ b/src/array_serde.rs @@ -5,13 +5,51 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -use serde::{self, Deserialize}; - -use std::marker::PhantomData; +use serde::{self, Serialize, Deserialize}; use imp_prelude::*; use super::arraytraits::ARRAY_FORMAT_VERSION; +use super::Elements; + +use std::marker::PhantomData; + +/// **Requires crate feature `"serde"`** +impl Serialize for ArrayBase + where A: Serialize, + D: Dimension + Serialize, + S: Data + +{ + fn serialize(&self, serializer: &mut Se) -> Result<(), Se::Error> + where Se: serde::Serializer + { + let mut struct_state = try!(serializer.serialize_struct("Array", 3)); + try!(serializer.serialize_struct_elt(&mut struct_state, "v", ARRAY_FORMAT_VERSION)); + try!(serializer.serialize_struct_elt(&mut struct_state, "dim", self.dim())); + try!(serializer.serialize_struct_elt(&mut struct_state, "data", Sequence(self.iter()))); + serializer.serialize_struct_end(struct_state) + } +} + +// private iterator wrapper +struct Sequence<'a, A: 'a, D>(Elements<'a, A, D>); + +impl<'a, A, D> Serialize for Sequence<'a, A, D> + where A: Serialize, + D: Dimension + Serialize +{ + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: serde::Serializer + { + let iter = &self.0; + let mut seq_state = try!(serializer.serialize_seq(Some(iter.len()))); + for elt in iter.clone() { + try!(serializer.serialize_seq_elt(&mut seq_state, elt)); + } + serializer.serialize_seq_end(seq_state) + } +} struct ArrayVisitor { _marker_a: PhantomData, diff --git a/src/array_serialize.rs b/src/array_serialize.rs new file mode 100644 index 000000000..600039347 --- /dev/null +++ b/src/array_serialize.rs @@ -0,0 +1,76 @@ +// Copyright 2014-2016 bluss and ndarray developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use serialize::{Encodable, Encoder, Decodable, Decoder}; +use super::arraytraits::ARRAY_FORMAT_VERSION; + +use imp_prelude::*; + +/// **Requires crate feature `"rustc-serialize"`** +impl Encodable for ArrayBase + where A: Encodable, + D: Dimension + Encodable, + S: Data +{ + fn encode(&self, s: &mut E) -> Result<(), E::Error> { + s.emit_struct("Array", 3, |e| { + try!(e.emit_struct_field("v", 0, |e| ARRAY_FORMAT_VERSION.encode(e))); + // FIXME: Write self.dim as a slice (self.shape) + // The problem is decoding it. + try!(e.emit_struct_field("dim", 1, |e| self.dim.encode(e))); + try!(e.emit_struct_field("data", 2, |e| { + let sz = self.dim.size(); + e.emit_seq(sz, |e| { + for (i, elt) in self.iter().enumerate() { + try!(e.emit_seq_elt(i, |e| elt.encode(e))) + } + Ok(()) + }) + })); + Ok(()) + }) + } +} + +/// **Requires crate feature `"rustc-serialize"`** +impl Decodable for ArrayBase + where A: Decodable, + D: Dimension + Decodable, + S: DataOwned +{ + fn decode(d: &mut E) -> Result, E::Error> { + d.read_struct("Array", 3, |d| { + let version: u8 = try!(d.read_struct_field("v", 0, Decodable::decode)); + if version > ARRAY_FORMAT_VERSION { + return Err(d.error("unknown array version")) + } + let dim: D = try!(d.read_struct_field("dim", 1, |d| { + Decodable::decode(d) + })); + + let elements = try!( + d.read_struct_field("data", 2, |d| { + d.read_seq(|d, len| { + if len != dim.size() { + Err(d.error("data and dimension must match in size")) + } else { + let mut elements = Vec::with_capacity(len); + for i in 0..len { + elements.push(try!(d.read_seq_elt::(i, Decodable::decode))) + } + Ok(elements) + } + }) + })); + unsafe { + Ok(ArrayBase::from_shape_vec_unchecked(dim, elements)) + } + }) + } +} + diff --git a/src/arrayserialize.rs b/src/arrayserialize.rs deleted file mode 100644 index 8341aee23..000000000 --- a/src/arrayserialize.rs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2014-2016 bluss and ndarray developers. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. -use serde::{self, Serialize}; - -use imp_prelude::*; - -use super::arraytraits::ARRAY_FORMAT_VERSION; -use super::Elements; - -/// **Requires crate feature `"serde"`** -impl Serialize for ArrayBase - where A: Serialize, - D: Dimension + Serialize, - S: Data - -{ - fn serialize(&self, serializer: &mut Se) -> Result<(), Se::Error> - where Se: serde::Serializer - { - let mut struct_state = try!(serializer.serialize_struct("Array", 3)); - try!(serializer.serialize_struct_elt(&mut struct_state, "v", ARRAY_FORMAT_VERSION)); - try!(serializer.serialize_struct_elt(&mut struct_state, "dim", self.dim())); - try!(serializer.serialize_struct_elt(&mut struct_state, "data", Sequence(self.iter()))); - serializer.serialize_struct_end(struct_state) - } -} - -// private iterator wrapper -struct Sequence<'a, A: 'a, D>(Elements<'a, A, D>); - -impl<'a, A, D> Serialize for Sequence<'a, A, D> - where A: Serialize, - D: Dimension + Serialize -{ - fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> - where S: serde::Serializer - { - let iter = &self.0; - let mut seq_state = try!(serializer.serialize_seq(Some(iter.len()))); - for elt in iter.clone() { - try!(serializer.serialize_seq_elt(&mut seq_state, elt)); - } - serializer.serialize_seq_end(seq_state) - } -} diff --git a/src/arraytraits.rs b/src/arraytraits.rs index 64bbf9e5a..4490a9a9e 100644 --- a/src/arraytraits.rs +++ b/src/arraytraits.rs @@ -212,71 +212,6 @@ unsafe impl Send for ArrayBase // Use version number so we can add a packed format later. pub const ARRAY_FORMAT_VERSION: u8 = 1u8; -/// **Requires crate feature `"rustc-serialize"`** -#[cfg(feature = "rustc-serialize")] -impl Encodable for ArrayBase - where A: Encodable, - D: Dimension + Encodable, - S: Data -{ - fn encode(&self, s: &mut E) -> Result<(), E::Error> { - s.emit_struct("Array", 3, |e| { - try!(e.emit_struct_field("v", 0, |e| ARRAY_FORMAT_VERSION.encode(e))); - // FIXME: Write self.dim as a slice (self.shape) - // The problem is decoding it. - try!(e.emit_struct_field("dim", 1, |e| self.dim.encode(e))); - try!(e.emit_struct_field("data", 2, |e| { - let sz = self.dim.size(); - e.emit_seq(sz, |e| { - for (i, elt) in self.iter().enumerate() { - try!(e.emit_seq_elt(i, |e| elt.encode(e))) - } - Ok(()) - }) - })); - Ok(()) - }) - } -} - -/// **Requires crate feature `"rustc-serialize"`** -#[cfg(feature = "rustc-serialize")] -impl Decodable for ArrayBase - where A: Decodable, - D: Dimension + Decodable, - S: DataOwned -{ - fn decode(d: &mut E) -> Result, E::Error> { - d.read_struct("Array", 3, |d| { - let version: u8 = try!(d.read_struct_field("v", 0, Decodable::decode)); - if version > ARRAY_FORMAT_VERSION { - return Err(d.error("unknown array version")) - } - let dim: D = try!(d.read_struct_field("dim", 1, |d| { - Decodable::decode(d) - })); - - let elements = try!( - d.read_struct_field("data", 2, |d| { - d.read_seq(|d, len| { - if len != dim.size() { - Err(d.error("data and dimension must match in size")) - } else { - let mut elements = Vec::with_capacity(len); - for i in 0..len { - elements.push(try!(d.read_seq_elt::(i, Decodable::decode))) - } - Ok(elements) - } - }) - })); - unsafe { - Ok(ArrayBase::from_shape_vec_unchecked(dim, elements)) - } - }) - } -} - // use "raw" form instead of type aliases here so that they show up in docs /// Implementation of `ArrayView::from(&S)` where `S` is a slice or slicable. diff --git a/src/lib.rs b/src/lib.rs index 262e8ed68..d93a0886e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -116,9 +116,9 @@ pub use shape_builder::{ ShapeBuilder }; mod arraytraits; #[cfg(feature = "serde")] -mod arrayserialize; -#[cfg(feature = "serde")] -mod arraydeserialize; +mod array_serde; +#[cfg(feature = "rustc-serialize")] +mod array_serialize; mod arrayformat; mod data_traits; From a9366216ebd9af258a2da79c99ea677533c638bf Mon Sep 17 00:00:00 2001 From: bluss Date: Sun, 14 Aug 2016 16:24:02 +0200 Subject: [PATCH 2/2] Implement Default for owned Arrays (Array and RcArray) zero-dimensional arrays (using () or Vec::new() as the dimension/D type parameter) will have 1 element in the default state. nonzero-dimensional arrays (using Ix, (Ix, Ix) and so on) will have 0 elements in their default state. --- src/arraytraits.rs | 22 ++++++++++++++++++++++ src/dimension.rs | 2 +- tests/array.rs | 12 ++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/arraytraits.rs b/src/arraytraits.rs index 4490a9a9e..6b4e06992 100644 --- a/src/arraytraits.rs +++ b/src/arraytraits.rs @@ -292,3 +292,25 @@ impl<'a, A: 'a, D, T> AsArray<'a, A, D> for T where T: Into>, D: Dimension, { } + +/// Create an owned array with a default state. +/// +/// The array is created with dimension `D::default()`, which results +/// in for example dimensions `0` and `(0, 0)` with zero elements for the +/// one-dimensional and two-dimensional cases respectively, while for example +/// the zero dimensional case uses `()` (or `Vec::new()`) which +/// results in an array with one element. +/// +/// Since arrays cannot grow, the intention is to use the default value as +/// placeholder. +impl Default for ArrayBase + where S: DataOwned, + D: Dimension, + A: Default, +{ + // NOTE: We can implement Default for non-zero dimensional array views by + // using an empty slice, however we need a trait for nonzero Dimension. + fn default() -> Self { + ArrayBase::default(D::default()) + } +} diff --git a/src/dimension.rs b/src/dimension.rs index 4b9e62b5e..09ad21b62 100644 --- a/src/dimension.rs +++ b/src/dimension.rs @@ -124,7 +124,7 @@ fn stride_offset_checked_arithmetic(dim: &D, strides: &D, index: &D) /// /// ***Don't implement or call methods in this trait, its interface is internal /// to the crate and will evolve at will.*** -pub unsafe trait Dimension : Clone + Eq + Debug + Send + Sync { +pub unsafe trait Dimension : Clone + Eq + Debug + Send + Sync + Default { /// `SliceArg` is the type which is used to specify slicing for this /// dimension. /// diff --git a/tests/array.rs b/tests/array.rs index fa4969538..225dd87b0 100644 --- a/tests/array.rs +++ b/tests/array.rs @@ -1050,3 +1050,15 @@ fn test_view_from_shape_ptr() { view[[0, 1]] = 0; assert_eq!(view, aview2(&[[0, 0, 2], [3, 4, 6]])); } + +#[test] +fn test_default() { + let a = as Default>::default(); + assert_eq!(a, aview2(&[[0.0; 0]; 0])); + + + #[derive(Default, Debug, PartialEq)] + struct Foo(i32); + let b = as Default>::default(); + assert_eq!(b, arr0(Foo::default())); +}