ayaka_primitive/
raw_value.rs

1use serde::{Deserialize, Serialize};
2use std::borrow::Cow;
3
4/// The basic and only type used in scripts.
5/// ```
6/// # use ayaka_primitive::RawValue;
7/// assert_eq!(serde_yaml::from_str::<RawValue>("~").unwrap(), RawValue::Unit);
8/// assert_eq!(serde_yaml::from_str::<RawValue>("true").unwrap(), RawValue::Bool(true));
9/// assert_eq!(serde_yaml::from_str::<RawValue>("123").unwrap(), RawValue::Num(123));
10/// assert_eq!(serde_yaml::from_str::<RawValue>("\"hello\"").unwrap(), RawValue::Str("hello".to_string()));
11/// ```
12#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)]
13#[serde(untagged)]
14pub enum RawValue {
15    /// The unit type. It is empty, just like [`None`] or [`()`] in Rust.
16    #[default]
17    Unit,
18    /// The boolean type.
19    Bool(bool),
20    /// The number type. It's [`i64`].
21    Num(i64),
22    /// The string type.
23    Str(String),
24}
25
26/// Represents the type of [`RawValue`].
27#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
28pub enum ValueType {
29    /// The unit type.
30    Unit,
31    /// The boolean type.
32    Bool,
33    /// The number type.
34    Num,
35    /// The string type.
36    Str,
37}
38
39impl RawValue {
40    /// Gets [`ValueType`].
41    pub fn get_type(&self) -> ValueType {
42        match self {
43            Self::Unit => ValueType::Unit,
44            Self::Bool(_) => ValueType::Bool,
45            Self::Num(_) => ValueType::Num,
46            Self::Str(_) => ValueType::Str,
47        }
48    }
49
50    /// Gets a boolean from the value:
51    /// * A [`RawValue::Unit`] converts to `false`.
52    /// * A [`RawValue::Num`] converts to `false` if and only if it's zero.
53    /// * A [`RawValue::Str`] converts to `false` if and only if it's empty.
54    ///
55    /// ```
56    /// # use ayaka_primitive::RawValue;
57    /// let unit_value = RawValue::Unit;
58    /// assert!(!unit_value.get_bool());
59    /// let num_value = RawValue::Num(123);
60    /// assert!(num_value.get_bool());
61    /// let str_value = RawValue::Str("hello".to_string());
62    /// assert!(str_value.get_bool());
63    /// let empty_str_value = RawValue::Str(String::default());
64    /// assert!(!empty_str_value.get_bool());
65    /// ```
66    pub fn get_bool(&self) -> bool {
67        match self {
68            Self::Unit => false,
69            Self::Bool(b) => *b,
70            Self::Num(i) => *i != 0,
71            Self::Str(s) => !s.is_empty(),
72        }
73    }
74
75    /// Gets a number from the value:
76    /// * A [`RawValue::Unit`] converts to 0.
77    /// * A [`RawValue::Bool`] converts `false` to 0 and `true` to 1.
78    /// * A [`RawValue::Str`] converts to the length of the string.
79    ///
80    /// ```
81    /// # use ayaka_primitive::RawValue;
82    /// let unit_value = RawValue::Unit;
83    /// assert_eq!(unit_value.get_num(), 0);
84    /// let bool_value = RawValue::Bool(true);
85    /// assert_eq!(bool_value.get_num(), 1);
86    /// let str_value = RawValue::Str("hello".to_string());
87    /// assert_eq!(str_value.get_num(), 5);
88    /// ```
89    pub fn get_num(&self) -> i64 {
90        match self {
91            Self::Unit => 0,
92            Self::Bool(b) => *b as i64,
93            Self::Num(i) => *i,
94            Self::Str(s) => s.len() as i64,
95        }
96    }
97
98    /// Gets a string from the value:
99    /// * A [`RawValue::Unit`] converts to empty string.
100    /// * A [`RawValue::Bool`] converts to "false" or "true".
101    /// * A [`RawValue::Num`] converts to the string representation of the number.\
102    ///
103    /// Be careful to use `get_str().into_owned()`, if possible, use `into_str()` instead.
104    ///
105    /// ```
106    /// # use ayaka_primitive::RawValue;
107    /// let unit_value = RawValue::Unit;
108    /// assert_eq!(unit_value.get_str(), "");
109    /// let bool_value = RawValue::Bool(true);
110    /// assert_eq!(bool_value.get_str(), "true");
111    /// let num_value = RawValue::Num(123);
112    /// assert_eq!(num_value.get_str(), "123");
113    /// ```
114    pub fn get_str(&self) -> Cow<str> {
115        match self {
116            Self::Unit => Cow::default(),
117            Self::Bool(b) => b.to_string().into(),
118            Self::Num(i) => i.to_string().into(),
119            Self::Str(s) => s.as_str().into(),
120        }
121    }
122
123    /// Gets a string from the value:
124    /// * A [`RawValue::Unit`] converts to empty string.
125    /// * A [`RawValue::Bool`] converts to "false" or "true".
126    /// * A [`RawValue::Num`] converts to the string representation of the number.
127    pub fn into_str(self) -> String {
128        match self {
129            Self::Unit => String::default(),
130            Self::Bool(b) => b.to_string(),
131            Self::Num(i) => i.to_string(),
132            Self::Str(s) => s,
133        }
134    }
135}
136
137#[cfg(test)]
138mod test {
139    use crate::*;
140
141    #[test]
142    fn serde_value() {
143        assert_eq!(
144            serde_yaml::from_str::<RawValue>("~").unwrap(),
145            RawValue::Unit
146        );
147
148        assert_eq!(
149            serde_yaml::from_str::<RawValue>("true").unwrap(),
150            RawValue::Bool(true)
151        );
152        assert_eq!(
153            serde_yaml::from_str::<RawValue>("false").unwrap(),
154            RawValue::Bool(false)
155        );
156
157        assert_eq!(
158            serde_yaml::from_str::<RawValue>("114514").unwrap(),
159            RawValue::Num(114514)
160        );
161        assert_eq!(
162            serde_yaml::from_str::<RawValue>("-1919810").unwrap(),
163            RawValue::Num(-1919810)
164        );
165
166        assert_eq!(
167            serde_yaml::from_str::<RawValue>("\"Hello world!\"").unwrap(),
168            RawValue::Str("Hello world!".into())
169        );
170
171        assert_eq!(serde_yaml::to_string(&RawValue::Unit).unwrap(), "null\n");
172
173        assert_eq!(
174            serde_yaml::to_string(&RawValue::Bool(true)).unwrap(),
175            "true\n"
176        );
177        assert_eq!(
178            serde_yaml::to_string(&RawValue::Bool(false)).unwrap(),
179            "false\n"
180        );
181
182        assert_eq!(
183            serde_yaml::to_string(&RawValue::Num(114514)).unwrap(),
184            "114514\n"
185        );
186        assert_eq!(
187            serde_yaml::to_string(&RawValue::Num(-1919)).unwrap(),
188            "-1919\n"
189        );
190
191        assert_eq!(
192            serde_yaml::to_string(&RawValue::Str("aaa".into())).unwrap(),
193            "aaa\n"
194        );
195    }
196}