arma_rs/value/
mod.rs

1use std::fmt::Display;
2
3mod features;
4mod from_arma;
5mod into_arma;
6pub mod loadout;
7
8pub use from_arma::{FromArma, FromArmaError};
9pub use into_arma::{DirectReturn, IntoArma};
10
11#[derive(Debug, Clone, PartialEq, PartialOrd)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13#[cfg_attr(feature = "serde", serde(untagged))]
14/// A value that can be converted to and from Arma types.
15pub enum Value {
16    /// Arma's `nil` value.
17    /// Represented as `null`
18    Null,
19    /// Arma's `number` value.
20    Number(f64),
21    /// Arma's `array` value.
22    /// Represented as `[...]`
23    Array(Vec<Value>),
24    /// Arma's `boolean` value.
25    /// Represented as `true` or `false`
26    Boolean(bool),
27    /// Arma's `string` value.
28    /// Represented as `"..."`
29    ///
30    /// Note: Arma escapes quotes with two double quotes.
31    /// This conversation will remove one step of escaping.
32    /// Example: `"My name is ""John""."` will become `My name is "John".`
33    String(String),
34    /// Unknown value. Contains the raw string.
35    Unknown(String),
36}
37
38impl Display for Value {
39    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40        match self {
41            Self::Null => write!(f, "null"),
42            Self::Number(n) => write!(f, "{n}"),
43            Self::Array(a) => write!(
44                f,
45                "[{}]",
46                a.iter()
47                    .map(ToString::to_string)
48                    .collect::<Vec<String>>()
49                    .join(",")
50            ),
51            Self::Boolean(b) => write!(f, "{b}"),
52            Self::String(s) => write!(f, "\"{}\"", s.replace('\"', "\"\"")),
53            Self::Unknown(s) => write!(f, "Unknown({})", s),
54        }
55    }
56}
57
58impl FromArma for Value {
59    fn from_arma(s: String) -> Result<Self, FromArmaError> {
60        match s.chars().next() {
61            Some('n') => Ok(Self::Null),
62            Some('t') | Some('f') => Ok(Value::Boolean(<bool>::from_arma(s)?)),
63            Some('0'..='9') | Some('-') => Ok(Value::Number(<f64>::from_arma(s)?)),
64            Some('[') => Ok(Value::Array(<Vec<Value>>::from_arma(s)?)),
65            Some('"') => Ok(Value::String(<String>::from_arma(s)?)),
66            _ => Ok(Value::Unknown(s)),
67        }
68    }
69}
70
71#[cfg(test)]
72mod tests {
73    use super::*;
74
75    #[test]
76    fn test_value_display() {
77        assert_eq!(Value::Null.to_string(), "null");
78        assert_eq!(Value::Number(1.0).to_string(), "1");
79        assert_eq!(Value::Number(1.5).to_string(), "1.5");
80        assert_eq!(Value::Number(-1.5).to_string(), "-1.5");
81        assert_eq!(Value::Boolean(true).to_string(), "true");
82        assert_eq!(Value::Boolean(false).to_string(), "false");
83        assert_eq!(Value::String("".to_string()).to_string(), "\"\"");
84        assert_eq!(Value::String(" ".to_string()).to_string(), "\" \"");
85        assert_eq!(Value::String("Hello".to_string()).to_string(), "\"Hello\"");
86        assert_eq!(
87            Value::String("Hello \"World\"".to_string()).to_string(),
88            "\"Hello \"\"World\"\"\""
89        );
90        assert_eq!(
91            Value::Array(vec![
92                Value::Number(1.0),
93                Value::Number(2.0),
94                Value::Number(3.0)
95            ])
96            .to_string(),
97            "[1,2,3]"
98        );
99        assert_eq!(
100            Value::Array(vec![
101                Value::String("Hello".to_string()),
102                Value::String("World".to_string())
103            ])
104            .to_string(),
105            "[\"Hello\",\"World\"]"
106        );
107    }
108
109    #[test]
110    fn value_from_arma() {
111        let value = Value::from_arma("null".to_string()).unwrap();
112        assert_eq!(value, Value::Null);
113        let value = Value::from_arma("true".to_string()).unwrap();
114        assert_eq!(value, Value::Boolean(true));
115        let value = Value::from_arma("false".to_string()).unwrap();
116        assert_eq!(value, Value::Boolean(false));
117        let value = Value::from_arma("1".to_string()).unwrap();
118        assert_eq!(value, Value::Number(1.0));
119        let value = Value::from_arma("1.5".to_string()).unwrap();
120        assert_eq!(value, Value::Number(1.5));
121        let value = Value::from_arma("-1.5".to_string()).unwrap();
122        assert_eq!(value, Value::Number(-1.5));
123        let value = Value::from_arma("[1,2,3]".to_string()).unwrap();
124        assert_eq!(
125            value,
126            Value::Array(vec![
127                Value::Number(1.0),
128                Value::Number(2.0),
129                Value::Number(3.0)
130            ])
131        );
132        let value = Value::from_arma("[\"Hello\",\"World\"]".to_string()).unwrap();
133        assert_eq!(
134            value,
135            Value::Array(vec![
136                Value::String("Hello".to_string()),
137                Value::String("World".to_string())
138            ])
139        );
140        let value = Value::from_arma("\"Hello\"".to_string()).unwrap();
141        assert_eq!(value, Value::String("Hello".to_string()));
142        let value = Value::from_arma("\"Hello \"\"World\"\"\"".to_string()).unwrap();
143        assert_eq!(value, Value::String("Hello \"World\"".to_string()));
144    }
145}