1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
//! Sym used to identify shader module resources.
use std::borrow::Borrow;
use std::ops::Deref;
use std::fmt;
use std::str::FromStr;

pub struct Sym(str);
impl Sym {
    pub fn new<S: AsRef<str> + ?Sized>(literal: &S) -> &Sym {
        unsafe { &*(literal.as_ref() as *const str as *const Sym) }
    }
    pub fn segs<'a>(&'a self) -> Segs<'a> { Segs(self.0.as_ref(), false) }
}
impl ToOwned for Sym {
    type Owned = Symbol;
    fn to_owned(&self) -> Symbol { Symbol::from(self.0.to_owned()) }
}
impl AsRef<str> for Sym {
    fn as_ref(&self) -> &str { &self.0 }
}
impl AsRef<Sym> for str {
    fn as_ref(&self) -> &Sym { Sym::new(self) }
}
impl AsRef<Sym> for Sym {
    fn as_ref(&self) -> &Sym { self }
}
impl fmt::Display for Sym {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.0.fmt(f) }
}
impl fmt::Debug for Sym {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.0.fmt(f) }
}

pub struct Symbol(Box<Sym>);
impl Symbol {
    pub fn new<S: AsRef<str> + ?Sized>(literal: &S) -> Self {
        Sym::new(literal).to_owned()
    }
    pub fn segs<'a>(&'a self) -> Segs<'a> { Segs(&(*self.0).0, false) }
    pub fn push<'a>(&mut self, seg: &Seg<'a>) {
        let inner = format!("{}.{}", &(self.0).0, seg).into_boxed_str();
        self.0 = Symbol::from(inner.as_ref()).0;
    }
    pub fn pop(&mut self) -> Option<Symbol> {
        fn split_sym(literal: &str) -> Option<(Symbol, Symbol)> {
            if literal.len() == 0 { return None; }
            let end = literal.bytes().rposition(|c| c == '.' as u8).unwrap_or(0);
            let rv = literal[end + 1..].to_owned().into();
            let new_inner = literal[..end].to_owned().into();
            Some((rv, new_inner))
        }
        let (rv, new_inner) = split_sym(&(self.0).0)?;
        self.0 = new_inner.0;
        Some(rv)
    }
}
impl Default for Symbol {
    fn default() -> Symbol { Symbol::new("") }
}
impl Clone for Symbol {
    fn clone(&self) -> Symbol { self.0.to_owned() }
}
impl From<Box<Sym>> for Symbol {
    fn from(boxed: Box<Sym>) -> Symbol {
        Symbol(boxed)
    }
}
impl From<String> for Symbol {
    fn from(literal: String) -> Symbol {
        unsafe {
            let ptr = std::boxed::Box::leak(literal.into_boxed_str()) as *mut str;
            let ptr = ptr as *mut Sym;
            let inner = Box::from_raw(ptr);
            inner.into()
        }
    }
}
impl From<&'_ str> for Symbol {
    fn from(literal: &'_ str) -> Symbol { literal.to_owned().into() }
}
impl<'a> From<Seg<'a>> for Symbol {
    fn from(seg: Seg<'a>) -> Symbol { Symbol::from(format!("{}", seg)) }
}
impl Borrow<Sym> for Symbol {
    fn borrow(&self) -> &Sym { self }
}
impl Deref for Symbol {
    type Target = Sym;
    fn deref(&self) -> &Sym { &self.0 }
}
impl fmt::Display for Symbol {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.0.fmt(f) }
}
impl fmt::Debug for Symbol {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (self as &dyn fmt::Display).fmt(f) }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Seg<'a> {
    Index(usize),
    Name(&'a str),
    Empty,
}
impl<'a> Seg<'a> {
    pub fn index(idx: usize) -> Self { Seg::Index(idx) }
    pub fn name(name: &'a str) -> Self { Seg::Name(name) }
    pub fn empty() -> Self { Seg::Empty }

    pub fn is_index(&self) -> bool {
        if let Seg::Index(_) = self { true } else { false }
    }
    pub fn is_name(&self) -> bool {
        if let Seg::Name(_) = self { true } else { false }
    }
    pub fn is_empty(&self) -> bool {
        if let Seg::Empty = self { true } else { false }
    }
}
impl<'a> fmt::Display for Seg<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use Seg::*;
        match self {
            Index(idx) => f.write_fmt(format_args!("{}", idx)),
            Name(name) => f.write_str(name),
            Empty => Ok(()),
        }
    }
}

pub struct Segs<'a>(&'a str, bool); // True means that we have reached the end.
impl<'a> Segs<'a> {
    pub fn remaining(&self) -> &Sym { Sym::new(self.0) }
}
impl<'a> Iterator for Segs<'a> {
    type Item = Seg<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        if self.0.is_empty() {
            return if self.1 { None } else { Some(Seg::Empty) };
        }
        let txt = if let Some(pos) = self.0.bytes().position(|c| c == '.' as u8) {
            let txt = &self.0[..pos];
            self.0 = &self.0[(pos + 1)..];
            txt
        } else {
            let txt = &self.0[..];
            self.0 = &"";
            self.1 = true;
            txt
        };
        if txt.is_empty() { return Some(Seg::Empty); }
        let seg = if let Ok(idx) = usize::from_str(txt) {
            Seg::Index(idx)
        } else {
            Seg::Name(txt)
        };
        return Some(seg);
    }
}