use std::collections::{BTreeMap, HashMap};
use std::marker::PhantomData;
pub use super::expand::Expand;
use crate::binary::{Decoder, Writer};
use crate::frame::{Packer, Unpacker};
use crate::model::borrowed::ValueRef;
use crate::model::value::{Map, Ref, Seg, Value};
use crate::schema::{Kinds, Reader, Schema, Shape, is_metadata_key};
pub trait With<F> {
fn shape() -> Shape;
fn read(v: &ValueRef<'_>, cx: &mut Reader<'_>) -> Option<F>;
fn write(f: &F) -> Value;
#[must_use]
fn absent() -> Option<F> {
None
}
fn skip(_f: &F) -> bool {
false
}
fn encode(f: &F, w: &mut Writer) {
w.value(&Self::write(f));
}
fn write_text(f: &F, w: &mut crate::text::Writer) {
w.value(&Self::write(f));
}
fn decode(d: &mut Decoder<'_>) -> Option<F> {
let arena = bumpalo::Bump::new();
let v = d.value_ref(&arena).ok()?;
let mut cx = Reader::new();
let f = Self::read(&v, &mut cx)?;
cx.problems.is_empty().then_some(f)
}
fn pack(f: &F, p: &mut Packer) {
let mut w = Writer::body();
Self::encode(f, &mut w);
p.put_bytes(&w.finish());
}
fn unpack(u: &mut Unpacker<'_>) -> Option<F> {
let mut d = Decoder::body(u.bytes()?);
let f = Self::decode(&mut d)?;
d.at_end().then_some(f)
}
}
#[derive(Debug)]
pub struct RefTo<K>(PhantomData<K>);
impl<K: Kinds> With<K::Id> for RefTo<K> {
fn shape() -> Shape {
super::ref_shape::<K>()
}
fn read(v: &ValueRef<'_>, cx: &mut Reader<'_>) -> Option<K::Id> {
super::read_id::<K>(v, cx)
}
fn write(f: &K::Id) -> Value {
Value::Ref(Ref::new(
K::first(),
crate::model::value::RefKey::spelled(&crate::schema::RefId::spell(f)),
))
}
fn write_text(f: &K::Id, w: &mut crate::text::Writer) {
w.reference(K::first().as_str(), &crate::schema::RefId::spell(f));
}
fn pack(f: &K::Id, p: &mut Packer) {
f.pack(p);
}
fn unpack(u: &mut Unpacker<'_>) -> Option<K::Id> {
K::Id::unpack(u)
}
}
#[derive(Debug)]
pub struct Spelled;
impl With<String> for Spelled {
fn shape() -> Shape {
Shape::Str
}
fn read(v: &ValueRef<'_>, cx: &mut Reader<'_>) -> Option<String> {
if let ValueRef::Str(s) = v {
return Some(s.to_string());
}
let spelled = crate::typed::spelling(&v.to_value());
if spelled.is_none() {
cx.expected(super::Expected::Text, v);
}
spelled
}
fn write(f: &String) -> Value {
Value::Str(f.clone())
}
fn write_text(f: &String, w: &mut crate::text::Writer) {
w.str(f);
}
}
#[derive(Debug)]
pub struct Opt<W>(PhantomData<W>);
impl<F, W: With<F>> With<Option<F>> for Opt<W> {
fn shape() -> Shape {
Shape::Optional(W::shape)
}
fn read(v: &ValueRef<'_>, cx: &mut Reader<'_>) -> Option<Option<F>> {
if v.is_null() {
Some(None)
} else {
W::read(v, cx).map(Some)
}
}
fn write(f: &Option<F>) -> Value {
f.as_ref().map_or(Value::Null, W::write)
}
fn write_text(f: &Option<F>, w: &mut crate::text::Writer) {
match f {
Some(f) => W::write_text(f, w),
None => {
w.null();
}
}
}
fn absent() -> Option<Option<F>> {
Some(None)
}
fn skip(f: &Option<F>) -> bool {
f.is_none()
}
}
#[derive(Debug)]
pub struct List<W>(PhantomData<W>);
impl<F, W: With<F>> With<Vec<F>> for List<W> {
fn shape() -> Shape {
Shape::List(W::shape)
}
fn read(v: &ValueRef<'_>, cx: &mut Reader<'_>) -> Option<Vec<F>> {
let ValueRef::List(items) = v else {
cx.expected(super::Expected::List, v);
return None;
};
let mut out = Vec::with_capacity(items.len());
let mut ok = true;
for (i, item) in items.iter().enumerate() {
match cx.at(Seg::Index(i), |cx| W::read(item, cx)) {
Some(x) => out.push(x),
None => ok = false,
}
}
ok.then_some(out)
}
fn write(f: &Vec<F>) -> Value {
Value::List(f.iter().map(W::write).collect())
}
fn write_text(f: &Vec<F>, w: &mut crate::text::Writer) {
w.list(f.len());
for item in f {
W::write_text(item, w);
}
}
}
#[derive(Debug)]
pub struct Values<W>(PhantomData<W>);
impl<F, W: With<F>> With<BTreeMap<String, F>> for Values<W> {
fn shape() -> Shape {
Shape::Map(W::shape)
}
fn read(v: &ValueRef<'_>, cx: &mut Reader<'_>) -> Option<BTreeMap<String, F>> {
read_values::<F, W, _>(v, cx)
}
fn write(f: &BTreeMap<String, F>) -> Value {
write_values::<F, W>(f.iter())
}
fn write_text(f: &BTreeMap<String, F>, w: &mut crate::text::Writer) {
w.map(f.len());
for (k, v) in f {
w.key(k);
W::write_text(v, w);
}
}
}
impl<F, W: With<F>> With<HashMap<String, F>> for Values<W> {
fn shape() -> Shape {
Shape::Map(W::shape)
}
fn read(v: &ValueRef<'_>, cx: &mut Reader<'_>) -> Option<HashMap<String, F>> {
read_values::<F, W, _>(v, cx)
}
fn write(f: &HashMap<String, F>) -> Value {
write_values::<F, W>(f.iter())
}
}
fn read_values<F, W: With<F>, M: Default + Extend<(String, F)>>(
v: &ValueRef<'_>,
cx: &mut Reader<'_>,
) -> Option<M> {
let map = cx.map(v)?;
let mut out = M::default();
let mut ok = true;
for (k, item) in map.iter().filter(|(k, _)| !is_metadata_key(k)) {
match cx.at(Seg::Key(k.to_string()), |cx| W::read(item, cx)) {
Some(x) => out.extend([(k.to_string(), x)]),
None => ok = false,
}
}
ok.then_some(out)
}
fn write_values<'a, F: 'a, W: With<F>>(
entries: impl Iterator<Item = (&'a String, &'a F)>,
) -> Value {
Value::Map(
entries
.map(|(k, v)| (k.clone(), W::write(v)))
.collect::<Map>(),
)
}
#[derive(Debug)]
pub struct Plain;
impl<F: Schema> With<F> for Plain {
fn shape() -> Shape {
F::shape()
}
fn read(v: &ValueRef<'_>, cx: &mut Reader<'_>) -> Option<F> {
F::read(v, cx)
}
fn write(f: &F) -> Value {
f.write()
}
fn absent() -> Option<F> {
F::absent()
}
fn skip(f: &F) -> bool {
f.skip()
}
fn write_text(f: &F, w: &mut crate::text::Writer) {
f.write_text(w);
}
fn encode(f: &F, w: &mut Writer) {
f.encode(w);
}
fn decode(d: &mut Decoder<'_>) -> Option<F> {
F::decode(d)
}
fn pack(f: &F, p: &mut Packer) {
f.pack(p);
}
fn unpack(u: &mut Unpacker<'_>) -> Option<F> {
F::unpack(u)
}
}
#[derive(Debug)]
pub struct Raw;
impl With<Vec<u8>> for Raw {
fn shape() -> Shape {
Shape::Bytes
}
fn read(v: &ValueRef<'_>, cx: &mut Reader<'_>) -> Option<Vec<u8>> {
match v {
ValueRef::Bytes(b) => Some(b.to_vec()),
ValueRef::Str(s) => {
if let crate::typed::Spelled::Bytes(b) = crate::typed::classify(s)
.map_err(|e| cx.problem_of(crate::Problem::BadTyped, e.to_string()))
.ok()?
{
Some(b)
} else {
cx.expected(super::Expected::Bytes, v);
None
}
}
other => {
cx.expected(super::Expected::Bytes, other);
None
}
}
}
fn write(f: &Vec<u8>) -> Value {
Value::Bytes(f.clone())
}
fn write_text(f: &Vec<u8>, w: &mut crate::text::Writer) {
w.bytes(f);
}
fn encode(f: &Vec<u8>, w: &mut Writer) {
w.bytes(f);
}
fn decode(d: &mut Decoder<'_>) -> Option<Vec<u8>> {
d.bytes().map(<[u8]>::to_vec)
}
fn pack(f: &Vec<u8>, p: &mut Packer) {
p.put_bytes(f);
}
fn unpack(u: &mut Unpacker<'_>) -> Option<Vec<u8>> {
u.bytes().map(<[u8]>::to_vec)
}
fn absent() -> Option<Vec<u8>> {
Some(Vec::new())
}
}