-
Notifications
You must be signed in to change notification settings - Fork 30
Description
Firstly, thanks for this amazing library, I'm using it in my own JS engine Yavashark.
I would propose an API where temporal_rs code can directly get properties from an JS object.
In my opinion, this makes sense, since there are many structs that essentially are an 1-to-1 mapping from a JS object to a struct in Rust.
In some cases, these mappings require validation (e.g PartialTime, CalendarFields), which with the API can then be moved into the temporal_rs implementation.
Additionally, it would also reduce the amount of binding code between the JS Engine and temporal_rs.
The API might look something like this:
ForeignObject trait
pub trait ForeignObject {
type Error: From<&'static str>;
type Context;
/// checks if the value is a string (e.g for things like timezone which can be a string or an object with a `timeZone` property)
fn is_string(&self, context: &mut Self::Context) -> Result<bool, Self::Error>;
/// converts the value to a string, errors if not a string
fn as_string(&self, context: &mut Self::Context) -> Result<String, Self::Error>;
/// gets a property by key, returns None if the property does not exist
fn get_number(&self, key: &str, context: &mut Self::Context) -> Result<Option<f64>, Self::Error>;
/// gets a property by key, returns None if the property does not exist
fn get_string(&self, key: &str, context: &mut Self::Context) -> Result<Option<String>, Self::Error>;
/// gets a property by key, returns None if the property does not exist
fn get_bool(&self, key: &str, context: &mut Self::Context) -> Result<Option<bool>, Self::Error>;
/// checks if the object has a property by key
fn has_key(&self, key: &str, context: &mut Self::Context) -> Result<bool, Self::Error>;
/// gets a property by key, returns None if the property does not exist (can be optimized by the implementor)
fn get_tiny_str<const LEN: usize>(
&self,
key: &str,
context: &mut Self::Context,
) -> Result<Option<TinyAsciiStr<LEN>>, Self::Error> {
match self.get_string(key, context)? {
Some(s) => {
let tiny_str = TinyAsciiStr::<LEN>::from_str(&s)
.map_err(|_| "String too long or contains non-ascii characters")?;
Ok(Some(tiny_str))
}
None => Ok(None),
}
}
/// gets a property by key, returns None if the property does not exist
fn get_u8(&self, key: &str, context: &mut Self::Context) -> Result<Option<u8>, Self::Error> {
match self.get_number(key, context)? {
Some(n) if n >= 0.0 && n <= u8::MAX as f64 && n.fract() == 0.0 => Ok(Some(n as u8)),
Some(_) => Err("Number out of range for u8".into()),
None => Ok(None),
}
}
/// gets a property by key, returns None if the property does not exist
fn get_u16(&self, key: &str, context: &mut Self::Context) -> Result<Option<u16>, Self::Error> {
match self.get_number(key, context)? {
Some(n) if n >= 0.0 && n <= u16::MAX as f64 && n.fract() == 0.0 => Ok(Some(n as u16)),
Some(_) => Err("Number out of range for u16".into()),
None => Ok(None),
}
}
/// gets a property by key, returns None if the property does not exist
fn get_i32(&self, key: &str, context: &mut Self::Context) -> Result<Option<i32>, Self::Error> {
match self.get_number(key, context)? {
Some(n) if n >= i32::MIN as f64 && n <= i32::MAX as f64 && n.fract() == 0.0 => Ok(Some(n as i32)),
Some(_) => Err("Number out of range for i32".into()),
None => Ok(None),
}
}
//... more methods for different number types as needed
}I think this can also be used in the C API (so with v8), however it requires some more binding glue between Rust and C
Is this something that is interesting to the temporal_rs maintainers? I am happy to discuss, also on the discord.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status