Trait starlark::values::ComplexValue [−][src]
pub trait ComplexValue<'v>: StarlarkValue<'v> + Trace<'v> {
type Frozen: SimpleValue;
fn freeze(self, freezer: &Freezer) -> Result<Self::Frozen>;
}
Expand description
A trait for values which are more complex - because they are either mutable, or contain references to other values.
For values that contain nested Value
types (mutable or not) there are a bunch of helpers
and macros.
Types containing Value
A Starlark type containing values will need to exist in two states: one containing Value
and one containing FrozenValue
. To deal with that, if we are defining the type
containing a single value, let’s call it One
, we’d define OneGen
(for the general version), and then have the starlark_complex_value!
macro
generate One
and FrozenOne
aliases.
use starlark::values::{AnyLifetime, ComplexValue, Coerce, Freezer, FrozenValue, SimpleValue, StarlarkValue, Value, ValueLike, Trace, Tracer};
use starlark::{starlark_complex_value, starlark_type};
#[derive(Debug, Trace, Coerce)]
#[repr(C)]
struct OneGen<V>(V);
starlark_complex_value!(One);
impl<'v, V: ValueLike<'v>> StarlarkValue<'v> for OneGen<V>
where Self: AnyLifetime<'v>
{
starlark_type!("one");
// To implement methods which are work for both `One` and `FrozenOne`,
// use the `ValueLike` trait.
}
impl<'v> ComplexValue<'v> for One<'v> {
type Frozen = FrozenOne;
fn freeze(self, freezer: &Freezer) -> anyhow::Result<Self::Frozen> {
Ok(OneGen(self.0.freeze(freezer)?))
}
}
The starlark_complex_value!
requires that the type have an instance for Coerce
,
then the macro defines two type aliases.
type One<'v> = OneGen<Value<'v>>;
type FrozenOne = OneGen<FrozenValue>;
To make these aliases public (or public to the crate) pass a visibility
to the macro, e.g. starlark_complex_value!(pub One)
.
The macro also defines instances of AnyLifetime
for both,
AllocValue
for both,
AllocFrozenValue
for the frozen one,
SimpleValue
for the frozen one and
FromValue
for the non-frozen one.
It also defines the methods:
impl<'v> One<'v> {
// Obtain a reference to `One` from a `Value`, regardless
// of whether the underlying `Value` is a `One` or `FrozenOne`.
pub fn from_value(x: Value<'v>) -> Option<ARef<'v, Self>> {
...
}
}
Different types
If the types are different between the frozen and non-frozen values you can define your own
type specialisations as type One<'v> = OneGen<Value<'v>>
and type FrozenOne = OneGen<String>
and use starlark_complex_values!
which will provide similar facilities to starlark_complex_value!
.
Other types
The macro starlark_complex_value!
is applicable when there is a single base type,
FooGen<V>
, with specialisations FooGen<Value<'v>>
and FooGen<FrozenValue>
.
If you have a type where the difference between frozen and non-frozen does not follow this
pattern then you will have to write instances of the traits you need manually.
Examples of cases where the macro doesn’t work include: