1use super::{
3 BTreeMap, Decoder, HashMap, Packer, Reader, Schema, Seg, Shape, Unpacker, Value, ValueRef,
4 Writer, is_metadata_key, typed,
5};
6
7fn typed_mark() -> char {
9 yog_ids::sep::TYPED.chars().next().unwrap_or_default()
10}
11
12impl Schema for Value {
15 fn shape() -> Shape {
16 Shape::Any
17 }
18 fn read(v: &ValueRef<'_>, _: &mut Reader) -> Option<Self> {
19 Some(v.to_value())
20 }
21 fn write(&self) -> Value {
22 self.clone()
23 }
24}
25
26impl Schema for bool {
27 fn shape() -> Shape {
28 Shape::Bool
29 }
30 fn read(v: &ValueRef<'_>, cx: &mut Reader) -> Option<Self> {
31 v.as_bool().or_else(|| {
32 cx.expected("true or false", v);
33 None
34 })
35 }
36 fn write(&self) -> Value {
37 Value::Bool(*self)
38 }
39 fn encode(&self, w: &mut Writer) {
40 w.bool(*self);
41 }
42 fn decode(d: &mut Decoder<'_>) -> Option<Self> {
43 d.bool()
44 }
45 fn pack(&self, p: &mut Packer) {
46 p.put_bool(*self);
47 }
48 fn unpack(u: &mut Unpacker<'_>) -> Option<Self> {
49 u.get_bool()
50 }
51}
52
53fn narrowed<T: TryFrom<i64>>(n: i64) -> Option<T> {
55 T::try_from(n).ok()
56}
57
58fn unsigned64<T: From<u64>>(n: i64) -> Option<T> {
60 Some(T::from(n as u64))
61}
62
63fn unsigned_size(n: i64) -> Option<usize> {
65 usize::try_from(n as u64).ok()
66}
67
68macro_rules! int_schema {
69 ($($t:ty => $to_bits:ident, $of_bits:ident, $of_i64:path);*) => {$(
70 impl Schema for $t {
71 fn shape() -> Shape {
72 Shape::Int { min: <$t>::MIN as i64, max: (<$t>::MAX as u64).min(i64::MAX as u64) as i64 }
73 }
74 fn read(v: &ValueRef<'_>, cx: &mut Reader) -> Option<Self> {
75 let Some(n) = v.as_i64() else {
76 cx.expected("an integer", v);
77 return None;
78 };
79 $of_i64(n).or_else(|| {
80 cx.problem(format!("{n} is out of range ({}..={})", <$t>::MIN, <$t>::MAX));
81 None
82 })
83 }
84 fn write(&self) -> Value {
85 Value::Int(*self as i64)
86 }
87 fn encode(&self, w: &mut Writer) {
88 w.int(*self as i64);
89 }
90 fn decode(d: &mut Decoder<'_>) -> Option<Self> {
91 d.int().and_then($of_i64)
92 }
93 fn pack(&self, p: &mut Packer) {
94 p.put_i(*self as i64);
95 }
96 fn unpack(u: &mut Unpacker<'_>) -> Option<Self> {
97 u.get_i().and_then($of_i64)
98 }
99 fn pack_list(items: &[Self], p: &mut Packer) {
100 p.put_uints(items.len(), items.iter().map(|&n| $to_bits(n as i128)));
101 }
102 fn unpack_list(u: &mut Unpacker<'_>) -> Option<Vec<Self>> {
103 u.get_uints(|v| <$t>::try_from($of_bits(v)).ok())
104 }
105 fn encode_list(items: &[Self], w: &mut Writer) {
106 w.ints(items.iter().map(|&n| n as i64));
107 }
108 fn decode_list(d: &mut Decoder<'_>) -> Option<Vec<Self>> {
109 let n = d.ints()?;
110 let mut out = Vec::with_capacity(n);
111 for _ in 0..n {
112 out.push($of_i64(d.packed_int()?)?);
113 }
114 Some(out)
115 }
116 }
117 )*};
118}
119int_schema!(
120 i8 => signed_bits, signed_of, narrowed; i16 => signed_bits, signed_of, narrowed;
121 i32 => signed_bits, signed_of, narrowed; i64 => signed_bits, signed_of, narrowed;
122 u8 => unsigned_bits, unsigned_of, narrowed; u16 => unsigned_bits, unsigned_of, narrowed;
123 u32 => unsigned_bits, unsigned_of, narrowed;
124 u64 => unsigned_bits, unsigned_of, unsigned64; usize => unsigned_bits, unsigned_of, unsigned_size
125);
126
127fn signed_bits(n: i128) -> u64 {
129 crate::binary::zigzag(n as i64)
130}
131
132fn signed_of(v: u64) -> i128 {
133 i128::from(crate::binary::unzigzag(v))
134}
135
136fn unsigned_bits(n: i128) -> u64 {
138 n as u64
139}
140
141fn unsigned_of(v: u64) -> i128 {
142 i128::from(v)
143}
144
145macro_rules! float_schema {
146 ($($t:ty => $one:ident, $many:ident, $read_many:ident, $put:ident, $get:ident, $puts:ident, $gets:ident);*) => {$(
147 impl Schema for $t {
148 fn shape() -> Shape {
149 Shape::Float { bits: u8::BITS * std::mem::size_of::<$t>() as u32 }
150 }
151 fn read(v: &ValueRef<'_>, cx: &mut Reader) -> Option<Self> {
152 v.as_f64().map(|f| f as $t).or_else(|| {
153 cx.expected("a number", v);
154 None
155 })
156 }
157 fn write(&self) -> Value {
158 Value::Float(*self as f64)
159 }
160 fn encode(&self, w: &mut Writer) {
161 w.$one(*self);
162 }
163 fn decode(d: &mut Decoder<'_>) -> Option<Self> {
164 d.float().map(|f| f as $t)
165 }
166 fn encode_list(items: &[Self], w: &mut Writer) {
167 w.$many(items);
168 }
169 fn decode_list(d: &mut Decoder<'_>) -> Option<Vec<Self>> {
170 d.$read_many()
171 }
172 fn pack(&self, p: &mut Packer) {
173 p.$put(*self);
174 }
175 fn unpack(u: &mut Unpacker<'_>) -> Option<Self> {
176 u.$get()
177 }
178 fn pack_list(items: &[Self], p: &mut Packer) {
179 p.$puts(items);
180 }
181 fn unpack_list(u: &mut Unpacker<'_>) -> Option<Vec<Self>> {
182 u.$gets()
183 }
184 }
185 )*};
186}
187float_schema!(
188 f32 => float32, floats32, floats32, put_f32, get_f32, put_f32s, get_f32s;
189 f64 => float, floats, floats, put_f64, get_f64, put_f64s, get_f64s
190);
191
192impl Schema for String {
193 fn shape() -> Shape {
194 Shape::Str
195 }
196 fn read(v: &ValueRef<'_>, cx: &mut Reader) -> Option<Self> {
197 match v {
198 ValueRef::Str(s) if !s.starts_with('@') => Some(s.to_string()),
200 ValueRef::Str(s) => match typed::classify(s) {
201 Ok(Value::Str(s)) => Some(s),
202 Ok(other) => {
203 cx.problem(format!(
204 "expected plain text, found {} (write `@@` for a literal `@`)",
205 other.kind_name()
206 ));
207 None
208 }
209 Err(e) => {
210 cx.problem_of(yog_ids::data_problem::BAD_TYPED, e);
211 None
212 }
213 },
214 other => {
215 cx.expected("a string", other);
216 None
217 }
218 }
219 }
220 fn write(&self) -> Value {
221 Value::Str(self.clone())
222 }
223 fn encode(&self, w: &mut Writer) {
224 w.str(self);
225 }
226 fn decode(d: &mut Decoder<'_>) -> Option<Self> {
227 d.str()
229 .filter(|s| !s.starts_with(typed_mark()))
230 .map(str::to_owned)
231 }
232 fn pack(&self, p: &mut Packer) {
233 p.put_str(self);
234 }
235 fn unpack(u: &mut Unpacker<'_>) -> Option<Self> {
236 u.get_str().map(str::to_owned)
237 }
238}
239
240impl Schema for std::borrow::Cow<'static, str> {
242 fn shape() -> Shape {
243 Shape::Str
244 }
245 fn read(v: &ValueRef<'_>, cx: &mut Reader) -> Option<Self> {
246 String::read(v, cx).map(Self::Owned)
247 }
248 fn write(&self) -> Value {
249 Value::Str(self.to_string())
250 }
251 fn encode(&self, w: &mut Writer) {
252 w.str(self);
253 }
254 fn decode(d: &mut Decoder<'_>) -> Option<Self> {
255 String::decode(d).map(Self::Owned)
256 }
257 fn pack(&self, p: &mut Packer) {
258 p.put_str(self);
259 }
260 fn unpack(u: &mut Unpacker<'_>) -> Option<Self> {
261 String::unpack(u).map(Self::Owned)
262 }
263}
264
265impl Schema for std::path::PathBuf {
267 fn shape() -> Shape {
268 Shape::Str
269 }
270 fn read(v: &ValueRef<'_>, cx: &mut Reader) -> Option<Self> {
271 String::read(v, cx).map(Self::from)
272 }
273 fn write(&self) -> Value {
274 Value::Str(self.to_string_lossy().into_owned())
275 }
276 fn encode(&self, w: &mut Writer) {
277 w.str(&self.to_string_lossy());
278 }
279 fn decode(d: &mut Decoder<'_>) -> Option<Self> {
280 String::decode(d).map(Self::from)
281 }
282 fn pack(&self, p: &mut Packer) {
283 p.put_str(&self.to_string_lossy());
284 }
285 fn unpack(u: &mut Unpacker<'_>) -> Option<Self> {
286 u.get_str().map(Self::from)
287 }
288}
289
290impl Schema for crate::Atom {
292 fn shape() -> Shape {
293 Shape::Atom
294 }
295 fn read(v: &ValueRef<'_>, cx: &mut Reader) -> Option<Self> {
296 String::read(v, cx).map(|s| crate::Atom::new(&s))
297 }
298 fn write(&self) -> Value {
299 Value::Str(self.as_str().to_owned())
300 }
301 fn encode(&self, w: &mut Writer) {
302 w.str(self.as_str());
303 }
304 fn decode(d: &mut Decoder<'_>) -> Option<Self> {
305 d.str()
306 .filter(|s| !s.starts_with(typed_mark()))
307 .map(crate::Atom::new)
308 }
309 fn pack(&self, p: &mut Packer) {
310 p.put_u(u64::from(self.number()));
311 }
312 fn unpack(u: &mut Unpacker<'_>) -> Option<Self> {
313 crate::Atom::from_number(u32::try_from(u.get_u()?).ok()?)
314 }
315}
316
317impl<T: Schema> Schema for Option<T> {
318 fn shape() -> Shape {
319 Shape::Optional(T::shape)
320 }
321 fn read(v: &ValueRef<'_>, cx: &mut Reader) -> Option<Self> {
322 if v.is_null() {
323 Some(None)
324 } else {
325 T::read(v, cx).map(Some)
326 }
327 }
328 fn write(&self) -> Value {
329 self.as_ref().map_or(Value::Null, T::write)
330 }
331 fn encode(&self, w: &mut Writer) {
332 match self {
333 Some(v) => v.encode(w),
334 None => {
335 w.null();
336 }
337 }
338 }
339 fn decode(d: &mut Decoder<'_>) -> Option<Self> {
340 if d.null() {
341 Some(None)
342 } else {
343 T::decode(d).map(Some)
344 }
345 }
346 fn pack(&self, p: &mut Packer) {
347 p.put_bool(self.is_some());
348 if let Some(v) = self {
349 v.pack(p);
350 }
351 }
352 fn unpack(u: &mut Unpacker<'_>) -> Option<Self> {
353 if u.get_bool()? {
354 T::unpack(u).map(Some)
355 } else {
356 Some(None)
357 }
358 }
359 fn absent() -> Option<Self> {
360 Some(None)
361 }
362 fn skip(&self) -> bool {
363 self.is_none()
364 }
365}
366
367impl<T: Schema> Schema for Box<T> {
368 fn shape() -> Shape {
369 T::shape()
370 }
371 fn read(v: &ValueRef<'_>, cx: &mut Reader) -> Option<Self> {
372 T::read(v, cx).map(Box::new)
373 }
374 fn write(&self) -> Value {
375 (**self).write()
376 }
377 fn encode(&self, w: &mut Writer) {
378 (**self).encode(w);
379 }
380 fn decode(d: &mut Decoder<'_>) -> Option<Self> {
381 T::decode(d).map(Box::new)
382 }
383 fn pack(&self, p: &mut Packer) {
384 (**self).pack(p);
385 }
386 fn unpack(u: &mut Unpacker<'_>) -> Option<Self> {
387 T::unpack(u).map(Box::new)
388 }
389 fn absent() -> Option<Self> {
390 T::absent().map(Box::new)
391 }
392 fn skip(&self) -> bool {
393 (**self).skip()
394 }
395}
396
397impl<T: Schema> Schema for Vec<T> {
398 fn shape() -> Shape {
399 Shape::List(T::shape)
400 }
401 fn read(v: &ValueRef<'_>, cx: &mut Reader) -> Option<Self> {
402 let ValueRef::List(items) = v else {
403 cx.expected("a list", v);
404 return None;
405 };
406 let mut out = Vec::with_capacity(items.len());
407 let mut ok = true;
408 for (i, item) in items.iter().enumerate() {
409 match cx.at(Seg::Index(i), |cx| T::read(item, cx)) {
410 Some(x) => out.push(x),
411 None => ok = false,
412 }
413 }
414 ok.then_some(out)
415 }
416 fn write(&self) -> Value {
417 Value::List(self.iter().map(T::write).collect())
418 }
419 fn encode(&self, w: &mut Writer) {
420 T::encode_list(self, w);
421 }
422 fn decode(d: &mut Decoder<'_>) -> Option<Self> {
423 T::decode_list(d)
424 }
425 fn pack(&self, p: &mut Packer) {
426 T::pack_list(self, p);
427 }
428 fn unpack(u: &mut Unpacker<'_>) -> Option<Self> {
429 T::unpack_list(u)
430 }
431}
432
433impl<T: Schema + Ord + Clone> Schema for std::collections::BTreeSet<T> {
435 fn shape() -> Shape {
436 Shape::List(T::shape)
437 }
438 fn read(v: &ValueRef<'_>, cx: &mut Reader) -> Option<Self> {
439 Vec::<T>::read(v, cx).map(Self::from_iter)
440 }
441 fn write(&self) -> Value {
442 Value::List(self.iter().map(T::write).collect())
443 }
444 fn encode(&self, w: &mut Writer) {
445 T::encode_list(&self.iter().cloned().collect::<Vec<_>>(), w);
447 }
448 fn decode(d: &mut Decoder<'_>) -> Option<Self> {
449 Vec::<T>::decode(d).map(Self::from_iter)
450 }
451}
452
453impl Schema for Box<str> {
456 fn shape() -> Shape {
457 Shape::Str
458 }
459 fn read(v: &ValueRef<'_>, cx: &mut Reader) -> Option<Self> {
460 String::read(v, cx).map(String::into_boxed_str)
461 }
462 fn write(&self) -> Value {
463 Value::Str(self.to_string())
464 }
465 fn encode(&self, w: &mut Writer) {
466 w.str(self);
467 }
468 fn decode(d: &mut Decoder<'_>) -> Option<Self> {
469 String::decode(d).map(String::into_boxed_str)
470 }
471 fn pack(&self, p: &mut Packer) {
472 p.put_str(self);
473 }
474 fn unpack(u: &mut Unpacker<'_>) -> Option<Self> {
475 u.get_str().map(Into::into)
476 }
477}
478
479impl Schema for yog_sync::Arc<str> {
481 fn shape() -> Shape {
482 Shape::Str
483 }
484 fn read(v: &ValueRef<'_>, cx: &mut Reader) -> Option<Self> {
485 String::read(v, cx).map(Into::into)
486 }
487 fn write(&self) -> Value {
488 Value::Str(self.to_string())
489 }
490 fn encode(&self, w: &mut Writer) {
491 w.str(self);
492 }
493 fn decode(d: &mut Decoder<'_>) -> Option<Self> {
494 String::decode(d).map(Into::into)
495 }
496 fn pack(&self, p: &mut Packer) {
497 p.put_str(self);
498 }
499 fn unpack(u: &mut Unpacker<'_>) -> Option<Self> {
500 u.get_shared_str()
501 }
502}
503
504impl<T: Schema> Schema for Box<[T]> {
506 fn shape() -> Shape {
507 Shape::List(T::shape)
508 }
509 fn read(v: &ValueRef<'_>, cx: &mut Reader) -> Option<Self> {
510 Vec::<T>::read(v, cx).map(Vec::into_boxed_slice)
511 }
512 fn write(&self) -> Value {
513 Value::List(self.iter().map(T::write).collect())
514 }
515 fn encode(&self, w: &mut Writer) {
516 T::encode_list(self, w);
517 }
518 fn decode(d: &mut Decoder<'_>) -> Option<Self> {
519 T::decode_list(d).map(Vec::into_boxed_slice)
520 }
521 fn pack(&self, p: &mut Packer) {
522 T::pack_list(self, p);
523 }
524 fn unpack(u: &mut Unpacker<'_>) -> Option<Self> {
525 T::unpack_list(u).map(Vec::into_boxed_slice)
526 }
527}
528
529impl<T: Schema, const N: usize> Schema for [T; N] {
530 fn shape() -> Shape {
531 Shape::List(T::shape)
532 }
533 fn read(v: &ValueRef<'_>, cx: &mut Reader) -> Option<Self> {
534 let items = Vec::<T>::read(v, cx)?;
535 let len = items.len();
536 items.try_into().ok().or_else(|| {
537 cx.problem(format!("expected {N} items, found {len}"));
538 None
539 })
540 }
541 fn write(&self) -> Value {
542 Value::List(self.iter().map(T::write).collect())
543 }
544 fn encode(&self, w: &mut Writer) {
545 T::encode_list(self, w);
546 }
547 fn decode(d: &mut Decoder<'_>) -> Option<Self> {
548 T::decode_list(d)?.try_into().ok()
549 }
550 fn pack(&self, p: &mut Packer) {
551 T::pack_list(self, p);
552 }
553 fn unpack(u: &mut Unpacker<'_>) -> Option<Self> {
554 T::unpack_list(u)?.try_into().ok()
555 }
556}
557
558impl Schema for () {
560 fn shape() -> Shape {
561 Shape::Any
562 }
563 fn read(_v: &ValueRef<'_>, _cx: &mut Reader) -> Option<Self> {
564 Some(())
565 }
566 fn write(&self) -> Value {
567 Value::Null
568 }
569}
570
571impl<T: Schema, E: Schema> Schema for Result<T, E> {
573 fn shape() -> Shape {
574 Shape::Any
575 }
576 fn read(v: &ValueRef<'_>, cx: &mut Reader) -> Option<Self> {
577 let ValueRef::Map(m) = v else {
578 cx.expected("{ ok } or { err }", v);
579 return None;
580 };
581 if let Some(ok) = m.get(RESULT_OK) {
582 return cx
583 .at(Seg::Key(RESULT_OK.into()), |cx| T::read(ok, cx))
584 .map(Ok);
585 }
586 let Some(err) = m.get(RESULT_ERR) else {
587 cx.expected("{ ok } or { err }", v);
588 return None;
589 };
590 cx.at(Seg::Key(RESULT_ERR.into()), |cx| E::read(err, cx))
591 .map(Err)
592 }
593 fn write(&self) -> Value {
594 let (key, value) = match self {
595 Ok(t) => (RESULT_OK, t.write()),
596 Err(e) => (RESULT_ERR, e.write()),
597 };
598 Value::Map([(key.to_owned(), value)].into_iter().collect())
599 }
600}
601
602pub(crate) const RESULT_OK: &str = "ok";
604pub(crate) const RESULT_ERR: &str = "err";
605
606macro_rules! tuples {
609 ($($what:literal: $n:literal => ($($t:ident $i:tt),+);)+) => {$(
610 impl<$($t: Schema),+> Schema for ($($t,)+) {
611 fn shape() -> Shape {
612 Shape::List(Value::shape)
613 }
614 fn read(v: &ValueRef<'_>, cx: &mut Reader) -> Option<Self> {
615 let ValueRef::List(items) = v else {
616 cx.expected($what, v);
617 return None;
618 };
619 if items.len() != $n {
620 cx.problem(format!("expected {} items, found {}", $n, items.len()));
621 return None;
622 }
623 let read = ($(cx.at(Seg::Index($i), |cx| $t::read(&items[$i], cx)),)+);
624 Some(($(read.$i?,)+))
625 }
626 fn write(&self) -> Value {
627 Value::List(vec![$(self.$i.write()),+])
628 }
629 }
630 )+};
631}
632
633tuples! {
634 "a pair [a, b]": 2 => (A 0, B 1);
635 "a triple [a, b, c]": 3 => (A 0, B 1, C 2);
636 "four [a, b, c, d]": 4 => (A 0, B 1, C 2, D 3);
637}
638
639fn read_map<T: Schema>(
640 v: &ValueRef,
641 cx: &mut Reader,
642 mut put: impl FnMut(String, T),
643) -> Option<()> {
644 let map = cx.map(v)?;
645 let mut ok = true;
646 for (k, item) in map.iter() {
647 if is_metadata_key(k) {
648 continue;
649 }
650 match cx.at(Seg::Key(k.to_string()), |cx| T::read(item, cx)) {
651 Some(x) => put(k.to_string(), x),
652 None => ok = false,
653 }
654 }
655 ok.then_some(())
656}
657
658impl<T: Schema> Schema for BTreeMap<String, T> {
659 fn shape() -> Shape {
660 Shape::Map(T::shape)
661 }
662 fn read(v: &ValueRef<'_>, cx: &mut Reader) -> Option<Self> {
663 let mut out = BTreeMap::new();
664 read_map(v, cx, |k, x| {
665 out.insert(k, x);
666 })?;
667 Some(out)
668 }
669 fn write(&self) -> Value {
670 Value::Map(self.iter().map(|(k, v)| (k.clone(), v.write())).collect())
671 }
672}
673
674impl<T: Schema> Schema for HashMap<String, T> {
675 fn shape() -> Shape {
676 Shape::Map(T::shape)
677 }
678 fn read(v: &ValueRef<'_>, cx: &mut Reader) -> Option<Self> {
679 let mut out = HashMap::new();
680 read_map(v, cx, |k, x| {
681 out.insert(k, x);
682 })?;
683 Some(out)
684 }
685 fn write(&self) -> Value {
686 let mut keys: Vec<&String> = self.keys().collect();
687 keys.sort();
688 Value::Map(
689 keys.into_iter()
690 .map(|k| (k.clone(), self[k].write()))
691 .collect(),
692 )
693 }
694}
695
696#[derive(Debug, Clone, PartialEq)]
698pub struct Ordered<T>(pub Vec<(String, T)>);
699
700impl<T> Default for Ordered<T> {
701 fn default() -> Self {
702 Self(Vec::new())
703 }
704}
705
706impl<T: Schema> Schema for Ordered<T> {
707 fn shape() -> Shape {
708 Shape::Map(T::shape)
709 }
710 fn read(v: &ValueRef<'_>, cx: &mut Reader) -> Option<Self> {
711 let mut out = Vec::new();
712 read_map(v, cx, |k, x| out.push((k, x)))?;
713 Some(Ordered(out))
714 }
715 fn write(&self) -> Value {
716 Value::Map(self.0.iter().map(|(k, v)| (k.clone(), v.write())).collect())
717 }
718}