[oden] Grab my incomplete QuickJS wrapper

This commit is contained in:
John Doty 2023-06-17 20:44:09 -07:00
parent aa70df41a3
commit 898b1fe129
114 changed files with 244181 additions and 0 deletions

View file

@ -0,0 +1,107 @@
use crate::{ContextRef, Error, Result, ValueRef};
use std::num::TryFromIntError;
pub trait TryFromValue: Sized {
fn try_from_value<'r>(value: &ValueRef<'r>, ctx: &ContextRef<'r>) -> Result<'r, Self>;
}
impl TryFromValue for u8 {
#[inline]
fn try_from_value<'r>(value: &ValueRef<'r>, ctx: &ContextRef<'r>) -> Result<'r, Self> {
let v = value.to_u32(&ctx)?;
v.try_into()
.map_err(|e: TryFromIntError| Error::ConversionError(e.to_string()))
}
}
impl TryFromValue for u16 {
#[inline]
fn try_from_value<'r>(value: &ValueRef<'r>, ctx: &ContextRef<'r>) -> Result<'r, Self> {
let v = value.to_u32(&ctx)?;
v.try_into()
.map_err(|e: TryFromIntError| Error::ConversionError(e.to_string()))
}
}
impl TryFromValue for u32 {
#[inline]
fn try_from_value<'r>(value: &ValueRef<'r>, ctx: &ContextRef<'r>) -> Result<'r, Self> {
value.to_u32(&ctx)
}
}
// impl<'c,'d> TryFrom<&'c ValueRef<'d>> for u64 {
// #[inline]
// fn try_from_value<'r>(value: &ValueRef<'r>, ctx:&ContextRef<'r>) -> Result<'r, Self> {
// value.to_u64()
// }
// }
impl TryFromValue for i8 {
#[inline]
fn try_from_value<'r>(value: &ValueRef<'r>, ctx: &ContextRef<'r>) -> Result<'r, Self> {
let v = value.to_i32(&ctx)?;
v.try_into()
.map_err(|e: TryFromIntError| Error::ConversionError(e.to_string()))
}
}
impl TryFromValue for i16 {
#[inline]
fn try_from_value<'r>(value: &ValueRef<'r>, ctx: &ContextRef<'r>) -> Result<'r, Self> {
let v = value.to_i32(&ctx)?;
v.try_into()
.map_err(|e: TryFromIntError| Error::ConversionError(e.to_string()))
}
}
impl TryFromValue for i32 {
#[inline]
fn try_from_value<'r>(value: &ValueRef<'r>, ctx: &ContextRef<'r>) -> Result<'r, Self> {
value.to_i32(&ctx)
}
}
impl TryFromValue for i64 {
#[inline]
fn try_from_value<'r>(value: &ValueRef<'r>, ctx: &ContextRef<'r>) -> Result<'r, Self> {
value.to_i64(&ctx)
}
}
impl TryFromValue for f32 {
#[inline]
fn try_from_value<'r>(value: &ValueRef<'r>, ctx: &ContextRef<'r>) -> Result<'r, Self> {
let v = value.to_float64(&ctx)?;
Ok(v as f32)
}
}
impl TryFromValue for f64 {
#[inline]
fn try_from_value<'r>(value: &ValueRef<'r>, ctx: &ContextRef<'r>) -> Result<'r, Self> {
value.to_float64(&ctx)
}
}
impl TryFromValue for bool {
#[inline]
fn try_from_value<'r>(value: &ValueRef<'r>, _ctx: &ContextRef<'r>) -> Result<'r, Self> {
value.to_bool()
}
}
impl TryFromValue for String {
#[inline]
fn try_from_value<'r>(value: &ValueRef<'r>, ctx: &ContextRef<'r>) -> Result<'r, Self> {
value.to_string(&ctx)
}
}
// impl<'c, T: Class> TryFrom<&'c ValueRef<'_>> for T {
//
// #[inline]
// fn try_from_value<'r>(value: &ValueRef<'r>, ctx:&ContextRef<'r>) -> Result<'r, Self> {
// T::from_value(value)
// }
// }

View file

