Skip to content

Implement Default for owned arrays #213

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 19, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 41 additions & 3 deletions src/arraydeserialize.rs → src/array_serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,51 @@
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<A, D, S> Serialize for ArrayBase<S, D>
where A: Serialize,
D: Dimension + Serialize,
S: Data<Elem = A>

{
fn serialize<Se>(&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<S>(&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<S, Di> {
_marker_a: PhantomData<S>,
Expand Down
76 changes: 76 additions & 0 deletions src/array_serialize.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Copyright 2014-2016 bluss and ndarray developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<A, S, D> Encodable for ArrayBase<S, D>
where A: Encodable,
D: Dimension + Encodable,
S: Data<Elem = A>
{
fn encode<E: Encoder>(&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<A, S, D> Decodable for ArrayBase<S, D>
where A: Decodable,
D: Dimension + Decodable,
S: DataOwned<Elem = A>
{
fn decode<E: Decoder>(d: &mut E) -> Result<ArrayBase<S, D>, 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::<A, _>(i, Decodable::decode)))
}
Ok(elements)
}
})
}));
unsafe {
Ok(ArrayBase::from_shape_vec_unchecked(dim, elements))
}
})
}
}

50 changes: 0 additions & 50 deletions src/arrayserialize.rs

This file was deleted.

87 changes: 22 additions & 65 deletions src/arraytraits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,71 +212,6 @@ unsafe impl<S, D> Send for ArrayBase<S, D>
// 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<A, S, D> Encodable for ArrayBase<S, D>
where A: Encodable,
D: Dimension + Encodable,
S: Data<Elem = A>
{
fn encode<E: Encoder>(&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<A, S, D> Decodable for ArrayBase<S, D>
where A: Decodable,
D: Dimension + Decodable,
S: DataOwned<Elem = A>
{
fn decode<E: Decoder>(d: &mut E) -> Result<ArrayBase<S, D>, 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::<A, _>(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.
Expand Down Expand Up @@ -357,3 +292,25 @@ impl<'a, A: 'a, D, T> AsArray<'a, A, D> for T
where T: Into<ArrayView<'a, A, D>>,
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<A, S, D> Default for ArrayBase<S, D>
where S: DataOwned<Elem=A>,
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())
}
}
2 changes: 1 addition & 1 deletion src/dimension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ fn stride_offset_checked_arithmetic<D>(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.
///
Expand Down
6 changes: 3 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
12 changes: 12 additions & 0 deletions tests/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 = <Array<f32, (Ix, Ix)> as Default>::default();
assert_eq!(a, aview2(&[[0.0; 0]; 0]));


#[derive(Default, Debug, PartialEq)]
struct Foo(i32);
let b = <Array<Foo, ()> as Default>::default();
assert_eq!(b, arr0(Foo::default()));
}