Skip to main content

somni_expr/
value.rs

1//! Types and operations.
2
3use indexmap::IndexMap;
4use somni_parser::parser::DefaultTypeSet;
5use std::rc::Rc;
6
7use crate::{OperatorError, RefPointee, Type, TypeSet};
8
9/// A Rust type that is used as the storage for a Somni type.
10pub trait ValueType: Sized + Clone + PartialEq + std::fmt::Debug {
11    /// The Somni type this Rust type is used for.
12    const TYPE: Type;
13
14    /// The type of the result of the unary `-` operator.
15    type NegateOutput: ValueType;
16
17    /// Implements the `==` operator.
18    fn equals(_a: Self, _b: Self) -> Result<bool, OperatorError> {
19        unimplemented!("Operation not supported")
20    }
21    /// Implements the `<` operator.
22    fn less_than(_a: Self, _b: Self) -> Result<bool, OperatorError> {
23        unimplemented!("Operation not supported")
24    }
25
26    /// Implements the `<=` operator.
27    fn less_than_or_equal(a: Self, b: Self) -> Result<bool, OperatorError> {
28        let less = Self::less_than(a.clone(), b.clone())?;
29        Ok(less || Self::equals(a, b)?)
30    }
31
32    /// Implements the `!=` operator.
33    fn not_equals(a: Self, b: Self) -> Result<bool, OperatorError> {
34        let equals = Self::equals(a, b)?;
35        Ok(!equals)
36    }
37    /// Implements the `|` operator.
38    fn bitwise_or(_a: Self, _b: Self) -> Result<Self, OperatorError> {
39        unimplemented!("Operation not supported")
40    }
41    /// Implements the `^` operator.
42    fn bitwise_xor(_a: Self, _b: Self) -> Result<Self, OperatorError> {
43        unimplemented!("Operation not supported")
44    }
45    /// Implements the `&` operator.
46    fn bitwise_and(_a: Self, _b: Self) -> Result<Self, OperatorError> {
47        unimplemented!("Operation not supported")
48    }
49    /// Implements the `<<` operator.
50    fn shift_left(_a: Self, _b: Self) -> Result<Self, OperatorError> {
51        unimplemented!("Operation not supported")
52    }
53    /// Implements the `>>` operator.
54    fn shift_right(_a: Self, _b: Self) -> Result<Self, OperatorError> {
55        unimplemented!("Operation not supported")
56    }
57    /// Implements the `+` operator.
58    fn add(_a: Self, _b: Self) -> Result<Self, OperatorError> {
59        unimplemented!("Operation not supported")
60    }
61    /// Implements the binary `-` operator.
62    fn subtract(_a: Self, _b: Self) -> Result<Self, OperatorError> {
63        unimplemented!("Operation not supported")
64    }
65    /// Implements the binary `*` operator.
66    fn multiply(_a: Self, _b: Self) -> Result<Self, OperatorError> {
67        unimplemented!("Operation not supported")
68    }
69    /// Implements the binary `/` operator.
70    fn divide(_a: Self, _b: Self) -> Result<Self, OperatorError> {
71        unimplemented!("Operation not supported")
72    }
73    /// Implements the binary `%` operator.
74    fn modulo(_a: Self, _b: Self) -> Result<Self, OperatorError> {
75        unimplemented!("Operation not supported")
76    }
77    /// Implements the unary `!` operator.
78    fn not(_a: Self) -> Result<Self, OperatorError> {
79        unimplemented!("Operation not supported")
80    }
81    /// Implements the unary `-` operator.
82    fn negate(_a: Self) -> Result<Self::NegateOutput, OperatorError> {
83        unimplemented!("Operation not supported")
84    }
85}
86
87impl ValueType for () {
88    type NegateOutput = Self;
89    const TYPE: Type = Type::Void;
90}
91
92macro_rules! value_type_int {
93    ($type:ty, $negate:ty, $kind:ident) => {
94        impl ValueType for $type {
95            const TYPE: Type = Type::$kind;
96            type NegateOutput = $negate;
97
98            fn less_than(a: Self, b: Self) -> Result<bool, OperatorError> {
99                Ok(a < b)
100            }
101            fn equals(a: Self, b: Self) -> Result<bool, OperatorError> {
102                Ok(a == b)
103            }
104            fn add(a: Self, b: Self) -> Result<Self, OperatorError> {
105                a.checked_add(b).ok_or(OperatorError::RuntimeError)
106            }
107            fn subtract(a: Self, b: Self) -> Result<Self, OperatorError> {
108                a.checked_sub(b).ok_or(OperatorError::RuntimeError)
109            }
110            fn multiply(a: Self, b: Self) -> Result<Self, OperatorError> {
111                a.checked_mul(b).ok_or(OperatorError::RuntimeError)
112            }
113            fn divide(a: Self, b: Self) -> Result<Self, OperatorError> {
114                if b == 0 {
115                    Err(OperatorError::RuntimeError)
116                } else {
117                    Ok(a / b)
118                }
119            }
120            fn modulo(a: Self, b: Self) -> Result<Self, OperatorError> {
121                if b == 0 {
122                    Err(OperatorError::RuntimeError)
123                } else {
124                    Ok(a % b)
125                }
126            }
127            fn bitwise_or(a: Self, b: Self) -> Result<Self, OperatorError> {
128                Ok(a | b)
129            }
130            fn bitwise_xor(a: Self, b: Self) -> Result<Self, OperatorError> {
131                Ok(a ^ b)
132            }
133            fn bitwise_and(a: Self, b: Self) -> Result<Self, OperatorError> {
134                Ok(a & b)
135            }
136            fn shift_left(a: Self, b: Self) -> Result<Self, OperatorError> {
137                if b < std::mem::size_of::<$type>() as Self * 8 {
138                    Ok(a << b)
139                } else {
140                    Err(OperatorError::RuntimeError)
141                }
142            }
143            fn shift_right(a: Self, b: Self) -> Result<Self, OperatorError> {
144                if b < std::mem::size_of::<$type>() as Self * 8 {
145                    Ok(a >> b)
146                } else {
147                    Err(OperatorError::RuntimeError)
148                }
149            }
150            fn not(a: Self) -> Result<Self, OperatorError> {
151                Ok(!a)
152            }
153            fn negate(a: Self) -> Result<Self::NegateOutput, OperatorError> {
154                Ok(-(a as $negate))
155            }
156        }
157    };
158}
159
160value_type_int!(u32, i32, Int);
161value_type_int!(u64, i64, Int);
162value_type_int!(u128, i128, Int);
163value_type_int!(i32, i32, SignedInt);
164value_type_int!(i64, i64, SignedInt);
165value_type_int!(i128, i128, SignedInt);
166
167impl ValueType for f32 {
168    const TYPE: Type = Type::Float;
169
170    type NegateOutput = Self;
171
172    fn less_than(a: Self, b: Self) -> Result<bool, OperatorError> {
173        Ok(a < b)
174    }
175    fn equals(a: Self, b: Self) -> Result<bool, OperatorError> {
176        Ok(a == b)
177    }
178    fn add(a: Self, b: Self) -> Result<Self, OperatorError> {
179        Ok(a + b)
180    }
181    fn subtract(a: Self, b: Self) -> Result<Self, OperatorError> {
182        Ok(a - b)
183    }
184    fn multiply(a: Self, b: Self) -> Result<Self, OperatorError> {
185        Ok(a * b)
186    }
187    fn divide(a: Self, b: Self) -> Result<Self, OperatorError> {
188        Ok(a / b)
189    }
190    fn modulo(a: Self, b: Self) -> Result<Self, OperatorError> {
191        Ok(a % b)
192    }
193    fn negate(a: Self) -> Result<Self::NegateOutput, OperatorError> {
194        Ok(-a)
195    }
196}
197
198impl ValueType for f64 {
199    const TYPE: Type = Type::Float;
200
201    type NegateOutput = Self;
202
203    fn less_than(a: Self, b: Self) -> Result<bool, OperatorError> {
204        Ok(a < b)
205    }
206    fn equals(a: Self, b: Self) -> Result<bool, OperatorError> {
207        Ok(a == b)
208    }
209    fn add(a: Self, b: Self) -> Result<Self, OperatorError> {
210        Ok(a + b)
211    }
212    fn subtract(a: Self, b: Self) -> Result<Self, OperatorError> {
213        Ok(a - b)
214    }
215    fn multiply(a: Self, b: Self) -> Result<Self, OperatorError> {
216        Ok(a * b)
217    }
218    fn divide(a: Self, b: Self) -> Result<Self, OperatorError> {
219        Ok(a / b)
220    }
221    fn modulo(a: Self, b: Self) -> Result<Self, OperatorError> {
222        Ok(a % b)
223    }
224    fn negate(a: Self) -> Result<Self::NegateOutput, OperatorError> {
225        Ok(-a)
226    }
227}
228
229impl ValueType for bool {
230    const TYPE: Type = Type::Bool;
231
232    type NegateOutput = Self;
233
234    fn equals(a: Self, b: Self) -> Result<bool, OperatorError> {
235        Ok(a == b)
236    }
237
238    fn bitwise_and(a: Self, b: Self) -> Result<bool, OperatorError> {
239        Ok(a & b)
240    }
241
242    fn bitwise_or(a: Self, b: Self) -> Result<bool, OperatorError> {
243        Ok(a | b)
244    }
245
246    fn bitwise_xor(a: Self, b: Self) -> Result<bool, OperatorError> {
247        Ok(a ^ b)
248    }
249
250    fn not(a: Self) -> Result<bool, OperatorError> {
251        Ok(!a)
252    }
253}
254
255for_each! {
256    ($string:ty) in [&str, String, Box<str>] => {
257        impl ValueType for $string {
258            const TYPE: Type = Type::String;
259            type NegateOutput = Self;
260
261            fn equals(a: Self, b: Self) -> Result<bool, OperatorError> {
262                Ok(a == b)
263            }
264        }
265    };
266}
267
268/// Represents any value in the expression language.
269#[derive(Debug)]
270pub enum TypedValue<T: TypeSet = DefaultTypeSet> {
271    /// Represents no value.
272    Void,
273    /// Represents an integer that may be signed or unsigned.
274    ///
275    /// MaybeSignedInt can compare equal with Int and SignedInt.
276    MaybeSignedInt(T::Integer),
277    /// Represents an unsigned integer.
278    Int(T::Integer),
279    /// Represents a signed integer.
280    SignedInt(T::SignedInteger),
281    /// Represents a floating-point.
282    Float(T::Float),
283    /// Represents a boolean.
284    Bool(bool),
285    /// Represents a string.
286    String(T::String),
287    /// Represents an iterator.
288    Iter(T::Iterator),
289    /// Represents a struct value: a named aggregate of typed fields.
290    Struct(SomniStruct<T>),
291    /// Represents a reference to a place (a variable, or a field within one).
292    Ref(Reference),
293}
294
295/// A struct value: a struct name plus its fields, keyed by field name.
296///
297/// This is the runtime representation of a Somni struct and doubles as the
298/// Rust-side boundary type. Field values are stored by name; the field order in
299/// the map reflects the struct's declaration order.
300///
301/// The entire representation lives behind a single [`Rc`], so `SomniStruct`
302/// (and therefore [`TypedValue`], which embeds it by value) is only one pointer
303/// wide. Clones share the payload until mutation, when [`Rc::make_mut`] provides
304/// copy-on-write value semantics. The internals are reached through
305/// [`name`](Self::name), [`fields`](Self::fields), [`fields_mut`](Self::fields_mut)
306/// and [`into_parts`](Self::into_parts).
307pub struct SomniStruct<T: TypeSet = DefaultTypeSet> {
308    inner: Rc<SomniStructInner<T>>,
309}
310
311/// The heap-allocated payload of a [`SomniStruct`].
312struct SomniStructInner<T: TypeSet> {
313    name: Box<str>,
314    fields: IndexMap<Box<str>, TypedValue<T>>,
315}
316
317impl<T: TypeSet> Clone for SomniStructInner<T> {
318    fn clone(&self) -> Self {
319        Self {
320            name: self.name.clone(),
321            fields: self.fields.clone(),
322        }
323    }
324}
325
326impl<T: TypeSet> SomniStruct<T> {
327    /// Creates a struct value from its name and fields.
328    pub fn new(name: Box<str>, fields: IndexMap<Box<str>, TypedValue<T>>) -> Self {
329        Self {
330            inner: Rc::new(SomniStructInner { name, fields }),
331        }
332    }
333
334    /// Returns the struct type's name.
335    pub fn name(&self) -> &str {
336        &self.inner.name
337    }
338
339    /// Returns the struct's fields, keyed by field name, in declaration order.
340    pub fn fields(&self) -> &IndexMap<Box<str>, TypedValue<T>> {
341        &self.inner.fields
342    }
343
344    /// Returns a mutable reference to the struct's fields.
345    pub fn fields_mut(&mut self) -> &mut IndexMap<Box<str>, TypedValue<T>> {
346        &mut Rc::make_mut(&mut self.inner).fields
347    }
348
349    /// Consumes the struct, returning its name and fields.
350    pub fn into_parts(self) -> (Box<str>, IndexMap<Box<str>, TypedValue<T>>) {
351        let inner = Rc::try_unwrap(self.inner).unwrap_or_else(|shared| (*shared).clone());
352        (inner.name, inner.fields)
353    }
354}
355
356impl<T: TypeSet> Clone for SomniStruct<T> {
357    fn clone(&self) -> Self {
358        Self {
359            inner: Rc::clone(&self.inner),
360        }
361    }
362}
363
364impl<T: TypeSet> std::fmt::Debug for SomniStruct<T> {
365    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
366        f.debug_struct("SomniStruct")
367            .field("name", &self.inner.name)
368            .field("fields", &self.inner.fields)
369            .finish()
370    }
371}
372
373impl<T: TypeSet> PartialEq for SomniStruct<T> {
374    fn eq(&self, other: &Self) -> bool {
375        // Structural equality: same struct name and equal fields. `IndexMap`'s
376        // `PartialEq` compares entries independent of order.
377        Rc::ptr_eq(&self.inner, &other.inner)
378            || (self.inner.name == other.inner.name && self.inner.fields == other.inner.fields)
379    }
380}
381
382/// A location that a reference points to: a root variable plus a path of field
383/// names to descend into. An empty path refers to the whole variable.
384///
385/// `root` is an opaque, context-internal variable address (the same encoding the
386/// evaluator uses for variable coordinates); only the owning [`ExprContext`] knows
387/// how to resolve it.
388///
389/// [`ExprContext`]: crate::ExprContext
390#[derive(Clone, Debug, PartialEq, Eq)]
391pub struct Place {
392    /// Opaque root variable address.
393    pub root: usize,
394    /// Field names to descend, from the root. Empty means the whole variable.
395    pub path: Box<[Box<str>]>,
396}
397
398/// A first-class reference value: the pointee type plus the place it points to.
399///
400/// The representation lives behind a single [`Box`], so `Reference` (and
401/// therefore [`TypedValue`], which embeds it by value) is only one pointer wide.
402/// The internals are reached through [`pointee`](Self::pointee),
403/// [`place`](Self::place) and [`into_place`](Self::into_place).
404#[derive(Clone, Debug, PartialEq, Eq)]
405pub struct Reference {
406    inner: Box<ReferenceInner>,
407}
408
409/// The heap-allocated payload of a [`Reference`].
410#[derive(Clone, Debug, PartialEq, Eq)]
411struct ReferenceInner {
412    pointee: RefPointee,
413    place: Place,
414}
415
416impl Reference {
417    /// Creates a reference to the given place with the given pointee kind.
418    pub fn new(pointee: RefPointee, place: Place) -> Self {
419        Self {
420            inner: Box::new(ReferenceInner { pointee, place }),
421        }
422    }
423
424    /// Returns the static kind of the referenced value.
425    pub fn pointee(&self) -> RefPointee {
426        self.inner.pointee
427    }
428
429    /// Returns the place this reference points to.
430    pub fn place(&self) -> &Place {
431        &self.inner.place
432    }
433
434    /// Consumes the reference, returning the place it points to.
435    pub fn into_place(self) -> Place {
436        self.inner.place
437    }
438}
439
440impl<T: TypeSet> PartialEq for TypedValue<T> {
441    fn eq(&self, other: &Self) -> bool {
442        match (self, other) {
443            (Self::MaybeSignedInt(lhs), Self::MaybeSignedInt(rhs) | Self::Int(rhs)) => lhs == rhs,
444            (Self::Int(lhs), Self::MaybeSignedInt(rhs) | Self::Int(rhs)) => lhs == rhs,
445            (Self::SignedInt(lhs), Self::SignedInt(rhs)) => lhs == rhs,
446            (Self::SignedInt(lhs), Self::MaybeSignedInt(rhs)) => {
447                T::to_signed(*rhs).map(|rhs| rhs == *lhs).unwrap_or(false)
448            }
449            (Self::MaybeSignedInt(lhs), Self::SignedInt(rhs)) => {
450                T::to_signed(*lhs).map(|lhs| lhs == *rhs).unwrap_or(false)
451            }
452            (Self::Float(lhs), Self::Float(rhs)) => lhs == rhs,
453            (Self::Bool(lhs), Self::Bool(rhs)) => lhs == rhs,
454            (Self::String(lhs), Self::String(rhs)) => lhs == rhs,
455            (Self::Iter(lhs), Self::Iter(rhs)) => lhs == rhs,
456            (Self::Struct(lhs), Self::Struct(rhs)) => lhs == rhs,
457            (Self::Ref(lhs), Self::Ref(rhs)) => lhs == rhs,
458            _ => core::mem::discriminant(self) == core::mem::discriminant(other),
459        }
460    }
461}
462
463impl<T: TypeSet> Clone for TypedValue<T> {
464    fn clone(&self) -> Self {
465        match self {
466            Self::Void => Self::Void,
467            Self::MaybeSignedInt(inner) => Self::MaybeSignedInt(*inner),
468            Self::Int(inner) => Self::Int(*inner),
469            Self::SignedInt(inner) => Self::SignedInt(*inner),
470            Self::Float(inner) => Self::Float(*inner),
471            Self::Bool(inner) => Self::Bool(*inner),
472            Self::String(inner) => Self::String(inner.clone()),
473            Self::Iter(inner) => Self::Iter(inner.clone()),
474            Self::Struct(inner) => Self::Struct(inner.clone()),
475            Self::Ref(inner) => Self::Ref(inner.clone()),
476        }
477    }
478}
479
480impl<T: TypeSet> TypedValue<T> {
481    /// Returns the Somni type of this value.
482    pub fn type_of(&self) -> Type {
483        match self {
484            TypedValue::Void => Type::Void,
485            TypedValue::Int(_) => Type::Int,
486            TypedValue::MaybeSignedInt(_) => Type::MaybeSignedInt,
487            TypedValue::SignedInt(_) => Type::SignedInt,
488            TypedValue::Float(_) => Type::Float,
489            TypedValue::Bool(_) => Type::Bool,
490            TypedValue::String(_) => Type::String,
491            TypedValue::Iter(_) => Type::Iter,
492            TypedValue::Struct(_) => Type::Struct,
493            TypedValue::Ref(r) => Type::Ref(r.pointee()),
494        }
495    }
496}
497
498/// Loads an owned Rust value from a TypedValue.
499pub trait LoadOwned<T: TypeSet = DefaultTypeSet> {
500    /// The type of the result.
501    type Output;
502
503    /// Loads an owned value from the given type context.
504    fn load_owned(_ctx: &T, typed: &TypedValue<T>) -> Option<Self::Output>;
505}
506
507/// Converts between a borrowed Rust value and a TypedValue.
508pub trait LoadStore<T: TypeSet = DefaultTypeSet> {
509    /// The type of the result.
510    type Output<'s>
511    where
512        T: 's;
513
514    /// Loads a borrowed value from the given type context.
515    fn load<'s>(_ctx: &'s T, typed: &'s TypedValue<T>) -> Option<Self::Output<'s>>;
516
517    /// Stores a Rust value into a TypedValue using the given type context.
518    fn store(&self, _ctx: &mut T) -> TypedValue<T>;
519}
520
521for_each! {
522    // Unsigned integers
523    ($type:ty) in [u32, u64, u128] => {
524        impl<T: TypeSet<Integer = Self>> LoadOwned<T> for $type {
525            type Output = Self;
526            fn load_owned(_ctx: &T, typed: &TypedValue<T>) -> Option<Self::Output> {
527                match typed {
528                    TypedValue::MaybeSignedInt(value) => Some(*value),
529                    TypedValue::Int(value) => Some(*value),
530                    _ => None,
531                }
532            }
533        }
534        impl<T: TypeSet<Integer = Self>> LoadStore<T> for $type {
535            type Output<'s> = Self;
536            fn load(ctx: &T, typed: &TypedValue<T>) -> Option<Self> {
537                <Self as LoadOwned<T>>::load_owned(ctx, typed)
538            }
539            fn store(&self, _ctx: &mut T) -> TypedValue<T> {
540                TypedValue::Int(*self)
541            }
542        }
543    };
544
545    // Signed integers
546    ($type:ty) in [i32, i64, i128] => {
547        impl<T: TypeSet<SignedInteger = Self>> LoadOwned<T> for $type {
548            type Output = Self;
549            fn load_owned(_ctx: &T, typed: &TypedValue<T>) -> Option<Self::Output> {
550                match typed {
551                    TypedValue::MaybeSignedInt(value) => T::to_signed(*value).ok(),
552                    TypedValue::SignedInt(value) => Some(*value),
553                    _ => None,
554                }
555            }
556        }
557        impl<T: TypeSet<SignedInteger = Self>> LoadStore<T> for $type {
558            type Output<'s> = Self;
559            fn load(ctx: &T, typed: &TypedValue<T>) -> Option<Self> {
560                <Self as LoadOwned<T>>::load_owned(ctx, typed)
561            }
562            fn store(&self, _ctx: &mut T) -> TypedValue<T> {
563                TypedValue::SignedInt(*self)
564            }
565        }
566    };
567
568    // Strings
569    ($type:ty) in [String, Box<str>] => {
570        impl<T: TypeSet> LoadOwned<T> for $type {
571            type Output = Self;
572            fn load_owned(ctx: &T, typed: &TypedValue<T>) -> Option<Self::Output> {
573                <&str as LoadStore<T>>::load(ctx, typed).map(Into::into)
574            }
575        }
576        impl<T: TypeSet> LoadStore<T> for $type {
577            type Output<'s> = Self;
578            fn load(ctx: &T, typed: &TypedValue<T>) -> Option<Self> {
579                <Self as LoadOwned<T>>::load_owned(ctx, typed)
580            }
581            fn store(&self, ctx: &mut T) -> TypedValue<T> {
582                TypedValue::String(ctx.store_string(self))
583            }
584        }
585    };
586
587    // Floats
588    ($type:ty) in [f32, f64] => {
589        impl<T: TypeSet<Float = Self>> LoadOwned<T> for $type {
590            type Output = Self;
591            fn load_owned(_ctx: &T, typed: &TypedValue<T>) -> Option<Self::Output> {
592                match typed {
593                    TypedValue::Float(value) => Some(*value),
594                    _ => None,
595                }
596            }
597        }
598        impl<T: TypeSet<Float = Self>> LoadStore<T> for $type {
599            type Output<'s> = Self;
600            fn load(ctx: &T, typed: &TypedValue<T>) -> Option<Self> {
601                <Self as LoadOwned<T>>::load_owned(ctx, typed)
602            }
603            fn store(&self, _ctx: &mut T) -> TypedValue<T> {
604                TypedValue::Float(*self)
605            }
606        }
607    };
608}
609
610// Somewhat special cases:
611
612impl<T: TypeSet> LoadOwned<T> for TypedValue<T> {
613    type Output = Self;
614    fn load_owned(_ctx: &T, typed: &TypedValue<T>) -> Option<Self> {
615        Some(typed.clone())
616    }
617}
618impl<T: TypeSet> LoadStore<T> for TypedValue<T> {
619    type Output<'s> = Self;
620    fn load(ctx: &T, typed: &TypedValue<T>) -> Option<Self> {
621        <Self as LoadOwned<T>>::load_owned(ctx, typed)
622    }
623    fn store(&self, _ctx: &mut T) -> TypedValue<T> {
624        self.clone()
625    }
626}
627
628impl<T: TypeSet> LoadOwned<T> for () {
629    type Output = Self;
630    fn load_owned(_ctx: &T, typed: &TypedValue<T>) -> Option<Self> {
631        if let TypedValue::Void = typed {
632            Some(())
633        } else {
634            None
635        }
636    }
637}
638impl<T: TypeSet> LoadStore<T> for () {
639    type Output<'s> = Self;
640    fn load(ctx: &T, typed: &TypedValue<T>) -> Option<Self> {
641        <Self as LoadOwned<T>>::load_owned(ctx, typed)
642    }
643    fn store(&self, _ctx: &mut T) -> TypedValue<T> {
644        TypedValue::Void
645    }
646}
647
648impl<T: TypeSet> LoadOwned<T> for bool {
649    type Output = Self;
650    fn load_owned(_ctx: &T, typed: &TypedValue<T>) -> Option<Self> {
651        if let TypedValue::Bool(value) = typed {
652            Some(*value)
653        } else {
654            None
655        }
656    }
657}
658impl<T: TypeSet> LoadStore<T> for bool {
659    type Output<'s> = Self;
660    fn load(ctx: &T, typed: &TypedValue<T>) -> Option<Self> {
661        <Self as LoadOwned<T>>::load_owned(ctx, typed)
662    }
663    fn store(&self, _ctx: &mut T) -> TypedValue<T> {
664        TypedValue::Bool(*self)
665    }
666}
667
668impl<T: TypeSet> LoadStore<T> for &str {
669    type Output<'s>
670        = &'s str
671    where
672        T: 's;
673
674    fn load<'s>(ctx: &'s T, typed: &'s TypedValue<T>) -> Option<Self::Output<'s>> {
675        if let TypedValue::String(index) = typed {
676            Some(ctx.load_string(index))
677        } else {
678            None
679        }
680    }
681    fn store(&self, ctx: &mut T) -> TypedValue<T> {
682        TypedValue::String(ctx.store_string(self))
683    }
684}
685
686// A struct value crosses the boundary as itself: its fields are already
687// `TypedValue`s, so no type context is needed to (un)wrap it.
688impl<T: TypeSet> LoadOwned<T> for SomniStruct<T> {
689    type Output = SomniStruct<T>;
690    fn load_owned(_ctx: &T, typed: &TypedValue<T>) -> Option<Self::Output> {
691        if let TypedValue::Struct(s) = typed {
692            Some(s.clone())
693        } else {
694            None
695        }
696    }
697}
698impl<T: TypeSet> LoadStore<T> for SomniStruct<T> {
699    type Output<'s> = SomniStruct<T>;
700    fn load(ctx: &T, typed: &TypedValue<T>) -> Option<Self> {
701        <Self as LoadOwned<T>>::load_owned(ctx, typed)
702    }
703    fn store(&self, _ctx: &mut T) -> TypedValue<T> {
704        TypedValue::Struct(self.clone())
705    }
706}