Skip to main content

yog_cli/design/
data.rs

1//! Yog Data files as the designers look things up in them (their typed
2//! strings as written: the schema reading them isn't run here).
3
4use yog_data::Value;
5
6/// A Yog Data file that's one object (a map), `None` if it isn't.
7pub fn read_object(text: &str) -> Option<Value> {
8    yog_data::text::parse_value(text)
9        .ok()
10        .filter(|v| matches!(v, Value::Map(_)))
11}
12
13/// `v` with its references as the runtime writes ids: `@item:x` → `x`,
14/// `@tag:item:x` → `#x` (what yog-book's renderer and the hosts read).
15pub fn runtime_ids(v: &mut Value) {
16    match v {
17        Value::Str(s) if s.starts_with('@') => match yog_data::typed::classify(s) {
18            Ok(Value::Ref(r)) => *s = r.id,
19            Ok(Value::Tag(r)) => *s = format!("#{}", r.id),
20            Ok(Value::Str(plain)) => *s = plain,
21            _ => {}
22        },
23        Value::List(items) => items.iter_mut().for_each(runtime_ids),
24        Value::Map(m) => {
25            let keys: Vec<String> = m.keys().map(str::to_string).collect();
26            for k in keys {
27                if let Some(x) = m.get_mut(&k) {
28                    runtime_ids(x);
29                }
30            }
31        }
32        _ => {}
33    }
34}
35
36/// The value at `keys` of `v`, one map key after another.
37pub fn at<'a>(v: &'a Value, keys: &[&str]) -> Option<&'a Value> {
38    keys.iter().try_fold(v, |v, k| v.get(k))
39}
40
41/// A file of JSON (the game's) or Yog Data text as a value.
42pub fn read_bytes(bytes: &[u8]) -> Option<Value> {
43    yog_data::text::parse_value(std::str::from_utf8(bytes).ok()?).ok()
44}