@ -0,0 +1,191 @@
use super::{TryFromValue, TryIntoValue};
use crate::{ContextRef, Error, ValueRef, ValueResult};
use std::marker::PhantomData;
pub trait IntoRustFunctionResult<'r> {
fn into_res(self, ctx: &ContextRef<'r>) -> ValueResult<'r>;
}
impl<'r, T: TryIntoValue<'r>> IntoRustFunctionResult<'r> for T {
fn into_res(self, ctx: &ContextRef<'r>) -> ValueResult<'r> {
self.try_into_value(ctx)
}
}
impl<'r, T: TryIntoValue<'r>, E: std::fmt::Display> IntoRustFunctionResult<'r>
for core::result::Result<T, E>
{
fn into_res(self, ctx: &ContextRef<'r>) -> ValueResult<'r> {
match self {
Ok(v) => v.try_into_value(ctx),
Err(e) => Err(Error::RustFunctionError(e.to_string())),
}
}
}
pub trait RustFunction<'r, F> {
fn argument_count() -> usize;
fn call(&self, context: &ContextRef<'r>, args: &[&ValueRef<'r>]) -> ValueResult<'r>;
}
impl<'r, R, F> RustFunction<'r, PhantomData<(&R, &F)>> for F
where
R: IntoRustFunctionResult<'r>,
F: Fn(&ContextRef<'r>) -> R + Sized,
{
fn argument_count() -> usize {
0
}
fn call(&self, context: &ContextRef<'r>, args: &[&ValueRef<'r>]) -> ValueResult<'r> {
if args.len() != 0 {
return Err(Error::ArgumentCountMismatch {
expected: Self::argument_count(),
received: args.len(),
});
}
let res = self(context);
res.into_res(context)
}
}
impl<'r, R, A, F> RustFunction<'r, PhantomData<(&R, &A, &F)>> for F
where
R: IntoRustFunctionResult<'r>,
A: TryFromValue,
F: Fn(&ContextRef<'r>, A) -> R + Sized,
{
fn argument_count() -> usize {
1
}
fn call(&self, context: &ContextRef<'r>, args: &[&ValueRef<'r>]) -> ValueResult<'r> {
if args.len() != Self::argument_count() {
return Err(Error::ArgumentCountMismatch {
expected: Self::argument_count(),
received: args.len(),
});
}
let va = A::try_from_value(args[0], &context)?;
let res = self(context, va);
res.into_res(context)
}
}
impl<'r, R, A, B, F> RustFunction<'r, PhantomData<(&R, &A, &B, &F)>> for F
where
R: IntoRustFunctionResult<'r>,
A: TryFromValue,
B: TryFromValue,
F: Fn(&ContextRef<'r>, A, B) -> R + Sized,
{
fn argument_count() -> usize {
2
}
fn call(&self, context: &ContextRef<'r>, args: &[&ValueRef<'r>]) -> ValueResult<'r> {
if args.len() != Self::argument_count() {
return Err(Error::ArgumentCountMismatch {
expected: Self::argument_count(),
received: args.len(),
});
}
let va = A::try_from_value(args[0], &context)?;
let vb = B::try_from_value(args[1], &context)?;
let res = self(context, va, vb);
res.into_res(context)
}
}
impl<'r, R, A, B, C, F> RustFunction<'r, PhantomData<(&R, &A, &B, &C, &F)>> for F
where
R: IntoRustFunctionResult<'r>,
A: TryFromValue,
B: TryFromValue,
C: TryFromValue,
F: Fn(&ContextRef<'r>, A, B, C) -> R + Sized,
{
fn argument_count() -> usize {
3
}
fn call(&self, context: &ContextRef<'r>, args: &[&ValueRef<'r>]) -> ValueResult<'r> {
if args.len() != Self::argument_count() {
return Err(Error::ArgumentCountMismatch {
expected: Self::argument_count(),
received: args.len(),
});
}
let va = A::try_from_value(args[0], &context)?;
let vb = B::try_from_value(args[1], &context)?;
let vc = C::try_from_value(args[2], &context)?;
let res = self(context, va, vb, vc);
res.into_res(context)
}
}
impl<'r, R, A, B, C, D, F> RustFunction<'r, PhantomData<(&R, &A, &B, &C, &D, &F)>> for F
where
R: IntoRustFunctionResult<'r>,
A: TryFromValue,
B: TryFromValue,
C: TryFromValue,
D: TryFromValue,
F: Fn(&ContextRef<'r>, A, B, C, D) -> R + Sized,
{
fn argument_count() -> usize {
4
}
fn call(&self, context: &ContextRef<'r>, args: &[&ValueRef<'r>]) -> ValueResult<'r> {
if args.len() != Self::argument_count() {
return Err(Error::ArgumentCountMismatch {
expected: Self::argument_count(),
received: args.len(),
});
}
let va = A::try_from_value(args[0], &context)?;
let vb = B::try_from_value(args[1], &context)?;
let vc = C::try_from_value(args[2], &context)?;
let vd = D::try_from_value(args[3], &context)?;
let res = self(context, va, vb, vc, vd);
res.into_res(context)
}
}
impl<'r, R, A, B, C, D, E, F> RustFunction<'r, PhantomData<(&R, &A, &B, &C, &D, &E, &F)>> for F
where
R: IntoRustFunctionResult<'r>,
A: TryFromValue,
B: TryFromValue,
C: TryFromValue,
D: TryFromValue,
E: TryFromValue,
F: Fn(&ContextRef<'r>, A, B, C, D, E) -> R + Sized,
{
fn argument_count() -> usize {
5
}
fn call(&self, context: &ContextRef<'r>, args: &[&ValueRef<'r>]) -> ValueResult<'r> {
if args.len() != Self::argument_count() {
return Err(Error::ArgumentCountMismatch {
expected: Self::argument_count(),
received: args.len(),
});
}
let va = A::try_from_value(args[0], &context)?;
let vb = B::try_from_value(args[1], &context)?;
let vc = C::try_from_value(args[2], &context)?;
let vd = D::try_from_value(args[3], &context)?;
let ve = E::try_from_value(args[4], &context)?;
let res = self(context, va, vb, vc, vd, ve);
res.into_res(context)
}
}

