Skip to main content

somni_expr/
value.rs

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