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}