plux_rs/variable/
var.rs

1use std::fmt::Display;
2
3use serde::{Deserialize, Serialize};
4
5use crate::utils::ParseVariableError;
6
7/// Represents a dynamically typed value that can be passed between plugins.
8///
9/// Variable is the core data type used for communication between plugins and the host.
10/// It supports all common data types and provides type-safe conversion methods.
11///
12/// # Variants
13///
14/// * `Null` - Represents a null/empty value (default)
15/// * `I8`, `I16`, `I32`, `I64` - Signed integer types
16/// * `U8`, `U16`, `U32`, `U64` - Unsigned integer types
17/// * `F32`, `F64` - Floating point types
18/// * `Bool` - Boolean values
19/// * `Char` - Unicode characters
20/// * `String` - UTF-8 strings
21/// * `List` - Lists/arrays of variables
22///
23/// # Examples
24///
25/// ```rust
26/// use plux_rs::variable::Variable;
27///
28/// // Create variables of different types
29/// let num = Variable::I32(42);
30/// let text = Variable::String("Hello".to_string());
31/// let flag = Variable::Bool(true);
32/// let list = Variable::List(vec![num, text, flag]);
33///
34/// // Convert from Rust types
35/// let var1: Variable = 42_i32.into();
36/// let var2: Variable = "hello".into();
37/// let var3: Variable = vec![1, 2, 3].into();
38/// ```
39#[derive(Default, PartialEq, PartialOrd, Clone, Debug, Serialize, Deserialize)]
40pub enum Variable {
41    /// Null/empty value
42    #[default]
43    Null,
44    /// 8-bit signed integer
45    I8(i8),
46    /// 16-bit signed integer
47    I16(i16),
48    /// 32-bit signed integer
49    I32(i32),
50    /// 64-bit signed integer
51    I64(i64),
52    /// 8-bit unsigned integer
53    U8(u8),
54    /// 16-bit unsigned integer
55    U16(u16),
56    /// 32-bit unsigned integer
57    U32(u32),
58    /// 64-bit unsigned integer
59    U64(u64),
60    /// 32-bit floating point
61    F32(f32),
62    /// 64-bit floating point
63    F64(f64),
64    /// Boolean value
65    Bool(bool),
66    /// Unicode character
67    Char(char),
68    /// UTF-8 string
69    String(String),
70    /// List of variables
71    List(Vec<Variable>),
72}
73
74/// Trait for converting Variables to specific Rust types.
75///
76/// FromVariable provides methods to safely convert Variables to their corresponding
77/// Rust types. It supports owned, borrowed, and mutable borrowed conversions.
78///
79/// # Type Parameters
80///
81/// * `Output` - The owned type to convert to
82/// * `RefOutput<'a>` - The borrowed type to convert to
83/// * `MutOutput<'a>` - The mutable borrowed type to convert to
84///
85/// # Required Methods
86///
87/// * `from_var` - Convert an owned Variable to the target type
88/// * `from_var_ref` - Convert a borrowed Variable to the target type
89/// * `from_var_mut` - Convert a mutable borrowed Variable to the target type
90///
91/// # Example
92///
93/// ```rust
94/// use plux_rs::variable::{Variable, FromVariable};
95///
96/// let var = Variable::I32(42);
97///
98/// // Convert to owned value
99/// let owned: i32 = i32::from_var(var).unwrap();
100///
101/// // Convert to borrowed value
102/// let var_ref = &Variable::I32(42);
103/// let borrowed: &i32 = i32::from_var_ref(var_ref).unwrap();
104/// ```
105pub trait FromVariable {
106    /// The owned output type
107    type Output;
108    /// The borrowed output type
109    type RefOutput<'a>
110    where
111        Self: 'a;
112    /// The mutable borrowed output type
113    type MutOutput<'a>
114    where
115        Self: 'a;
116
117    /// Convert an owned Variable to the target type.
118    ///
119    /// # Parameters
120    ///
121    /// * `var` - The Variable to convert
122    ///
123    /// # Returns
124    ///
125    /// Returns `Result<Self::Output, ParseVariableError>` containing the converted value
126    /// or an error if the conversion fails.
127    fn from_var(var: Variable) -> Result<Self::Output, ParseVariableError>;
128
129    /// Convert a borrowed Variable to the target type.
130    ///
131    /// # Parameters
132    ///
133    /// * `var` - The Variable to convert
134    ///
135    /// # Returns
136    ///
137    /// Returns `Result<Self::RefOutput<'_>, ParseVariableError>` containing the converted value
138    /// or an error if the conversion fails.
139    fn from_var_ref(var: &Variable) -> Result<Self::RefOutput<'_>, ParseVariableError>;
140
141    /// Convert a mutable borrowed Variable to the target type.
142    ///
143    /// # Parameters
144    ///
145    /// * `var` - The Variable to convert
146    ///
147    /// # Returns
148    ///
149    /// Returns `Result<Self::MutOutput<'_>, ParseVariableError>` containing the converted value
150    /// or an error if the conversion fails.
151    fn from_var_mut(var: &mut Variable) -> Result<Self::MutOutput<'_>, ParseVariableError>;
152}
153
154macro_rules! impl_from {
155    ($ty:ty, $from:ident) => {
156        impl From<$ty> for Variable {
157            fn from(x: $ty) -> Self {
158                Self::$from(x)
159            }
160        }
161    };
162}
163
164macro_rules! impl_from_variable {
165    ($ty:ty, $from:ident) => {
166        impl FromVariable for $ty {
167            type Output = Self;
168            type RefOutput<'a> = &'a Self;
169            type MutOutput<'a> = &'a mut Self;
170
171            fn from_var(var: Variable) -> Result<Self::Output, ParseVariableError> {
172                match var {
173                    Variable::$from(x) => Ok(x),
174                    _ => Err(ParseVariableError::new(stringify!($from))),
175                }
176            }
177
178            fn from_var_ref(var: &Variable) -> Result<Self::RefOutput<'_>, ParseVariableError> {
179                match var {
180                    Variable::$from(x) => Ok(x),
181                    _ => Err(ParseVariableError::new(stringify!($from))),
182                }
183            }
184
185            fn from_var_mut(var: &mut Variable) -> Result<Self::MutOutput<'_>, ParseVariableError> {
186                match var {
187                    Variable::$from(x) => Ok(x),
188                    _ => Err(ParseVariableError::new(stringify!($from))),
189                }
190            }
191        }
192    };
193}
194
195impl From<&str> for Variable {
196    fn from(x: &str) -> Self {
197        Self::String(x.to_string())
198    }
199}
200
201impl<T> From<&[T]> for Variable
202where
203    T: Into<Variable> + Clone,
204{
205    fn from(x: &[T]) -> Self {
206        Self::List(x.iter().cloned().map(|item| item.into()).collect())
207    }
208}
209
210impl<T> From<Vec<T>> for Variable
211where
212    T: Into<Variable>,
213{
214    fn from(x: Vec<T>) -> Self {
215        Self::List(x.into_iter().map(|item| item.into()).collect())
216    }
217}
218
219impl_from!(i8, I8);
220impl_from!(i16, I16);
221impl_from!(i32, I32);
222impl_from!(i64, I64);
223impl_from!(u8, U8);
224impl_from!(u16, U16);
225impl_from!(u32, U32);
226impl_from!(u64, U64);
227impl_from!(f32, F32);
228impl_from!(f64, F64);
229impl_from!(bool, Bool);
230impl_from!(char, Char);
231impl_from!(String, String);
232
233impl Display for Variable {
234    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
235        match self {
236            Variable::Null => write!(f, "Null"),
237            Variable::I8(v) => write!(f, "{v}"),
238            Variable::I16(v) => write!(f, "{v}"),
239            Variable::I32(v) => write!(f, "{v}"),
240            Variable::I64(v) => write!(f, "{v}"),
241            Variable::U8(v) => write!(f, "{v}"),
242            Variable::U16(v) => write!(f, "{v}"),
243            Variable::U32(v) => write!(f, "{v}"),
244            Variable::U64(v) => write!(f, "{v}"),
245            Variable::F32(v) => write!(f, "{v}"),
246            Variable::F64(v) => write!(f, "{v}"),
247            Variable::Bool(v) => write!(f, "{v}"),
248            Variable::Char(v) => write!(f, "{v}"),
249            Variable::String(v) => write!(f, "{v}"),
250            Variable::List(v) => write!(f, "{v:?}"),
251        }
252    }
253}
254
255impl Variable {
256    /// Check if the Variable represents a null value.
257    ///
258    /// # Returns
259    ///
260    /// Returns `true` if the Variable is `Variable::Null`, `false` otherwise.
261    ///
262    /// # Example
263    ///
264    /// ```rust
265    /// use plux_rs::variable::Variable;
266    ///
267    /// let null_var = Variable::Null;
268    /// let int_var = Variable::I32(42);
269    ///
270    /// assert!(null_var.is_null());
271    /// assert!(!int_var.is_null());
272    /// ```
273    pub fn is_null(&self) -> bool {
274        match self {
275            Variable::Null => true,
276            _ => false,
277        }
278    }
279}
280
281impl Variable {
282    /// Parse the Variable into a specific type (panics on error).
283    ///
284    /// This method converts the Variable to the specified type, panicking if
285    /// the conversion fails. Use this when you're certain about the type.
286    ///
287    /// # Type Parameters
288    ///
289    /// * `F` - The target type that implements FromVariable
290    ///
291    /// # Returns
292    ///
293    /// Returns the converted value of type `F::Output`.
294    ///
295    /// # Panics
296    ///
297    /// Panics if the Variable cannot be converted to the target type.
298    ///
299    /// # Example
300    ///
301    /// ```rust
302    /// use plux_rs::variable::Variable;
303    ///
304    /// let var = Variable::I32(42);
305    /// let num: i32 = var.parse::<i32>();
306    /// assert_eq!(num, 42);
307    /// ```
308    pub fn parse<F>(self) -> F::Output
309    where
310        F: FromVariable,
311    {
312        F::from_var(self).unwrap()
313    }
314
315    /// Parse the Variable into a specific type by reference (panics on error).
316    ///
317    /// This method converts the Variable to the specified type without consuming it,
318    /// panicking if the conversion fails.
319    ///
320    /// # Type Parameters
321    ///
322    /// * `F` - The target type that implements FromVariable
323    ///
324    /// # Returns
325    ///
326    /// Returns a reference to the converted value of type `F::RefOutput<'_>`.
327    ///
328    /// # Panics
329    ///
330    /// Panics if the Variable cannot be converted to the target type.
331    pub fn parse_ref<F>(&self) -> F::RefOutput<'_>
332    where
333        F: FromVariable,
334    {
335        F::from_var_ref(self).unwrap()
336    }
337
338    /// Parse the Variable into a specific type by mutable reference (panics on error).
339    ///
340    /// This method converts the Variable to the specified type without consuming it,
341    /// panicking if the conversion fails.
342    ///
343    /// # Type Parameters
344    ///
345    /// * `F` - The target type that implements FromVariable
346    ///
347    /// # Returns
348    ///
349    /// Returns a mutable reference to the converted value of type `F::MutOutput<'_>`.
350    ///
351    /// # Panics
352    ///
353    /// Panics if the Variable cannot be converted to the target type.
354    pub fn parse_mut<F>(&mut self) -> F::MutOutput<'_>
355    where
356        F: FromVariable,
357    {
358        F::from_var_mut(self).unwrap()
359    }
360
361    /// Try to parse the Variable into a specific type.
362    ///
363    /// This method attempts to convert the Variable to the specified type,
364    /// returning an error if the conversion fails.
365    ///
366    /// # Type Parameters
367    ///
368    /// * `F` - The target type that implements FromVariable
369    ///
370    /// # Returns
371    ///
372    /// Returns `Result<F::Output, ParseVariableError>` containing the converted value
373    /// or an error if the conversion fails.
374    ///
375    /// # Example
376    ///
377    /// ```rust
378    /// use plux_rs::variable::Variable;
379    ///
380    /// let var = Variable::I32(42);
381    /// match var.try_parse::<i32>() {
382    ///     Ok(num) => println!("Parsed: {}", num),
383    ///     Err(e) => println!("Parse error: {}", e),
384    /// }
385    /// ```
386    pub fn try_parse<F>(self) -> Result<F::Output, ParseVariableError>
387    where
388        F: FromVariable,
389    {
390        F::from_var(self)
391    }
392
393    /// Try to parse the Variable into a specific type by reference.
394    ///
395    /// This method attempts to convert the Variable to the specified type without consuming it,
396    /// returning an error if the conversion fails.
397    ///
398    /// # Type Parameters
399    ///
400    /// * `F` - The target type that implements FromVariable
401    ///
402    /// # Returns
403    ///
404    /// Returns `Result<F::RefOutput<'_>, ParseVariableError>` containing a reference to the
405    /// converted value or an error if the conversion fails.
406    pub fn try_parse_ref<F>(&self) -> Result<F::RefOutput<'_>, ParseVariableError>
407    where
408        F: FromVariable,
409    {
410        F::from_var_ref(self)
411    }
412
413    /// Try to parse the Variable into a specific type by mutable reference.
414    ///
415    /// This method attempts to convert the Variable to the specified type without consuming it,
416    /// returning an error if the conversion fails.
417    ///
418    /// # Type Parameters
419    ///
420    /// * `F` - The target type that implements FromVariable
421    ///
422    /// # Returns
423    ///
424    /// Returns `Result<F::MutOutput<'_>, ParseVariableError>` containing a mutable reference to the
425    /// converted value or an error if the conversion fails.
426    pub fn try_parse_mut<F>(&mut self) -> Result<F::MutOutput<'_>, ParseVariableError>
427    where
428        F: FromVariable,
429    {
430        F::from_var_mut(self)
431    }
432}
433
434impl FromVariable for Vec<Variable> {
435    type Output = Self;
436    type RefOutput<'a> = &'a Self;
437    type MutOutput<'a> = &'a mut Self;
438
439    fn from_var(var: Variable) -> Result<Self::Output, ParseVariableError> {
440        match var {
441            Variable::List(x) => Ok(x),
442            _ => Err(ParseVariableError::new("Vec<Variable>")),
443        }
444    }
445
446    fn from_var_ref(var: &Variable) -> Result<Self::RefOutput<'_>, ParseVariableError> {
447        match var {
448            Variable::List(x) => Ok(x),
449            _ => Err(ParseVariableError::new("Vec<Variable>")),
450        }
451    }
452
453    fn from_var_mut(var: &mut Variable) -> Result<Self::MutOutput<'_>, ParseVariableError> {
454        match var {
455            Variable::List(x) => Ok(x),
456            _ => Err(ParseVariableError::new("Vec<Variable>")),
457        }
458    }
459}
460
461impl<T> FromVariable for Vec<T>
462where
463    T: FromVariable,
464{
465    type Output = Vec<T::Output>;
466    type RefOutput<'a>
467        = Vec<T::RefOutput<'a>>
468    where
469        T: 'a;
470    type MutOutput<'a>
471        = Vec<T::MutOutput<'a>>
472    where
473        T: 'a;
474
475    fn from_var(var: Variable) -> Result<Self::Output, ParseVariableError> {
476        match var {
477            Variable::List(x) => {
478                let mut arr = vec![];
479                for var in x.into_iter() {
480                    arr.push(var.try_parse::<T>()?);
481                }
482                Ok(arr)
483            }
484            _ => Err(ParseVariableError::new("Vec<T>")),
485        }
486    }
487
488    fn from_var_ref(var: &Variable) -> Result<Self::RefOutput<'_>, ParseVariableError> {
489        match var {
490            Variable::List(x) => {
491                let mut arr = vec![];
492                for var in x.iter() {
493                    arr.push(var.try_parse_ref::<T>()?);
494                }
495                Ok(arr)
496            }
497            _ => Err(ParseVariableError::new("Vec<T>")),
498        }
499    }
500
501    fn from_var_mut(var: &mut Variable) -> Result<Self::MutOutput<'_>, ParseVariableError> {
502        match var {
503            Variable::List(x) => {
504                let mut arr = vec![];
505                for var in x.iter_mut() {
506                    arr.push(var.try_parse_mut::<T>()?);
507                }
508                Ok(arr)
509            }
510            _ => Err(ParseVariableError::new("Vec<T>")),
511        }
512    }
513}
514
515impl_from_variable!(i8, I8);
516impl_from_variable!(i16, I16);
517impl_from_variable!(i32, I32);
518impl_from_variable!(i64, I64);
519impl_from_variable!(u8, U8);
520impl_from_variable!(u16, U16);
521impl_from_variable!(u32, U32);
522impl_from_variable!(u64, U64);
523impl_from_variable!(f32, F32);
524impl_from_variable!(f64, F64);
525impl_from_variable!(bool, Bool);
526impl_from_variable!(char, Char);
527impl_from_variable!(String, String);
528
529#[test]
530fn into() {
531    let a = 10_i16;
532
533    let b: Variable = a.into();
534    assert_eq!(b, Variable::I16(10));
535}
536
537#[test]
538fn parse() {
539    let mut a: Variable = 10_i16.into();
540
541    assert_eq!(a.clone().parse::<i16>(), 10);
542    assert_eq!(a.parse_ref::<i16>(), &10);
543    assert_eq!(a.parse_mut::<i16>(), &mut 10);
544
545    match a.clone().try_parse::<i16>() {
546        Ok(b) => assert_eq!(b, 10),
547        Err(e) => panic!("{}", e),
548    };
549
550    match a.try_parse_ref::<i16>() {
551        Ok(b) => assert_eq!(b, &10),
552        Err(e) => panic!("{}", e),
553    };
554
555    match a.try_parse_mut::<i16>() {
556        Ok(b) => assert_eq!(b, &mut 10),
557        Err(e) => panic!("{}", e),
558    };
559}
560
561#[test]
562fn parse_vec() {
563    let mut a: Variable = vec![10_i16].into();
564
565    let b = a.parse_mut::<Vec<i16>>();
566
567    assert_eq!(b, vec![&mut 10]);
568}