-
Notifications
You must be signed in to change notification settings - Fork 25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Generic abstract type support #93
Comments
Generally, I like the approach, thank you for the thorough write-up with examples and a detailed explanation of the use-case.
Is the idea that someone would construct an external value explicitly and pass it to the context in order to use this (see example below)? Automatically serializable types would continue to operate as they do today? context.add_variable_from_value("user", Value::ExternalValue(&user)) // or something It seems like this problem could also be solved by the trait-based design in #76, do you agree |
After some experimenting with vendored version of the library. ExternalType looks like: #[derive(Debug, Clone)]
pub struct ExternalValue(Arc<dyn ExternalType>);
impl ExternalValue {
pub fn downcast<T>(&self) -> Option<Arc<T>>
where
T: 'static + Send + Sync,
{
Arc::downcast::<T>(self.0.clone()).ok()
}
} That's blocked by rust-lang/rust#119335 for now. A more complicated version can be created that partially copies |
Ideally, if the type implements
Yes and no. This issue basically attacks the same problem from a different angle. I personally prefer If |
There's no way of passing partially visible types through cel expressions.
This means that any functions that use
This
require that value to beFrom<Value>
for any type they operate on. This is doable in a lot of cases, but negatively impacts performance. In some cases it's impossible because internal API guarantees can't be (safely) upheld.Cel spec provides abstract types for this kind of use.
Use Case
I have some
User
type on Rust size, which has a bunch ofOption
,MaybeUninit
, etc. values that get populated through use (cache, temporary state, etc.).I want to provide a
get_role
function which performs expensive computation. The Rust implementation can make use of private cached values stored inUser
. Cel functions are forced to reconstructUser
partially from data that's visible to end-user, and then recompute all potential intermediate and final information to provide the result once.Solution
TryIntoValue
provides a type projection from internal types to Cel types. This issue arises when the library discards the source type information in favor of operating with Cel types (i.e.Value
).The solution is to retain source type in form of
, so that those values can be passed around and accessed from
Handler<T>
. This is assumingTryIntoValue: Any + Send + Sync
for simplicity, but another trait with stricter requirements should be introduced and auto-implemented for allT: TryIntoValue + Any + Send + Sync
.FromContext::from_context
needs to compare valueTypeId
for thoseValue
s and error withUnsupportedTargetType
orNotSupportedAsMethod
appropriately.By providing:
users will be able to do:
Issues
Value::Map
and assumes they can construct an identical value in place of internally-typed one, which fails. This suggests there needs to be a new error type returned whenValue::*
is provided in place ofValue::External
.Examples in the wild
mlua
-UserData
void*
, in cel this would be an abstract typeThe text was updated successfully, but these errors were encountered: