1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
use super::{LVar, Val}; use std::fmt::Debug; use std::rc::Rc; /// Helper for converting into [`Val<T>`](crate::value::Val). /// /// In order to be able to mix [resolved values](crate::value::Val) and [logical /// variables](crate::value::LVar) in the same [state](crate::state), they need /// to be contained in the shared [`Val`](crate::value::Val) enum. This trait /// provides a standard way to convert various types of values into this /// container enum without manual wrapping. /// /// # TLDR: If you see a function that takes `IntoVal<T>` /// ``` /// # use canrun::{Val, IntoVal}; /// # use std::fmt::Debug; /// fn foo<T: Debug, TV: IntoVal<T>>(bar: TV) -> Val<T> { /// bar.into_val() /// } /// ``` /// That means it can take any of these types and will take care of converting /// them into a `Val<T>` for you: /// ``` /// # use canrun::{Val, var, IntoVal}; /// # use std::fmt::Debug; /// # fn foo<T: Debug, TV: IntoVal<T>>(bar: TV) -> Val<T> { /// # bar.into_val() /// # } /// let a: Val<i32> = foo(1); // a plain value of type `T` /// let b: Val<i32> = foo(var()); // an `LVar<T>` /// let c: Val<i32> = foo(a); // a `Val<T>` /// ``` pub trait IntoVal<T: Debug> { /// Convert various `T` related values into a [`Val<T>`](crate::value::Val). /// /// # Example: /// ``` /// use canrun::{var, IntoVal, Val, LVar}; /// /// let x: LVar<i32> = var(); /// let x_val: Val<i32> = x.into_val(); /// /// let y: i32 = 1; /// let y_val: Val<i32> = y.into_val(); /// ``` fn into_val(self) -> Val<T>; } impl<T: Debug> IntoVal<T> for T { fn into_val(self) -> Val<T> { Val::Resolved(Rc::new(self)) } } impl<T: Debug> IntoVal<T> for Val<T> { fn into_val(self) -> Val<T> { self } } impl<T: Debug> IntoVal<T> for &Val<T> { fn into_val(self) -> Val<T> { self.clone() } } impl<T: Clone + Debug> IntoVal<T> for &T { fn into_val(self) -> Val<T> { Val::Resolved(Rc::new(self.clone())) } } impl<T: Debug> IntoVal<T> for LVar<T> { fn into_val(self) -> Val<T> { Val::Var(self) } } impl<T: Debug> IntoVal<T> for &LVar<T> { fn into_val(self) -> Val<T> { Val::Var(*self) } }