mod broadcast;
mod contiguity;
pub(crate) mod kernels;
mod shape;
mod slice_with;
mod strides;
use serde::ser::SerializeStruct;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub struct Layout<const N: usize> {
shape: [usize; N],
strides: [isize; N],
offset: usize,
}
impl<const N: usize> Layout<N> {
pub fn try_new(
shape: [usize; N],
strides: [isize; N],
offset: usize,
) -> crate::domain::error::Result<Self> {
let candidate = Self::from_parts_unchecked(shape, strides, offset);
candidate.checked_size()?;
candidate.checked_min_max_offsets()?;
Ok(candidate)
}
#[inline]
pub(crate) const fn from_parts_unchecked(
shape: [usize; N],
strides: [isize; N],
offset: usize,
) -> Self {
Self {
shape,
strides,
offset,
}
}
#[inline]
#[must_use]
pub const fn shape(&self) -> [usize; N] {
self.shape
}
#[inline]
#[must_use]
pub const fn strides(&self) -> [isize; N] {
self.strides
}
#[inline]
#[must_use]
pub const fn offset(&self) -> usize {
self.offset
}
}
impl<const N: usize> TryFrom<([usize; N], [isize; N], usize)> for Layout<N> {
type Error = crate::domain::error::LetoError;
#[inline]
fn try_from(
(shape, strides, offset): ([usize; N], [isize; N], usize),
) -> core::result::Result<Self, Self::Error> {
Self::try_new(shape, strides, offset)
}
}
impl<const N: usize> Serialize for Layout<N> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_struct("Layout", 3)?;
state.serialize_field("shape", self.shape.as_slice())?;
state.serialize_field("strides", self.strides.as_slice())?;
state.serialize_field("offset", &self.offset)?;
state.end()
}
}
impl<'de, const N: usize> Deserialize<'de> for Layout<N> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)]
struct LayoutFields {
shape: Vec<usize>,
strides: Vec<isize>,
offset: usize,
}
let fields = LayoutFields::deserialize(deserializer)?;
let shape = fields.shape.try_into().map_err(|values: Vec<usize>| {
serde::de::Error::custom(format!(
"layout shape rank {} does not match expected rank {}",
values.len(),
N
))
})?;
let strides = fields.strides.try_into().map_err(|values: Vec<isize>| {
serde::de::Error::custom(format!(
"layout stride rank {} does not match expected rank {}",
values.len(),
N
))
})?;
Self::try_new(shape, strides, fields.offset).map_err(serde::de::Error::custom)
}
}