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