mindustry logic execution, map- and schematic- parsing and rendering
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
#[derive(Copy, Clone, Debug)]
pub enum LVar<'string> {
    Num(f64),
    String(&'string str),
}

impl PartialEq for LVar<'_> {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (Self::Num(a), Self::Num(b)) => (a - b).abs() < 0.000_001,
            (Self::String(l0), Self::String(r0)) => l0 == r0,
            _ => false,
        }
    }
}

impl LVar<'_> {
    // get null
    pub const fn null() -> LVar<'static> {
        LVar::Num(0.0)
    }
}

#[derive(Copy, Clone)]
pub enum LAddress<'str> {
    Const(LVar<'str>),
    Address(usize, Priv),
}

impl<'v> LAddress<'v> {
    /// # Safety
    ///
    /// you must make sure that addr is in bounds of the memory.
    pub(crate) const unsafe fn addr(addr: usize) -> Self {
        LAddress::Address(addr, Priv { _priv: () })
    }

    pub(crate) fn cnst(c: impl Into<LVar<'v>>) -> Self {
        Self::Const(c.into())
    }
}

#[derive(Copy, Clone)]
pub struct Priv {
    _priv: (),
}

impl std::fmt::Debug for LAddress<'_> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::Const(c) => write!(f, "LAddress {c}"),
            Self::Address(n, ..) => write!(f, "LAddress {n:x}"),
        }
    }
}

impl std::fmt::Display for LVar<'_> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::Num(n) => write!(f, "{n}"),
            Self::String(s) => write!(f, r#"{}"#, s.replace(r"\n", "\n")),
        }
    }
}

impl From<f64> for LVar<'_> {
    fn from(value: f64) -> Self {
        Self::Num(value)
    }
}

impl From<bool> for LVar<'_> {
    fn from(value: bool) -> Self {
        Self::Num(value.into())
    }
}

impl<'s> From<&'s str> for LVar<'s> {
    fn from(value: &'s str) -> Self {
        Self::String(value)
    }
}

/// cleared every loop
#[derive(Default, Debug)]
pub struct LRegistry<'str>(Box<[LVar<'str>]>);

impl<'s> LRegistry<'s> {
    pub fn new(size: usize) -> Self {
        Self(vec![LVar::null(); size].into_boxed_slice())
    }

    pub fn clear(&mut self) {
        for var in &mut *self.0 {
            *var = LVar::null();
        }
    }

    pub fn get(&self, a: LAddress<'s>) -> LVar<'s> {
        match a {
            // SAFETY: addr constructor requires bounds
            LAddress::Address(n, ..) => unsafe { *self.0.get_unchecked(n) },
            LAddress::Const(n) => n,
        }
    }

    pub fn set(&mut self, a: LAddress<'s>, b: LAddress<'s>) -> bool {
        match a {
            LAddress::Const(_) => false,
            LAddress::Address(v, ..) => {
                match b {
                    LAddress::Const(n) => {
                        // SAFETY: v comes from Address, therefore safe
                        *unsafe { self.0.get_unchecked_mut(v) } = n;
                    }
                    LAddress::Address(n, ..) => {
                        // SAFETY: n comes from Address, therefore safe
                        let b = *unsafe { self.0.get_unchecked(n) };
                        // SAFETY: v comes from Addr, therefore safe
                        *unsafe { self.0.get_unchecked_mut(v) } = b;
                    }
                };
                true
            }
        }
    }

    pub fn get_mut(&mut self, a: LAddress<'s>) -> Option<&mut LVar<'s>> {
        match a {
            LAddress::Const(_) => None,
            // SAFETY: addr constructor requires bounds
            LAddress::Address(n, ..) => Some(unsafe { self.0.get_unchecked_mut(n) }),
        }
    }
}