View file

@ -0,0 +1,129 @@
use crate::{Class, ContextRef, Error, Value, ValueRef, ValueResult};
pub trait TryIntoValue<'r> {
fn try_into_value(self, ctx: &ContextRef<'r>) -> ValueResult<'r>;
}
impl<'r> TryIntoValue<'r> for u8 {
#[inline]
fn try_into_value(self, ctx: &ContextRef<'r>) -> ValueResult<'r> {
ctx.new_u64(self)
}
}
impl<'r> TryIntoValue<'r> for u16 {
#[inline]
fn try_into_value(self, ctx: &ContextRef<'r>) -> ValueResult<'r> {
ctx.new_u64(self)
}
}
impl<'r> TryIntoValue<'r> for u32 {
#[inline]
fn try_into_value(self, ctx: &ContextRef<'r>) -> ValueResult<'r> {
ctx.new_u64(self)
}
}
impl<'r> TryIntoValue<'r> for u64 {
#[inline]
fn try_into_value(self, ctx: &ContextRef<'r>) -> ValueResult<'r> {
ctx.new_u64(self)
}
}
impl<'r> TryIntoValue<'r> for i8 {
#[inline]
fn try_into_value(self, ctx: &ContextRef<'r>) -> ValueResult<'r> {
ctx.new_i32(self)
}
}
impl<'r> TryIntoValue<'r> for i16 {
#[inline]
fn try_into_value(self, ctx: &ContextRef<'r>) -> ValueResult<'r> {
ctx.new_i32(self)
}
}
impl<'r> TryIntoValue<'r> for i32 {
#[inline]
fn try_into_value(self, ctx: &ContextRef<'r>) -> ValueResult<'r> {
ctx.new_i32(self)
}
}
impl<'r> TryIntoValue<'r> for i64 {
#[inline]
fn try_into_value(self, ctx: &ContextRef<'r>) -> ValueResult<'r> {
ctx.new_i64(self)
}
}
impl<'r> TryIntoValue<'r> for f32 {
#[inline]
fn try_into_value(self, ctx: &ContextRef<'r>) -> ValueResult<'r> {
ctx.new_f64(self)
}
}
impl<'r> TryIntoValue<'r> for f64 {
#[inline]
fn try_into_value(self, ctx: &ContextRef<'r>) -> ValueResult<'r> {
ctx.new_f64(self)
}
}
impl<'r> TryIntoValue<'r> for bool {
#[inline]
fn try_into_value(self, ctx: &ContextRef<'r>) -> ValueResult<'r> {
ctx.new_bool(self)
}
}
impl<'r> TryIntoValue<'r> for &str {
#[inline]
fn try_into_value(self, ctx: &ContextRef<'r>) -> ValueResult<'r> {
ctx.new_string(self)
}
}
impl<'r> TryIntoValue<'r> for &ValueRef<'r> {
#[inline]
fn try_into_value(self, ctx: &ContextRef<'r>) -> ValueResult<'r> {
Ok(self.dup(ctx))
}
}
impl<'r> TryIntoValue<'r> for Value<'r> {
#[inline]
fn try_into_value(self, ctx: &ContextRef<'r>) -> ValueResult<'r> {
Ok(self.dup(ctx))
}
}
impl<'r> TryIntoValue<'r> for Error<'r> {
#[inline]
fn try_into_value(self, ctx: &ContextRef<'r>) -> ValueResult<'r> {
match self {
Error::TooManyClasses => Err(Error::TooManyClasses),
Error::WrongClass(c) => Err(Error::WrongClass(c)),
Error::UnexpectedNul => Err(Error::UnexpectedNul),
Error::DifferentRuntime => Err(Error::DifferentRuntime),
Error::InvalidType { expected, found } => Err(Error::InvalidType { expected, found }),
Error::ArgumentCountMismatch { expected, received } => {
Err(Error::ArgumentCountMismatch { expected, received })
}
Error::ConversionError(e) => Err(Error::ConversionError(e)),
Error::RustFunctionError(e) => Err(Error::RustFunctionError(e)),
Error::Exception(v) => Err(Error::Exception(v.dup(ctx))),
}
}
}
impl<'r, T: Class> TryIntoValue<'r> for T {
#[inline]
fn try_into_value(self, ctx: &ContextRef<'r>) -> ValueResult<'r> {
self.into_value(ctx)
}
}

View file

@ -0,0 +1,8 @@
mod into;
pub use into::*;
mod from;
pub use from::*;
mod function;
pub use function::*;