Mon, 06 Jan 2025 20:29:25 -0500
More Serialize / Deserialize / Debug derives
--- a/Cargo.toml Mon Dec 30 15:46:28 2024 -0500 +++ b/Cargo.toml Mon Jan 06 20:29:25 2025 -0500 @@ -12,7 +12,7 @@ categories = ["mathematics", "data-structures"] [dependencies] -serde = { version = "1.0", features = ["derive"] } +serde = { version = "1.0", features = ["derive", "rc"] } csv = "~1.3.1" nalgebra = "~0.33.0" num-traits = { version = "~0.2.14", features = ["std"] }
--- a/src/bisection_tree/aggregator.rs Mon Dec 30 15:46:28 2024 -0500 +++ b/src/bisection_tree/aggregator.rs Mon Jan 06 20:29:25 2025 -0500 @@ -2,6 +2,7 @@ Aggregation / summarisation of information in branches of bisection trees. */ +use serde::{Serialize, Deserialize}; use crate::types::*; use crate::sets::Set; use crate::instance::Instance; @@ -33,7 +34,7 @@ } /// An [`Aggregator`] that doesn't aggregate anything. -#[derive(Clone,Debug)] +#[derive(Clone,Debug,Serialize,Deserialize)] pub struct NullAggregator; impl Aggregator for NullAggregator { @@ -47,7 +48,7 @@ } /// Upper and lower bounds on an `F`-valued function. -#[derive(Copy,Clone,Debug)] +#[derive(Copy,Clone,Debug,Serialize,Deserialize)] pub struct Bounds<F>( /// Lower bound pub F,
--- a/src/bisection_tree/bt.rs Mon Dec 30 15:46:28 2024 -0500 +++ b/src/bisection_tree/bt.rs Mon Jan 06 20:29:25 2025 -0500 @@ -43,7 +43,13 @@ /// Node of a [`BT`] bisection tree. /// /// For the type and const parameteres, see the [module level documentation][super]. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(bound( + serialize = "NodeOption<F, D, A, N, P> : Serialize, + A : Serialize,", + deserialize = "NodeOption<F, D, A, N, P> : for<'a> Deserialize<'a>, + A : for<'a> Deserialize<'a>," +))] pub struct Node<F : Num, D, A : Aggregator, const N : usize, const P : usize> { /// The data or branches under the node. pub(super) data : NodeOption<F, D, A, N, P>, @@ -54,7 +60,13 @@ /// Branching information of a [`Node`] of a [`BT`] bisection tree into `P` subnodes. /// /// For the type and const parameters, see the [module level documentation][super]. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(bound( + serialize = "[Node<F, D, A, N, P>; P] : Serialize, + Loc<F, N> : Serialize,", + deserialize = "[Node<F, D, A, N, P>; P] : for<'a> Deserialize<'a>, + Loc<F, N> : for<'a> Deserialize<'a>," +))] pub(super) struct Branches<F : Num, D, A : Aggregator, const N : usize, const P : usize> { /// Point for subdivision of the (unstored) [`Cube`] corresponding to the node. pub(super) branch_at : Loc<F, N>, @@ -198,6 +210,7 @@ } /// An iterator over the $P=2^N$ subcubes of a [`Cube`] subdivided at a point `d`. +#[derive(Debug, Clone)] pub(super) struct SubcubeIter<'b, F : Float, const N : usize, const P : usize> { domain : &'b Cube<F, N>, branch_at : Loc<F, N>, @@ -637,7 +650,15 @@ /// It should be accessed via the [`BTImpl`] trait to hide the `const P : usize` parameter until /// const generics are flexible enough to fix `P=pow(2, N)` and thus also get rid of /// the `BTNodeLookup : BTNode<F, D, A, N>` trait bound. -#[derive(Clone,Debug)] +#[derive(Clone,Debug,Serialize,Deserialize)] +#[serde(bound( + serialize = "Cube<F, N> : Serialize, + M : Serialize, + <BTNodeLookup as BTNode<F, D, A, N>>::Node : Serialize,", + deserialize = "Cube<F, N> : for<'a> Deserialize<'a>, + M : for<'a> Deserialize<'a>, + <BTNodeLookup as BTNode<F, D, A, N>>::Node : for<'a> Deserialize<'a>," +))] pub struct BT< M : Depth, F : Float,
--- a/src/bisection_tree/btfn.rs Mon Dec 30 15:46:28 2024 -0500 +++ b/src/bisection_tree/btfn.rs Mon Jan 06 20:29:25 2025 -0500 @@ -1,5 +1,6 @@ use numeric_literals::replace_float_literals; +use serde::{Serialize, Deserialize}; use std::iter::Sum; use std::marker::PhantomData; use std::sync::Arc; @@ -30,7 +31,7 @@ /// Identifiers of the components ([`SupportGenerator::Id`], usually `usize`) are stored stored /// in a [bisection tree][BTImpl], when one is provided as `bt`. However `bt` may also be `()` /// for a [`PreBTFN`] that is only useful for vector space operations with a full [`BTFN`]. -#[derive(Clone,Debug)] +#[derive(Clone,Debug,Serialize,Deserialize)] pub struct BTFN< F : Float, G : SupportGenerator<F, N>, @@ -39,6 +40,7 @@ > /*where G::SupportType : LocalAnalysis<F, A, N>*/ { bt : BT, generator : Arc<G>, + #[serde(skip)] _phantoms : PhantomData<F>, } @@ -587,14 +589,17 @@ } /// Helper type to use [`P2Refiner`] for maximisation. +#[derive(Debug, Clone, Serialize, Deserialize)] struct RefineMax; /// Helper type to use [`P2Refiner`] for minimisation. +#[derive(Debug, Clone, Serialize, Deserialize)] struct RefineMin; /// A bisection tree [`Refiner`] for maximising or minimising a [`BTFN`]. /// /// The type parameter `T` should be either [`RefineMax`] or [`RefineMin`]. +#[derive(Debug, Clone, Serialize, Deserialize)] struct P2Refiner<F : Float, T> { /// The maximum / minimum should be above / below this threshold. /// If the threshold cannot be satisfied, the refiner will return `None`. @@ -733,6 +738,7 @@ /// The type parameter `T` should be either [`RefineMax`] for upper bound or [`RefineMin`] /// for lower bound. +#[derive(Debug, Clone, Serialize, Deserialize)] struct BoundRefiner<F : Float, T> { /// The upper/lower bound to check for bound : F,
--- a/src/bisection_tree/either.rs Mon Dec 30 15:46:28 2024 -0500 +++ b/src/bisection_tree/either.rs Mon Jan 06 20:29:25 2025 -0500 @@ -1,6 +1,7 @@ use std::iter::Chain; use std::sync::Arc; +use serde::{Serialize, Deserialize}; use crate::types::*; use crate::mapping::{ @@ -20,7 +21,7 @@ /// A structure for storing two [`SupportGenerator`]s summed/chain together. /// /// This is needed to work with sums of different types of [`Support`]s. -#[derive(Debug,Clone)] +#[derive(Debug,Clone,Serialize,Deserialize)] pub struct BothGenerators<A, B>( pub(super) Arc<A>, pub(super) Arc<B>, @@ -29,7 +30,7 @@ /// A structure for a [`Support`] that can be either `A` or `B`. /// /// This is needed to work with sums of different types of [`Support`]s. -#[derive(Debug,Clone)] +#[derive(Debug,Clone,Serialize,Deserialize)] pub enum EitherSupport<A, B> { Left(A), Right(B),
--- a/src/bisection_tree/refine.rs Mon Dec 30 15:46:28 2024 -0500 +++ b/src/bisection_tree/refine.rs Mon Jan 06 20:29:25 2025 -0500 @@ -3,6 +3,7 @@ use std::cmp::{PartialOrd, Ord, Ordering, Ordering::*, max}; use std::marker::PhantomData; use std::sync::{Arc, Mutex, MutexGuard, Condvar}; +use serde::{Serialize, Deserialize}; use crate::types::*; use crate::nanleast::NaNLeast; use crate::sets::Cube; @@ -35,12 +36,20 @@ /// An [`AggregatorSorting`] for [`Bounds`], using the upper/lower bound as the upper/lower key. /// /// See [`LowerBoundSorting`] for the opposite ordering. -pub struct UpperBoundSorting<F : Float>(PhantomData<F>); +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct UpperBoundSorting<F : Float>( + #[serde(skip)] + PhantomData<F> +); /// An [`AggregatorSorting`] for [`Bounds`], using the upper/lower bound as the lower/upper key. /// /// See [`UpperBoundSorting`] for the opposite ordering. -pub struct LowerBoundSorting<F : Float>(PhantomData<F>); +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct LowerBoundSorting<F : Float>( + #[serde(skip)] + PhantomData<F> +); impl<F : Float> AggregatorSorting for UpperBoundSorting<F> { type Agg = Bounds<F>; @@ -136,6 +145,7 @@ } /// Structure for tracking the refinement process in a [`BinaryHeap`]. +#[derive(Debug)] struct RefinementInfo<'a, F, D, A, S, RResult, const N : usize, const P : usize> where F : Float, D : 'static, @@ -228,6 +238,7 @@ /// This is a container for a [`BinaryHeap`] of [`RefinementInfo`]s together with tracking of /// the greatest lower bound of the [`Aggregator`]s of the [`Node`]s therein accroding to /// chosen [`AggregatorSorting`]. +#[derive(Debug)] struct HeapContainer<'a, F, D, A, S, RResult, const N : usize, const P : usize> where F : Float, D : 'static + Copy,
--- a/src/bisection_tree/support.rs Mon Dec 30 15:46:28 2024 -0500 +++ b/src/bisection_tree/support.rs Mon Jan 06 20:29:25 2025 -0500 @@ -2,7 +2,7 @@ /*! Traits for representing the support of a [`Mapping`], and analysing the mapping on a [`Cube`]. */ -use serde::Serialize; +use serde::{Serialize, Deserialize}; use std::ops::{MulAssign,DivAssign,Neg}; use crate::types::{Float, Num}; use crate::maputil::map2; @@ -103,7 +103,13 @@ impl<F : Float, T : GlobalAnalysis<F, Bounds<F>>> Bounded<F> for T { } /// Shift of [`Support`] and [`Mapping`]; output of [`Support::shift`]. -#[derive(Copy,Clone,Debug,Serialize)] // Serialize! but not implemented by Loc. +#[derive(Copy,Clone,Debug,Serialize,Deserialize)] +#[serde(bound( + serialize = "Loc<F, N> : Serialize, + T : Serialize,", + deserialize = "Loc<F, N> : for<'a> Deserialize<'a>, + T : for<'a> Deserialize<'a>", +))] pub struct Shift<T, F, const N : usize> { shift : Loc<F, N>, base_fn : T,
--- a/src/convex.rs Mon Dec 30 15:46:28 2024 -0500 +++ b/src/convex.rs Mon Jan 06 20:29:25 2025 -0500 @@ -3,6 +3,7 @@ */ use std::marker::PhantomData; +use serde::{Serialize, Deserialize}; use crate::types::*; use crate::mapping::{Mapping, Space}; use crate::linops::IdOp; @@ -68,6 +69,7 @@ } +#[derive(Serialize,Deserialize,Debug,Clone)] pub struct NormConstraint<F : Float, E : NormExponent> { radius : F, norm : NormMapping<F, E>, @@ -160,6 +162,7 @@ } } +#[derive(Serialize,Deserialize,Debug,Clone)] pub struct NormProjection<F : Float, E : NormExponent> { radius : F, exponent : E, @@ -194,7 +197,11 @@ /// The zero mapping -pub struct Zero<Domain : Space, F : Num>(PhantomData<(Domain, F)>); +#[derive(Serialize,Deserialize,Debug,Clone)] +pub struct Zero<Domain : Space, F : Num>( + #[serde(skip)] + PhantomData<(Domain, F)> +); impl<Domain : Space, F : Num> Zero<Domain, F> { pub fn new() -> Self { @@ -247,7 +254,11 @@ /// The zero indicator -pub struct ZeroIndicator<Domain : Space, F : Num>(PhantomData<(Domain, F)>); +#[derive(Serialize,Deserialize,Debug,Clone)] +pub struct ZeroIndicator<Domain : Space, F : Num>( + #[serde(skip)] + PhantomData<(Domain, F)> +); impl<Domain : Space, F : Num> ZeroIndicator<Domain, F> { pub fn new() -> Self {
--- a/src/discrete_gradient.rs Mon Dec 30 15:46:28 2024 -0500 +++ b/src/discrete_gradient.rs Mon Jan 06 20:29:25 2025 -0500 @@ -2,6 +2,7 @@ Simple disrete gradient operators */ use numeric_literals::replace_float_literals; +use serde::{Serialize, Deserialize}; use nalgebra::{ DVector, Matrix, U1, Storage, StorageMut, Dyn }; @@ -10,23 +11,32 @@ use crate::linops::{Mapping, Linear, BoundedLinear, Adjointable, GEMV}; use crate::norms::{Norm, L2}; -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, Serialize, Deserialize)] /// Forward differences with Neumann boundary conditions pub struct ForwardNeumann; -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, Serialize, Deserialize)] /// Forward differences with Dirichlet boundary conditions pub struct ForwardDirichlet; -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, Serialize, Deserialize)] /// Backward differences with Dirichlet boundary conditions pub struct BackwardDirichlet; -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, Serialize, Deserialize)] /// Backward differences with Neumann boundary conditions pub struct BackwardNeumann; /// Finite differences gradient +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(bound( + serialize = "[usize; N] : Serialize, + B : Serialize, + F : Serialize,", + deserialize = "[usize; N] : for<'a> Deserialize<'a>, + B : for<'a> Deserialize<'a>, + F : for<'a> Deserialize<'a>," +))] pub struct Grad< F : Float + nalgebra::RealField, B : Discretisation<F>,
--- a/src/fe_model/p2_local_model.rs Mon Dec 30 15:46:28 2024 -0500 +++ b/src/fe_model/p2_local_model.rs Mon Jan 06 20:29:25 2025 -0500 @@ -2,6 +2,7 @@ Second order polynomical (P2) models on real intervals and planar 2D simplices. */ +use serde::{Serialize, Deserialize}; use crate::types::*; use crate::loc::Loc; use crate::sets::{Set,NPolygon,SpannedHalfspace}; @@ -16,6 +17,11 @@ /// /// The type parameter `D` indicates the number of nodes. (Rust's const generics do not currently /// allow its automatic calculation from `N`.) +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(bound( + serialize = "[Loc<F, N>; D] : Serialize", + deserialize = "[Loc<F, N>; D] : for<'a> Deserialize<'a>", +))] pub struct Simplex<F : Float, const N : usize, const D : usize>(pub [Loc<F, N>; D]); /// A two-dimensional planar simplex pub type PlanarSimplex<F> = Simplex<F, 2, 3>; @@ -119,6 +125,15 @@ } /// A local second order polynomical model of dimension `N` with `E` edges +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(bound( + serialize = "F : Serialize, + Loc<F, N> : Serialize, + Loc<F, E> : Serialize", + deserialize = "F : for<'a> Deserialize<'a>, + Loc<F, N> : for<'a> Deserialize<'a>, + Loc<F, E> : for<'a> Deserialize<'a>", +))] pub struct P2LocalModel<F : Num, const N : usize, const E : usize/*, const V : usize, const Q : usize*/> { a0 : F, a1 : Loc<F, N>,
--- a/src/loc.rs Mon Dec 30 15:46:28 2024 -0500 +++ b/src/loc.rs Mon Jan 06 20:29:25 2025 -0500 @@ -13,14 +13,18 @@ use crate::linops::{AXPY, Mapping, Linear}; use crate::instance::{Instance, BasicDecomposition}; use crate::mapping::Space; -use serde::ser::{Serialize, Serializer, SerializeSeq}; +use serde::{Serialize, Deserialize}; /// A container type for (short) `N`-dimensional vectors of element type `F`. /// /// Supports basic operations of an [`Euclidean`] space, several [`Norm`]s, and /// fused [`AXPY`] operations, among others. -#[derive(Copy,Clone,Debug,PartialEq,Eq)] +#[derive(Copy,Clone,Debug,PartialEq,Eq,Serialize,Deserialize)] +#[serde(bound( + serialize = "[F; N] : Serialize", + deserialize = "[F; N] : for<'a> Deserialize<'a>" +))] pub struct Loc<F, const N : usize>( /// An array of the elements of the vector pub [F; N] @@ -39,23 +43,6 @@ } } -// Need to manually implement as [F; N] serialisation is provided only for some N. -impl<F, const N : usize> Serialize for Loc<F, N> -where - F: Serialize, -{ - fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> - where - S: Serializer, - { - let mut seq = serializer.serialize_seq(Some(N))?; - for e in self.iter() { - seq.serialize_element(e)?; - } - seq.end() - } -} - impl<F, const N : usize> Loc<F, N> { /// Creates a new `Loc` vector from an array. #[inline]
--- a/src/norms.rs Mon Dec 30 15:46:28 2024 -0500 +++ b/src/norms.rs Mon Jan 06 20:29:25 2025 -0500 @@ -2,7 +2,7 @@ Norms, projections, etc. */ -use serde::Serialize; +use serde::{Serialize, Deserialize}; use std::marker::PhantomData; use crate::types::*; use crate::euclidean::*; @@ -12,10 +12,11 @@ // Abstract norms // -#[derive(Copy,Clone,Debug)] +#[derive(Copy,Clone,Debug, Serialize, Deserialize)] /// Helper structure to convert a [`NormExponent`] into a [`Mapping`] pub struct NormMapping<F : Float, E : NormExponent>{ pub(crate) exponent : E, + #[serde(skip)] _phantoms : PhantomData<F> } @@ -30,29 +31,29 @@ } /// Exponent type for the 1-[`Norm`]. -#[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] +#[derive(Copy,Debug,Clone,Serialize,Deserialize,Eq,PartialEq)] pub struct L1; impl NormExponent for L1 {} /// Exponent type for the 2-[`Norm`]. -#[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] +#[derive(Copy,Debug,Clone,Serialize,Deserialize,Eq,PartialEq)] pub struct L2; impl NormExponent for L2 {} /// Exponent type for the ∞-[`Norm`]. -#[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] +#[derive(Copy,Debug,Clone,Serialize,Deserialize,Eq,PartialEq)] pub struct Linfinity; impl NormExponent for Linfinity {} /// Exponent type for 2,1-[`Norm`]. /// (1-norm over a domain Ω, 2-norm of a vector at each point of the domain.) -#[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] +#[derive(Copy,Debug,Clone,Serialize,Deserialize,Eq,PartialEq)] pub struct L21; impl NormExponent for L21 {} /// Norms for pairs (a, b). ‖(a,b)‖ = ‖(‖a‖_A, ‖b‖_B)‖_J /// For use with [`crate::direct_product::Pair`] -#[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] +#[derive(Copy,Debug,Clone,Serialize,Deserialize,Eq,PartialEq)] pub struct PairNorm<A, B, J>(pub A, pub B, pub J); impl<A, B, J> NormExponent for PairNorm<A, B, J> @@ -63,7 +64,7 @@ /// /// The parameter γ of this type is the smoothing factor. Zero means no smoothing, and higher /// values more smoothing. Behaviour with γ < 0 is undefined. -#[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] +#[derive(Copy,Debug,Clone,Serialize,Deserialize,Eq,PartialEq)] pub struct HuberL1<F : Float>(pub F); impl<F : Float> NormExponent for HuberL1<F> {} @@ -71,7 +72,7 @@ /// /// The parameter γ of this type is the smoothing factor. Zero means no smoothing, and higher /// values more smoothing. Behaviour with γ < 0 is undefined. -#[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] +#[derive(Copy,Debug,Clone,Serialize,Deserialize,Eq,PartialEq)] pub struct HuberL21<F : Float>(pub F); impl<F : Float> NormExponent for HuberL21<F> {}
--- a/src/operator_arithmetic.rs Mon Dec 30 15:46:28 2024 -0500 +++ b/src/operator_arithmetic.rs Mon Jan 06 20:29:25 2025 -0500 @@ -2,7 +2,7 @@ Arithmetic of [`Mapping`]s. */ -use serde::Serialize; +use serde::{Serialize, Deserialize}; use crate::types::*; use crate::instance::{Space, Instance}; use crate::mapping::{Mapping, DifferentiableImpl, DifferentiableMapping}; @@ -22,7 +22,7 @@ } /// Weighting of a [`Mapping`] by scalar multiplication. -#[derive(Copy,Clone,Debug,Serialize)] +#[derive(Copy,Clone,Debug,Serialize,Deserialize)] pub struct Weighted<T, C : Constant> { /// The weight pub weight : C, @@ -73,7 +73,7 @@ } /// A sum of [`Mapping`]s. -#[derive(Serialize, Debug, Clone)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct MappingSum<M>(Vec<M>); impl< M> MappingSum<M> {
--- a/src/sets.rs Mon Dec 30 15:46:28 2024 -0500 +++ b/src/sets.rs Mon Jan 06 20:29:25 2025 -0500 @@ -7,7 +7,7 @@ use crate::loc::Loc; use crate::euclidean::Euclidean; use crate::instance::{Space, Instance}; -use serde::Serialize; +use serde::{Serialize, Deserialize}; pub mod cube; pub use cube::Cube; @@ -62,7 +62,7 @@ /// /// The halfspace is $H = \\{ t v + a \mid a^⊤ v = 0 \\}$, where $v$ is the orthogonal /// vector and $t$ the offset. -#[derive(Clone,Copy,Debug,Serialize,Eq,PartialEq)] +#[derive(Clone,Copy,Debug,Serialize,Deserialize,Eq,PartialEq)] pub struct Halfspace<A, F> where A : Euclidean<F>, F : Float { pub orthogonal : A, pub offset : F, @@ -116,7 +116,11 @@ } /// Polygons defined by `N` `Halfspace`s. -#[derive(Clone,Copy,Debug,Eq,PartialEq)] +#[derive(Clone,Copy,Debug,Eq,PartialEq,Serialize,Deserialize)] +#[serde(bound( + serialize = "[Halfspace<A,F>; N] : Serialize", + deserialize = "[Halfspace<A,F>; N] : for<'a> Deserialize<'a>" +))] pub struct NPolygon<A, F, const N : usize>(pub [Halfspace<A,F>; N]) where A : Euclidean<F>, F : Float;
--- a/src/sets/cube.rs Mon Dec 30 15:46:28 2024 -0500 +++ b/src/sets/cube.rs Mon Jan 06 20:29:25 2025 -0500 @@ -16,7 +16,7 @@ ``` */ -use serde::ser::{Serialize, Serializer, SerializeTupleStruct}; +use serde::{Serialize, Deserialize}; use crate::types::*; use crate::loc::Loc; use crate::sets::SetOrd; @@ -30,25 +30,14 @@ /// A multi-dimensional cube $∏_{i=1}^N [a_i, b_i)$ with the starting and ending points /// along $a_i$ and $b_i$ along each dimension of type `U`. -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct Cube<U : Num, const N : usize>(pub(super) [[U; 2]; N]); - -// Need to manually implement as [F; N] serialisation is provided only for some N. -impl<F : Num + Serialize, const N : usize> Serialize for Cube<F, N> -where - F: Serialize, -{ - fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> - where - S: Serializer, - { - let mut ts = serializer.serialize_tuple_struct("Cube", N)?; - for e in self.0.iter() { - ts.serialize_field(e)?; - } - ts.end() - } -} +#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(bound( + serialize = "[[U; 2]; N] : Serialize", + deserialize = "[[U; 2]; N] : for<'a> Deserialize<'a>", +))] +pub struct Cube<U : Num, const N : usize>( + pub(super) [[U; 2]; N] +); impl<A : Num, const N : usize> FixedLength<N> for Cube<A,N> { type Iter = std::array::IntoIter<[A; 2], N>;
--- a/src/types.rs Mon Dec 30 15:46:28 2024 -0500 +++ b/src/types.rs Mon Jan 06 20:29:25 2025 -0500 @@ -60,7 +60,8 @@ /// Trait for general numeric types pub trait Num : 'static + Copy + Sync + Send + num::Num + num_traits::NumAssign + std::iter::Sum + std::iter::Product - + std::fmt::Debug + std::fmt::Display + serde::Serialize + + std::fmt::Debug + std::fmt::Display + + serde::Serialize + CastFrom<u8> + CastFrom<u16> + CastFrom<u32> + CastFrom<u64> + CastFrom<u128> + CastFrom<usize> + CastFrom<i8> + CastFrom<i16> + CastFrom<i32> + CastFrom<i64>