Skip to main content

yog_data/schema/
fields.rs

1//! A struct's fields as files write them, by their Rust names: code that
2//! names a field (where a problem is) says it through [`field!`](crate::field),
3//! checked when it's compiled and renamed with the field.
4
5/// A struct with named fields (`#[derive(Schema)]`): each field's Rust name
6/// and its name in files.
7pub trait Fields {
8    const FIELDS: &'static [(&'static str, &'static str)];
9}
10
11/// `ident`'s name in files among `fields` — a compile error when it's used
12/// in a constant (as [`field!`](crate::field) does) and there's no such field.
13#[must_use]
14pub const fn field_name(
15    fields: &'static [(&'static str, &'static str)],
16    ident: &str,
17) -> &'static str {
18    let mut i = 0;
19    while i < fields.len() {
20        if same(fields[i].0, ident) {
21            return fields[i].1;
22        }
23        i += 1;
24    }
25    panic!("no such field")
26}
27
28const fn same(a: &str, b: &str) -> bool {
29    let (a, b) = (a.as_bytes(), b.as_bytes());
30    if a.len() != b.len() {
31        return false;
32    }
33    let mut i = 0;
34    while i < a.len() {
35        if a[i] != b[i] {
36            return false;
37        }
38        i += 1;
39    }
40    true
41}
42
43/// Field `ident` of struct `T` as files write it: `field!(BlockProps, tool_level)`
44/// → `"tool_level"`. A field `T` hasn't got doesn't compile.
45#[macro_export]
46macro_rules! field {
47    ($t:ty, $f:ident) => {{
48        const NAME: &str = $crate::schema::field_name(
49            <$t as $crate::schema::Fields>::FIELDS,
50            ::core::stringify!($f),
51        );
52        NAME
53    }};
54}
55
56#[cfg(test)]
57mod tests {
58    use crate::Schema;
59
60    #[derive(Schema)]
61    struct Probe {
62        plain: u32,
63        #[data(rename = "written")]
64        renamed: u32,
65    }
66
67    #[test]
68    fn fields_by_their_rust_names() {
69        assert_eq!(crate::field!(Probe, plain), "plain");
70        assert_eq!(crate::field!(Probe, renamed), "written");
71    }
72}