1use std::collections::{BTreeMap, HashMap};
20use std::marker::PhantomData;
21
22use crate::binary::{Decoder, Writer};
23use crate::borrowed::ValueRef;
24use crate::frame::{Packer, Unpacker};
25use crate::schema::{Kinds, Reader, Schema, Shape, Text, is_metadata_key, read_ref};
26use crate::value::{Map, Ref, Seg, Value};
27
28pub trait With<F> {
30 fn shape() -> Shape;
31 fn read(v: &ValueRef<'_>, cx: &mut Reader) -> Option<F>;
32 fn write(f: &F) -> Value;
33 fn absent() -> Option<F> {
35 None
36 }
37 fn skip(_f: &F) -> bool {
39 false
40 }
41 fn encode(f: &F, w: &mut Writer) {
44 w.value(&Self::write(f));
45 }
46 fn decode(d: &mut Decoder<'_>) -> Option<F> {
49 let arena = bumpalo::Bump::new();
50 let v = d.value_ref(&arena).ok()?;
51 let mut cx = Reader::new();
52 let f = Self::read(&v, &mut cx)?;
53 cx.problems.is_empty().then_some(f)
54 }
55 fn pack(f: &F, p: &mut Packer) {
58 let mut w = Writer::body();
59 Self::encode(f, &mut w);
60 p.put_bytes(&w.finish());
61 }
62 fn unpack(u: &mut Unpacker<'_>) -> Option<F> {
64 let mut d = Decoder::body(u.get_bytes()?);
65 let f = Self::decode(&mut d)?;
66 d.at_end().then_some(f)
67 }
68}
69
70pub struct RefTo<K>(PhantomData<K>);
72
73impl<K: Kinds> With<String> for RefTo<K> {
74 fn shape() -> Shape {
75 Shape::Ref(K::NAMES)
76 }
77 fn read(v: &ValueRef<'_>, cx: &mut Reader) -> Option<String> {
78 if let ValueRef::Ref { kind, id } = v
80 && (K::NAMES.is_empty() || K::NAMES.contains(kind))
81 {
82 if cx.keeps_found() || cx.resolves() {
83 let r = Ref::new(*kind, *id);
84 if cx.keeps_found() {
85 cx.note_ref(r.clone());
86 }
87 return cx.take_ref(r);
88 }
89 return Some(id.to_string());
90 }
91 let r = read_ref(v, cx, K::NAMES)?;
92 cx.take_ref(r)
93 }
94 fn write(f: &String) -> Value {
95 Value::Ref(Ref::new(
96 K::NAMES.first().copied().unwrap_or(yog_ids::kind::ITEM),
97 f.clone(),
98 ))
99 }
100}
101
102pub struct Spelled;
106
107impl With<String> for Spelled {
108 fn shape() -> Shape {
109 Shape::Str
110 }
111 fn read(v: &ValueRef<'_>, cx: &mut Reader) -> Option<String> {
112 if let ValueRef::Str(s) = v {
113 return Some(s.to_string());
114 }
115 let spelled = crate::typed::typed_string(&v.to_value());
116 if spelled.is_none() {
117 cx.expected("text", v);
118 }
119 spelled
120 }
121 fn write(f: &String) -> Value {
122 Value::Str(f.clone())
123 }
124}
125
126pub struct TextOf;
128
129impl With<String> for TextOf {
130 fn shape() -> Shape {
131 Shape::Text
132 }
133 fn read(v: &ValueRef<'_>, cx: &mut Reader) -> Option<String> {
134 let t = Text::read(v, cx)?;
135 cx.take_text(t)
136 }
137 fn write(f: &String) -> Value {
138 Value::Text(f.clone())
139 }
140}
141
142pub struct Opt<W>(PhantomData<W>);
144
145impl<F, W: With<F>> With<Option<F>> for Opt<W> {
146 fn shape() -> Shape {
147 Shape::Optional(W::shape)
148 }
149 fn read(v: &ValueRef<'_>, cx: &mut Reader) -> Option<Option<F>> {
150 if v.is_null() {
151 Some(None)
152 } else {
153 W::read(v, cx).map(Some)
154 }
155 }
156 fn write(f: &Option<F>) -> Value {
157 f.as_ref().map_or(Value::Null, W::write)
158 }
159 fn absent() -> Option<Option<F>> {
160 Some(None)
161 }
162 fn skip(f: &Option<F>) -> bool {
163 f.is_none()
164 }
165}
166
167pub struct List<W>(PhantomData<W>);
169
170impl<F, W: With<F>> With<Vec<F>> for List<W> {
171 fn shape() -> Shape {
172 Shape::List(W::shape)
173 }
174 fn read(v: &ValueRef<'_>, cx: &mut Reader) -> Option<Vec<F>> {
175 let ValueRef::List(items) = v else {
176 cx.expected("a list", v);
177 return None;
178 };
179 let mut out = Vec::with_capacity(items.len());
180 let mut ok = true;
181 for (i, item) in items.iter().enumerate() {
182 match cx.at(Seg::Index(i), |cx| W::read(item, cx)) {
183 Some(x) => out.push(x),
184 None => ok = false,
185 }
186 }
187 ok.then_some(out)
188 }
189 fn write(f: &Vec<F>) -> Value {
190 Value::List(f.iter().map(W::write).collect())
191 }
192}
193
194pub struct Values<W>(PhantomData<W>);
196
197impl<F, W: With<F>> With<BTreeMap<String, F>> for Values<W> {
198 fn shape() -> Shape {
199 Shape::Map(W::shape)
200 }
201 fn read(v: &ValueRef<'_>, cx: &mut Reader) -> Option<BTreeMap<String, F>> {
202 read_values::<F, W, _>(v, cx)
203 }
204 fn write(f: &BTreeMap<String, F>) -> Value {
205 write_values::<F, W>(f.iter())
206 }
207}
208
209impl<F, W: With<F>> With<HashMap<String, F>> for Values<W> {
210 fn shape() -> Shape {
211 Shape::Map(W::shape)
212 }
213 fn read(v: &ValueRef<'_>, cx: &mut Reader) -> Option<HashMap<String, F>> {
214 read_values::<F, W, _>(v, cx)
215 }
216 fn write(f: &HashMap<String, F>) -> Value {
217 write_values::<F, W>(f.iter())
218 }
219}
220
221fn read_values<F, W: With<F>, M: Default + Extend<(String, F)>>(
223 v: &ValueRef<'_>,
224 cx: &mut Reader,
225) -> Option<M> {
226 let map = cx.map(v)?;
227 let mut out = M::default();
228 let mut ok = true;
229 for (k, item) in map.iter().filter(|(k, _)| !is_metadata_key(k)) {
230 match cx.at(Seg::Key(k.to_string()), |cx| W::read(item, cx)) {
231 Some(x) => out.extend([(k.to_string(), x)]),
232 None => ok = false,
233 }
234 }
235 ok.then_some(out)
236}
237
238fn write_values<'a, F: 'a, W: With<F>>(
239 entries: impl Iterator<Item = (&'a String, &'a F)>,
240) -> Value {
241 Value::Map(
242 entries
243 .map(|(k, v)| (k.clone(), W::write(v)))
244 .collect::<Map>(),
245 )
246}
247
248pub struct Plain;
250
251impl<F: Schema> With<F> for Plain {
252 fn shape() -> Shape {
253 F::shape()
254 }
255 fn read(v: &ValueRef<'_>, cx: &mut Reader) -> Option<F> {
256 F::read(v, cx)
257 }
258 fn write(f: &F) -> Value {
259 f.write()
260 }
261 fn absent() -> Option<F> {
262 F::absent()
263 }
264 fn skip(f: &F) -> bool {
265 f.skip()
266 }
267 fn encode(f: &F, w: &mut Writer) {
268 f.encode(w);
269 }
270 fn decode(d: &mut Decoder<'_>) -> Option<F> {
271 F::decode(d)
272 }
273 fn pack(f: &F, p: &mut Packer) {
274 f.pack(p);
275 }
276 fn unpack(u: &mut Unpacker<'_>) -> Option<F> {
277 F::unpack(u)
278 }
279}
280
281pub struct Raw;
283
284impl With<Vec<u8>> for Raw {
285 fn shape() -> Shape {
286 Shape::Bytes
287 }
288 fn read(v: &ValueRef<'_>, cx: &mut Reader) -> Option<Vec<u8>> {
289 match v {
290 ValueRef::Bytes(b) => Some(b.to_vec()),
291 ValueRef::Str(s) => match crate::typed::classify(s).map_err(|e| cx.problem(e)).ok()? {
293 crate::Value::Bytes(b) => Some(b),
294 _ => {
295 cx.expected("bytes", v);
296 None
297 }
298 },
299 other => {
300 cx.expected("bytes", other);
301 None
302 }
303 }
304 }
305 fn write(f: &Vec<u8>) -> Value {
306 Value::Bytes(f.clone())
307 }
308 fn encode(f: &Vec<u8>, w: &mut Writer) {
309 w.bytes(f);
310 }
311 fn decode(d: &mut Decoder<'_>) -> Option<Vec<u8>> {
312 d.bytes().map(<[u8]>::to_vec)
313 }
314 fn pack(f: &Vec<u8>, p: &mut Packer) {
315 p.put_bytes(f);
316 }
317 fn unpack(u: &mut Unpacker<'_>) -> Option<Vec<u8>> {
318 u.get_bytes().map(<[u8]>::to_vec)
319 }
320 fn absent() -> Option<Vec<u8>> {
321 Some(Vec::new())
322 }
323}