use crate::beve::reader::{Key, Reader};
use crate::beve::writer::Writer;
use crate::error::PResult;
use crate::options::Options;
use crate::traits::{Elements, Keys, Variants};
#[diagnostic::on_unimplemented(
note = "a type becomes readable by being declared with `structio::object!` or \
`#[derive(Structio)]`, or by a `beve::Read` impl written by hand",
note = "a declaration generates both directions unless it narrows to one: a \
struct that is only ever written is declared \
`object!(write_only ..)` or `#[structio(write_only)]`, and then \
nothing in it needs a read impl",
note = "where the struct really is read, a stub whose body is \
`r.skip_value()` is legitimate there"
)]
pub trait Read<'de>: Sized {
fn read<O: Options>(&mut self, r: &mut Reader<'de, O>) -> PResult<()>;
fn read_bulk<O: Options>(
_out: &mut Vec<Self>,
_n: usize,
_elem: u8,
_r: &mut Reader<'de, O>,
) -> PResult<bool> {
Ok(false)
}
}
#[diagnostic::on_unimplemented(
note = "a type becomes writable by being declared with `structio::object!` or \
`#[derive(Structio)]`, or by a `beve::Write` impl written by hand",
note = "the direction axis narrows only to the write half -- there is no \
`read_only` -- so a type used in a struct that is only ever read \
still needs this impl",
note = "there is no empty stub: a member that writes nothing truncates the \
object. `w.write_null()` with `is_null` returning `true` lets \
`SkipNull` drop the member"
)]
pub trait Write {
fn write<O: Options>(&self, w: &mut Writer<'_, O>);
#[inline]
fn is_null(&self) -> bool {
false
}
const ARRAY: Option<&'static [u8]> = None;
fn write_payload<O: Options>(items: &[Self], w: &mut Writer<'_, O>)
where
Self: Sized,
{
let _ = (items, w);
unreachable!("structio: a typed array without a payload writer")
}
}
#[diagnostic::on_unimplemented(
note = "`{Self}` is the adapter the field named; it is what carries the impl, \
rather than the field's own type",
note = "a declaration generates both directions unless it narrows to one: an \
adapter in a struct declared `write_only` carries the write half \
alone",
note = "where the struct really is read, a stub whose body is \
`r.skip_value()` is legitimate there"
)]
pub trait ReadAs<'de, T> {
fn read<O: Options>(value: &mut T, r: &mut Reader<'de, O>) -> PResult<()>;
#[inline]
fn read_bulk<O: Options>(
_out: &mut Vec<T>,
_n: usize,
_elem: u8,
_r: &mut Reader<'de, O>,
) -> PResult<bool> {
Ok(false)
}
}
#[diagnostic::on_unimplemented(
note = "`{Self}` is the adapter the field named; it is what carries the impl, \
rather than the field's own type",
note = "the direction axis narrows only to the write half, so an adapter \
used in a struct that is only ever read still needs this half",
note = "there is no empty stub: a member that writes nothing truncates the \
object. `w.write_null()` with `is_null` returning `true` lets \
`SkipNull` drop the member"
)]
pub trait WriteAs<T: ?Sized> {
fn write<O: Options>(value: &T, w: &mut Writer<'_, O>);
#[inline]
fn is_null(value: &T) -> bool {
let _ = value;
false
}
const ARRAY: Option<&'static [u8]> = None;
fn write_payload<O: Options>(items: &[T], w: &mut Writer<'_, O>)
where
T: Sized,
{
let _ = (items, w);
unreachable!("structio: a typed array without a payload writer")
}
}
pub trait ReadKeyAs<T> {
fn from_key(key: Key<'_>) -> PResult<T>;
}
pub trait WriteKeyAs<T: ?Sized> {
const OBJECT: u8;
fn write_key<O: Options>(value: &T, w: &mut Writer<'_, O>);
}
pub trait ReadObject<'de>: Keys + Sized {
fn read_field<O: Options>(
&mut self,
index: usize,
key: &[u8],
r: &mut Reader<'de, O>,
) -> PResult<bool>;
}
pub trait WriteObject: Keys {
fn write_fields<O: Options>(&self, w: &mut Writer<'_, O>);
fn count_fields<O: Options>(&self) -> usize;
}
pub trait ReadArray<'de>: Elements + Sized {
fn read_element<O: Options>(&mut self, index: usize, r: &mut Reader<'de, O>) -> PResult<()>;
}
pub trait WriteArray: Elements {
fn write_elements<O: Options>(&self, w: &mut Writer<'_, O>);
const ARRAY: Option<&'static [u8]> = None;
fn write_payload<O: Options>(&self, w: &mut Writer<'_, O>) {
let _ = w;
unreachable!("structio: a typed array without a payload writer")
}
}
pub trait ReadEnum<'de>: Variants + Sized {
fn read_name(&mut self, index: usize, name: &[u8]) -> PResult<bool>;
fn read_payload<O: Options>(
&mut self,
index: usize,
name: &[u8],
r: &mut Reader<'de, O>,
) -> PResult<bool>;
}
pub trait ReadInternallyTagged<'de>: Variants + Sized {
const TAG: &'static str;
fn read_variant<O: Options>(
&mut self,
index: usize,
name: &[u8],
r: &mut Reader<'de, O>,
remaining: usize,
open: usize,
) -> PResult<bool>;
}
#[diagnostic::on_unimplemented(
note = "this is `beve::Read` and `beve::Write` at once, the bound a BEVE-only \
declaration appends to every type parameter; one \
`structio::beve_object!` covers both halves",
note = "a `write_only` declaration appends `beve::Write` instead, which is \
this without the read half"
)]
pub trait ReadWrite: for<'de> Read<'de> + Write {}
impl<T> ReadWrite for T where T: for<'de> Read<'de> + Write {}
#[diagnostic::on_unimplemented(note = "this is `beve::Read` from a document of any lifetime plus \
`Default`, the bound for a function that hands back a value parsed \
out of a buffer it owns; `Default` is there because \
`beve::Read::read` fills a value that already exists")]
pub trait ReadOwned: Default + for<'de> Read<'de> {}
impl<T> ReadOwned for T where T: Default + for<'de> Read<'de> {}