Skip to main content

manual_impls/
manual_impls.rs

1//! Declaring a schema by hand, without the `object!` macro.
2//!
3//! This is the escape hatch for anything the macro cannot express: computed
4//! fields, custom coercions, wire formats that do not map cleanly onto struct
5//! members. It is also the code the macro generates, so reading it shows
6//! exactly what `object!` does.
7//!
8//! Kept as a runnable example so the version in docs/schema-declaration.md
9//! cannot drift from an API that still compiles. The region between the markers
10//! below *is* that version: `docs_quote_the_example_verbatim` in tests/docs.rs
11//! fails if the two stop matching, so the claim is checked rather than
12//! promised.
13//!
14//! This is the JSON half. `Keys` is shared by every format, so adding BEVE
15//! means the same four impls again against `beve::Reader` and `beve::Writer`
16//! and nothing else; see `structio::beve` for their signatures.
17//!
18//! `cargo run --example manual_impls`
19// docs:begin
20use structio::json::{Parser, Read, ReadObject, Write, WriteObject, Writer};
21use structio::{ErrorCode, KeyMap, Keys, Options};
22
23#[derive(Default)]
24struct Person {
25    first_name: String,
26    age: u32,
27    friends: Vec<String>,
28}
29
30impl Keys for Person {
31    const KEYS: &'static [&'static str] = &["first_name", "age", "friends"];
32    const MAP: &'static KeyMap = &KeyMap::build(Self::KEYS);
33}
34
35impl<'de> ReadObject<'de> for Person {
36    fn read_field<O: Options>(
37        &mut self,
38        index: usize,
39        p: &mut Parser<'de, O>,
40    ) -> Result<bool, ErrorCode> {
41        // The index came from a hash, so confirm the key before using it.
42        if !p.match_key(Self::KEYS[index]) {
43            return Ok(false);
44        }
45        p.colon()?;
46        match index {
47            0 => Read::read(&mut self.first_name, p)?,
48            1 => Read::read(&mut self.age, p)?,
49            2 => Read::read(&mut self.friends, p)?,
50            _ => return Ok(false),
51        }
52        Ok(true)
53    }
54}
55
56impl WriteObject for Person {
57    fn write_fields<O: Options>(&self, w: &mut Writer<'_, O>) {
58        w.member("\"first_name\":", &self.first_name);
59        w.member("\"age\":", &self.age);
60        w.member("\"friends\":", &self.friends);
61    }
62}
63
64impl<'de> Read<'de> for Person {
65    fn read<O: Options>(&mut self, p: &mut Parser<'de, O>) -> Result<(), ErrorCode> {
66        p.read_object(self)
67    }
68}
69impl Write for Person {
70    fn write<O: Options>(&self, w: &mut Writer<'_, O>) {
71        w.write_object(self)
72    }
73}
74// docs:end
75
76fn main() {
77    let p: Person = structio::from_str(r#"{"age":3,"first_name":"x","friends":["a"]}"#).unwrap();
78    assert_eq!(p.age, 3);
79    assert_eq!(p.first_name, "x");
80    assert_eq!(
81        structio::to_string(&p),
82        r#"{"first_name":"x","age":3,"friends":["a"]}"#
83    );
84    println!("manual impls work");
85}