use core::marker::PhantomData;
use anybytes::view::ViewError;
use anybytes::{Bytes, View};
use zerocopy::{Immutable, IntoBytes, KnownLayout, TryFromBytes};
use crate::blob::{Blob, BlobEncoding, TryFromBlob};
use crate::macros::entity;
use crate::metadata;
use crate::metadata::MetaDescribe;
use crate::trible::Fragment;
pub trait ArrayElement: MetaDescribe + 'static {
type Native: IntoBytes + Immutable + TryFromBytes + KnownLayout + Sync + Send + 'static;
}
pub struct Array<T: ArrayElement>(PhantomData<T>);
impl<T: ArrayElement> BlobEncoding for Array<T> {}
impl<T: ArrayElement> MetaDescribe for Array<T> {
fn describe() -> Fragment {
let mut core = entity! {
metadata::array_item_schema*: T::describe(),
metadata::tag: metadata::KIND_BLOB_ENCODING,
};
let id = core.root().expect("rooted");
let id_ref = crate::id::ExclusiveId::force_ref(&id);
core += entity! { id_ref @
metadata::name: "array",
metadata::description:
"Flat array of typed values in native byte order. \
Shape is stored externally in TribleSpace triples.",
};
core
}
}
impl<T: ArrayElement> crate::inline::Encodes<Vec<T::Native>> for Array<T>
where
crate::inline::encodings::hash::Handle<Array<T>>: crate::inline::InlineEncoding,
{
type Output = Blob<Array<T>>;
fn encode(source: Vec<T::Native>) -> Blob<Array<T>> {
Blob::new(Bytes::from_source(source))
}
}
impl<T: ArrayElement> TryFromBlob<Array<T>> for Bytes {
type Error = core::convert::Infallible;
fn try_from_blob(blob: Blob<Array<T>>) -> Result<Self, Self::Error> {
Ok(blob.bytes)
}
}
pub mod elements {
use super::ArrayElement;
use crate::macros::entity;
use crate::metadata::{self, MetaDescribe};
use crate::trible::Fragment;
macro_rules! impl_array_element {
($marker:ident, $native:ty, $id:expr, $doc:expr) => {
#[doc = $doc]
pub struct $marker;
impl MetaDescribe for $marker {
fn describe() -> Fragment {
let id = crate::id_hex!($id);
entity! { crate::id::ExclusiveId::force_ref(&id) @
metadata::name: stringify!($marker),
metadata::description: $doc,
}
}
}
impl ArrayElement for $marker {
type Native = $native;
}
};
}
impl_array_element!(
F32,
f32,
"92F4DB8D84519C8D6E212CB810FF40D4",
"32-bit IEEE-754 float."
);
impl_array_element!(
F64,
f64,
"FA3AD8DEC844D5F409AB728269B7A3FE",
"64-bit IEEE-754 float."
);
impl_array_element!(
U8,
u8,
"D16AC7C02F25E4799F4D47EB1E51EF6E",
"Unsigned 8-bit integer."
);
impl_array_element!(
U16,
u16,
"C14453D98F283B96A1010A9F24D53B17",
"Unsigned 16-bit integer."
);
impl_array_element!(
U32,
u32,
"1B9DD214A02C58D9141EF802273120F8",
"Unsigned 32-bit integer."
);
impl_array_element!(
U64,
u64,
"323C0143534D3AD4898D69EA5597414A",
"Unsigned 64-bit integer."
);
impl_array_element!(
I8,
i8,
"E68060AF27227583CB1AEDF89E17E278",
"Signed 8-bit integer."
);
impl_array_element!(
I16,
i16,
"E72199687209A576562B5BD7196FD755",
"Signed 16-bit integer."
);
impl_array_element!(
I32,
i32,
"AB831A6CCDAF7F49BA5BEADEA32CA04E",
"Signed 32-bit integer."
);
impl_array_element!(
I64,
i64,
"53426475A3C695420B23C329285DCA57",
"Signed 64-bit integer."
);
}
impl<T: ArrayElement> TryFromBlob<Array<T>> for View<[T::Native]> {
type Error = ViewError;
fn try_from_blob(blob: Blob<Array<T>>) -> Result<Self, Self::Error> {
blob.bytes.view()
}
}