use crate::error::PResult;
use crate::json::parser::Parser;
use crate::json::writer::Writer;
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 `json::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 \
`p.skip_value()` is legitimate there"
)]
pub trait Read<'de>: Sized {
fn read<O: Options>(&mut self, p: &mut Parser<'de, O>) -> PResult<()>;
}
#[diagnostic::on_unimplemented(
note = "a type becomes writable by being declared with `structio::object!` or \
`#[derive(Structio)]`, or by a `json::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
}
}
#[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 \
`p.skip_value()` is legitimate there"
)]
pub trait ReadAs<'de, T> {
fn read<O: Options>(value: &mut T, p: &mut Parser<'de, O>) -> PResult<()>;
}
#[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
}
}
pub trait ReadKeyAs<T> {
fn from_key(key: &str) -> PResult<T>;
}
pub trait WriteKeyAs<T: ?Sized> {
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, p: &mut Parser<'de, O>) -> PResult<bool>;
}
pub trait WriteObject: Keys {
fn write_fields<O: Options>(&self, w: &mut Writer<'_, O>);
}
pub trait ReadArray<'de>: Elements + Sized {
fn read_element<O: Options>(&mut self, index: usize, p: &mut Parser<'de, O>) -> PResult<()>;
}
pub trait WriteArray: Elements {
fn write_elements<O: Options>(&self, w: &mut Writer<'_, O>);
}
pub trait ReadEnum<'de>: Variants + Sized {
fn read_name<O: Options>(&mut self, index: usize, p: &mut Parser<'de, O>) -> PResult<bool>;
fn read_payload<O: Options>(&mut self, index: usize, p: &mut Parser<'de, O>) -> PResult<bool>;
}
pub trait ReadInternallyTagged<'de>: Variants + Sized {
const TAG: &'static str;
fn read_variant<O: Options>(
&mut self,
index: usize,
p: &mut Parser<'de, O>,
open: usize,
) -> PResult<bool>;
}
#[diagnostic::on_unimplemented(
note = "this is `json::Read` and `json::Write` at once, the bound a JSON-only \
declaration appends to every type parameter; one \
`structio::json_object!` covers both halves",
note = "a `write_only` declaration appends `json::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 {}