use super::*;
use core::marker::PhantomData;
use serde::de::{
value::{MapAccessDeserializer, SeqAccessDeserializer},
DeserializeSeed, Deserializer, Error, MapAccess, SeqAccess, Visitor,
};
use serde_ndim::de::MakeNDim;
struct ArrayFormatVisitor<A>(PhantomData<fn() -> A>);
impl<A> ArrayFormatVisitor<A> {
const fn new() -> Self {
Self(PhantomData)
}
}
impl<'de, A> Visitor<'de> for ArrayFormatVisitor<A>
where
A: Deserialize<'de> + MakeNDim,
A::Item: Deserialize<'de>,
{
type Value = A;
fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
formatter.write_str("an ndarray object or a nested array sequence")
}
fn visit_seq<S>(self, seq: S) -> Result<Self::Value, S::Error>
where
S: SeqAccess<'de>,
{
serde_ndim::deserialize(SeqAccessDeserializer::new(seq))
}
fn visit_map<M>(self, map: M) -> Result<Self::Value, M::Error>
where
M: MapAccess<'de>,
{
A::deserialize(MapAccessDeserializer::new(map))
}
}
fn deserialize_array_format<'de, A, D>(deserializer: D) -> Result<A, D::Error>
where
A: Deserialize<'de> + MakeNDim,
A::Item: Deserialize<'de>,
D: Deserializer<'de>,
{
if deserializer.is_human_readable() {
deserializer.deserialize_any(ArrayFormatVisitor::<A>::new())
} else {
A::deserialize(deserializer)
}
}
struct ArraySeed<D>(PhantomData<fn() -> D>);
impl<D> ArraySeed<D> {
const fn new() -> Self {
Self(PhantomData)
}
}
impl<'de, D> DeserializeSeed<'de> for ArraySeed<D>
where
D: DataOwned,
D::Elem: Deserialize<'de>,
ArrayBase<D, Ix1>: Deserialize<'de> + MakeNDim<Item = D::Elem>,
{
type Value = ArrayBase<D, Ix1>;
fn deserialize<De>(self, deserializer: De) -> Result<Self::Value, De::Error>
where
De: Deserializer<'de>,
{
deserialize_array_format(deserializer)
}
}
struct GridVisitor<D, const N: usize>(PhantomData<fn() -> D>);
impl<D, const N: usize> GridVisitor<D, N> {
const fn new() -> Self {
Self(PhantomData)
}
}
impl<'de, D, const N: usize> Visitor<'de> for GridVisitor<D, N>
where
D: DataOwned,
D::Elem: Deserialize<'de> + Debug,
ArrayBase<D, Ix1>: Deserialize<'de> + MakeNDim<Item = D::Elem>,
{
type Value = [ArrayBase<D, Ix1>; N];
fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
formatter.write_str("a sequence of arrays")
}
fn visit_seq<S>(self, mut seq: S) -> Result<Self::Value, S::Error>
where
S: SeqAccess<'de>,
{
let mut grid = Vec::with_capacity(N);
while let Some(array) = seq.next_element_seed(ArraySeed::<D>::new())? {
grid.push(array);
}
grid.try_into().map_err(|e: Vec<_>| {
Error::custom(format_args!(
"expected {N} array(s), found {}: {e:?}",
e.len()
))
})
}
}
struct GridVecVisitor<D>(PhantomData<fn() -> D>);
impl<D> GridVecVisitor<D> {
const fn new() -> Self {
Self(PhantomData)
}
}
impl<'de, D> Visitor<'de> for GridVecVisitor<D>
where
D: DataOwned,
D::Elem: Deserialize<'de>,
ArrayBase<D, Ix1>: Deserialize<'de> + MakeNDim<Item = D::Elem>,
{
type Value = Vec<ArrayBase<D, Ix1>>;
fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
formatter.write_str("a sequence of arrays")
}
fn visit_seq<S>(self, mut seq: S) -> Result<Self::Value, S::Error>
where
S: SeqAccess<'de>,
{
let mut grid = Vec::new();
while let Some(array) = seq.next_element_seed(ArraySeed::<D>::new())? {
grid.push(array);
}
Ok(grid)
}
}
pub fn deserialize_grid_arr<'de, D, const N: usize, De>(
deserializer: De,
) -> Result<[ArrayBase<D, Ix1>; N], De::Error>
where
D: DataOwned,
D::Elem: Deserialize<'de> + Debug,
[ArrayBase<D, Ix1>; N]: Deserialize<'de>,
De: Deserializer<'de>,
{
if deserializer.is_human_readable() {
deserializer.deserialize_seq(GridVisitor::<D, N>::new())
} else {
<[ArrayBase<D, Ix1>; N]>::deserialize(deserializer)
}
}
pub fn deserialize_grid_vec<'de, D, De>(
deserializer: De,
) -> Result<Vec<ArrayBase<D, Ix1>>, De::Error>
where
D: DataOwned,
D::Elem: Deserialize<'de>,
De: Deserializer<'de>,
{
if deserializer.is_human_readable() {
deserializer.deserialize_seq(GridVecVisitor::<D>::new())
} else {
Vec::<ArrayBase<D, Ix1>>::deserialize(deserializer)
}
}
pub fn deserialize_fixed<'de, D, const N: usize, De>(
deserializer: De,
) -> Result<ArrayBase<D, Dim<[Ix; N]>>, De::Error>
where
D: DataOwned,
D::Elem: Deserialize<'de>,
Dim<[Ix; N]>: Dimension + Deserialize<'de>,
ArrayBase<D, Dim<[Ix; N]>>: MakeNDim<Item = D::Elem>,
De: Deserializer<'de>,
{
deserialize_array_format(deserializer)
}
pub fn deserialize_dyn<'de, D, De>(deserializer: De) -> Result<ArrayBase<D, IxDyn>, De::Error>
where
D: DataOwned,
D::Elem: Deserialize<'de>,
ArrayBase<D, IxDyn>: MakeNDim<Item = D::Elem>,
De: Deserializer<'de>,
{
deserialize_array_format(deserializer)
}