Skip to main content

yog_data/meaning/
mod.rs

1//! [`Meaning`]: what a reference is to Yog.
2
3use substrate_data::{Kind, Ref};
4
5use crate::found::TagRef;
6
7/// What opens a stack's data after an id (a block's state: `yog_ids::sep::STATE_OPEN`).
8const DATA_OPEN: &str = "{";
9use crate::{Res, kinds};
10
11/// What a reference is to Yog: content, a tag of content, a `.yres`
12/// entry, an image source or a translation key.
13#[derive(Debug, Clone, PartialEq)]
14pub enum Meaning {
15    Content(Ref),
16    Tag(TagRef),
17    Res(Res),
18    Image(String),
19    Lang(String),
20}
21
22impl Meaning {
23    /// What `r` is, if it's well formed for its kind (a tag names its
24    /// content's kind, a `.yres` entry its set).
25    pub fn of(r: Ref) -> Option<Meaning> {
26        let (kind, id) = (r.kind.as_str(), r.id.as_str());
27        Some(if kind == kinds::Tag::NAME {
28            let (kind, id) = id.split_once(yog_ids::sep::NAMESPACE)?;
29            Meaning::Tag(TagRef {
30                kind: kind.to_owned(),
31                id: id.to_owned(),
32            })
33        } else if kind == kinds::Res::NAME {
34            Meaning::Res(Res::parse(id)?)
35        } else if kind == kinds::Image::NAME {
36            Meaning::Image(id.to_owned())
37        } else if kind == kinds::Lang::NAME {
38            Meaning::Lang(id.to_owned())
39        } else {
40            // A content id is the game's way (`ns:path`, lower case, a block
41            // state or data after it), the game's when it names no namespace.
42            let base = id.split(yog_ids::sep::STATE_OPEN).next().unwrap_or(id);
43            let base = base.split(DATA_OPEN).next().unwrap_or(base);
44            if !yog_ids::valid_id(base) {
45                return None;
46            }
47            Meaning::Content(Ref::parse(kind, &yog_ids::qualify(id)).ok()?)
48        })
49    }
50}