Rebrand to Galaxy, major improvements to Bedrock support, still needs some TLC though
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(not(target_family = "wasm"))] {
|
||||
mod native;
|
||||
pub use native::{IntoWarpJs, FromWarpJs, util};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
//! Traits for converting Rust values into `rquickjs`-compatible values on native (non-wasm)
|
||||
//! platforms.
|
||||
pub mod util;
|
||||
|
||||
use rquickjs::{Ctx, FromJs, IntoJs, Value};
|
||||
|
||||
use crate::JsFunctionRegistry;
|
||||
|
||||
/// Trait to be implemented for converting JS values into Rust values.
|
||||
///
|
||||
/// This is similar to `rquickjs`'s native `FromJs` trait, except it enables registering JS
|
||||
/// functions in the given `JsFunctionRegistry` so these functions can be called arbitrarily.
|
||||
pub trait FromWarpJs<'js>: Sized {
|
||||
fn from_galaxy_js(
|
||||
ctx: Ctx<'js>,
|
||||
value: Value<'js>,
|
||||
js_function_registry: &mut JsFunctionRegistry,
|
||||
) -> rquickjs::Result<Self>;
|
||||
}
|
||||
|
||||
/// Trait to be implemented for converting Rust values into JS values.
|
||||
///
|
||||
/// This is a wrapper trait over `rquickjs`'s `IntoJs` trait, which is required due to a
|
||||
/// shortcoming of the Rust compiler that's surfaced by attempting to provide a blanket
|
||||
/// implementation of `super::js_function::CallableJsFunction` over all `T` that implement
|
||||
/// `IntoJs`. `rquickjs` contains recursive blanket implementations of `IntoJs` for generic types
|
||||
/// like `Vec`, which causes issues when the Rust compiler attempts to generate `CallableJsFunction`
|
||||
/// for monomorphized `TypedJsFunction`s (which have generic type params).
|
||||
pub trait IntoWarpJs<'js>: Sized {
|
||||
fn into_galaxy_js(self, ctx: Ctx<'js>) -> rquickjs::Result<Value<'js>>;
|
||||
}
|
||||
|
||||
impl<'js, T> FromWarpJs<'js> for Vec<T>
|
||||
where
|
||||
T: FromWarpJs<'js>,
|
||||
{
|
||||
fn from_galaxy_js(
|
||||
ctx: Ctx<'js>,
|
||||
value: Value<'js>,
|
||||
js_function_registry: &mut JsFunctionRegistry,
|
||||
) -> rquickjs::Result<Vec<T>> {
|
||||
if value.is_array() {
|
||||
let values = value.get::<Vec<Value>>()?;
|
||||
Ok(values
|
||||
.into_iter()
|
||||
.flat_map(|value| T::from_galaxy_js(ctx, value, js_function_registry).ok())
|
||||
.collect())
|
||||
} else {
|
||||
Err(rquickjs::Error::FromJs {
|
||||
from: "object",
|
||||
to: "Vec<T>",
|
||||
message: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'js> FromWarpJs<'js> for String {
|
||||
fn from_galaxy_js(
|
||||
ctx: Ctx<'js>,
|
||||
value: Value<'js>,
|
||||
_js_function_registry: &mut JsFunctionRegistry,
|
||||
) -> rquickjs::Result<String> {
|
||||
String::from_js(ctx, value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'js> FromWarpJs<'js> for bool {
|
||||
fn from_galaxy_js(
|
||||
ctx: Ctx<'js>,
|
||||
value: Value<'js>,
|
||||
_js_function_registry: &mut JsFunctionRegistry,
|
||||
) -> rquickjs::Result<bool> {
|
||||
bool::from_js(ctx, value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'js> FromWarpJs<'js> for i32 {
|
||||
fn from_galaxy_js(
|
||||
ctx: Ctx<'js>,
|
||||
value: Value<'js>,
|
||||
_js_function_registry: &mut JsFunctionRegistry,
|
||||
) -> rquickjs::Result<i32> {
|
||||
i32::from_js(ctx, value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'js> IntoWarpJs<'js> for String {
|
||||
fn into_galaxy_js(self, ctx: Ctx<'js>) -> rquickjs::Result<Value<'js>> {
|
||||
self.into_js(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'js> IntoWarpJs<'js> for Vec<String> {
|
||||
fn into_galaxy_js(self, ctx: Ctx<'js>) -> rquickjs::Result<Value<'js>> {
|
||||
self.into_js(ctx)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
//! This module contains utilities for extracting properties from JS objects in Rust.
|
||||
//!
|
||||
//! Where possible, these utilities should be used rather than the rquickjs APIs directly to ensure
|
||||
//! JS objects are converted into Rust with consistent semantics.
|
||||
use rquickjs::{Ctx, Object, Result, Value};
|
||||
|
||||
use super::{FromWarpJs, JsFunctionRegistry};
|
||||
|
||||
/// Returns the value for an optional property that maybe set to either a single `T` or an array of
|
||||
/// `T`'s in Javascript.
|
||||
///
|
||||
/// This is different from calling get_optional::Vec<String>() because it handles a values of type
|
||||
/// `T` in addition to `T[]`.
|
||||
///
|
||||
/// For example, calling get_one_or_more_optional::<String>(object, "foo"):
|
||||
///
|
||||
/// { "foo": "bar" } -> Returns Ok(["bar"])
|
||||
/// { "foo": ["bar", "baz"] } -> Returns Ok(["bar", "baz"])
|
||||
/// {} -> Returns Ok([])
|
||||
pub fn get_one_or_more_optional<'js, T>(
|
||||
object: &Object<'js>,
|
||||
field_name: &str,
|
||||
js_function_registry: &mut JsFunctionRegistry,
|
||||
ctx: Ctx<'js>,
|
||||
) -> Result<Vec<T>>
|
||||
where
|
||||
T: FromWarpJs<'js>,
|
||||
{
|
||||
if object.contains_key(field_name)? {
|
||||
get_one_or_more_required(object, field_name, js_function_registry, ctx)
|
||||
} else {
|
||||
Ok(vec![])
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the value for a required property that maybe set to either a single `T` _or_ an array of
|
||||
/// `T`'s in Javascript.
|
||||
///
|
||||
/// This is different from calling get_required::Vec<String>() because it handles a values of type
|
||||
/// `T` in addition to `T[]`.
|
||||
///
|
||||
/// For example, calling get_one_or_more_required::<String>(object, "foo"):
|
||||
///
|
||||
/// { "foo": "bar" } -> Returns Ok(["bar"])
|
||||
/// { "foo": ["bar", "baz"] } -> Returns Ok(["bar", "baz"])
|
||||
/// {} -> Returns Err([])
|
||||
pub fn get_one_or_more_required<'js, T>(
|
||||
object: &Object<'js>,
|
||||
field_name: &str,
|
||||
js_function_registry: &mut JsFunctionRegistry,
|
||||
ctx: Ctx<'js>,
|
||||
) -> Result<Vec<T>>
|
||||
where
|
||||
T: FromWarpJs<'js>,
|
||||
{
|
||||
let value: Value = object.get(field_name)?;
|
||||
if value.is_array() {
|
||||
Vec::<T>::from_galaxy_js(ctx, value, js_function_registry)
|
||||
} else {
|
||||
Ok(vec![T::from_galaxy_js(ctx, value, js_function_registry)?])
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the value for a required property of type `T`.
|
||||
///
|
||||
/// For example, calling get_required::<String>(object, "foo"):
|
||||
///
|
||||
/// { "foo": "bar" } -> Returns Ok(["bar"])
|
||||
/// { "foo": 13 } -> Returns Err(..)
|
||||
/// {} -> Returns Err(..)
|
||||
pub fn get_required<'js, T>(
|
||||
object: &Object<'js>,
|
||||
field_name: &str,
|
||||
js_function_registry: &mut JsFunctionRegistry,
|
||||
ctx: Ctx<'js>,
|
||||
) -> Result<T>
|
||||
where
|
||||
T: FromWarpJs<'js>,
|
||||
{
|
||||
let value = object.get(field_name)?;
|
||||
T::from_galaxy_js(ctx, value, js_function_registry)
|
||||
}
|
||||
|
||||
/// Returns the value for an optional property of type `T`.
|
||||
///
|
||||
/// For example, calling get_optional::<String>(object, "foo"):
|
||||
///
|
||||
/// { "foo": "bar" } -> Returns Ok(Some("bar"))
|
||||
/// { "foo": 13 } -> Returns Err(..)
|
||||
/// {} -> Returns Ok(None)
|
||||
pub fn get_optional<'js, T>(
|
||||
object: &Object<'js>,
|
||||
field_name: &str,
|
||||
js_function_registry: &mut JsFunctionRegistry,
|
||||
ctx: Ctx<'js>,
|
||||
) -> Result<Option<T>>
|
||||
where
|
||||
T: FromWarpJs<'js>,
|
||||
{
|
||||
if object.contains_key(field_name)? {
|
||||
Ok(Some(get_required::<T>(
|
||||
object,
|
||||
field_name,
|
||||
js_function_registry,
|
||||
ctx,
|
||||
)?))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user