Skip to content

Commit d6f9b02

Browse files
authored
Merge pull request #40 from golemcloud/typed-arrays
Represent list<u8> as UInt8Array
2 parents 6069bea + 229f3bc commit d6f9b02

10 files changed

Lines changed: 89 additions & 35 deletions

File tree

crates/wasm-rquickjs/skeleton/src/internal.rs

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -549,36 +549,3 @@ fn dump_cannot_find_method(
549549

550550
panic_message
551551
}
552-
553-
// Wrapper type that forces the js type to be a bigint instead of the default number which can loose some bits due to
554-
pub struct BigIntWrapper<T>(pub T);
555-
556-
impl<'js> IntoJs<'js> for BigIntWrapper<u64> {
557-
fn into_js(self, ctx: &Ctx<'js>) -> rquickjs::Result<Value<'js>> {
558-
let bigint = rquickjs::BigInt::from_u64(ctx.clone(), self.0)?;
559-
Ok(Value::from_big_int(bigint))
560-
}
561-
}
562-
563-
impl<'js> IntoJs<'js> for BigIntWrapper<i64> {
564-
fn into_js(self, ctx: &Ctx<'js>) -> rquickjs::Result<Value<'js>> {
565-
let bigint = rquickjs::BigInt::from_i64(ctx.clone(), self.0)?;
566-
Ok(Value::from_big_int(bigint))
567-
}
568-
}
569-
570-
impl<'js> FromJs<'js> for BigIntWrapper<u64> {
571-
fn from_js(ctx: &Ctx<'js>, value: Value<'js>) -> rquickjs::Result<Self> {
572-
let bigint = rquickjs::BigInt::from_js(ctx, value)?;
573-
let i64_value = bigint.to_i64()?;
574-
Ok(BigIntWrapper(i64_value as u64))
575-
}
576-
}
577-
578-
impl<'js> FromJs<'js> for BigIntWrapper<i64> {
579-
fn from_js(ctx: &Ctx<'js>, value: Value<'js>) -> rquickjs::Result<Self> {
580-
let bigint = rquickjs::BigInt::from_js(ctx, value)?;
581-
let i64_value = bigint.to_i64()?;
582-
Ok(BigIntWrapper(i64_value))
583-
}
584-
}

crates/wasm-rquickjs/skeleton/src/wrappers.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,57 @@ impl<'js, Ok: FromJs<'js>, Err: FromJs<'js>> FromJs<'js> for JsResult<Ok, Err> {
116116
}
117117
}
118118
}
119+
120+
// Wrapper type that forces the js type to be a bigint instead of the default number which can loose some bits due to
121+
pub struct BigIntWrapper<T>(pub T);
122+
123+
impl<'js> IntoJs<'js> for BigIntWrapper<u64> {
124+
fn into_js(self, ctx: &Ctx<'js>) -> rquickjs::Result<Value<'js>> {
125+
let bigint = rquickjs::BigInt::from_u64(ctx.clone(), self.0)?;
126+
Ok(Value::from_big_int(bigint))
127+
}
128+
}
129+
130+
impl<'js> IntoJs<'js> for BigIntWrapper<i64> {
131+
fn into_js(self, ctx: &Ctx<'js>) -> rquickjs::Result<Value<'js>> {
132+
let bigint = rquickjs::BigInt::from_i64(ctx.clone(), self.0)?;
133+
Ok(Value::from_big_int(bigint))
134+
}
135+
}
136+
137+
impl<'js> FromJs<'js> for BigIntWrapper<u64> {
138+
fn from_js(ctx: &Ctx<'js>, value: Value<'js>) -> rquickjs::Result<Self> {
139+
let bigint = rquickjs::BigInt::from_js(ctx, value)?;
140+
let i64_value = bigint.to_i64()?;
141+
Ok(BigIntWrapper(i64_value as u64))
142+
}
143+
}
144+
145+
impl<'js> FromJs<'js> for BigIntWrapper<i64> {
146+
fn from_js(ctx: &Ctx<'js>, value: Value<'js>) -> rquickjs::Result<Self> {
147+
let bigint = rquickjs::BigInt::from_js(ctx, value)?;
148+
let i64_value = bigint.to_i64()?;
149+
Ok(BigIntWrapper(i64_value))
150+
}
151+
}
152+
153+
pub struct UInt8Array(pub Vec<u8>);
154+
155+
impl<'js> IntoJs<'js> for UInt8Array {
156+
fn into_js(self, ctx: &Ctx<'js>) -> rquickjs::Result<Value<'js>> {
157+
let array = rquickjs::TypedArray::new_copy(ctx.clone(), self.0)?;
158+
Ok(array.into_value())
159+
}
160+
}
161+
162+
impl<'js> FromJs<'js> for UInt8Array {
163+
fn from_js(_ctx: &Ctx<'js>, value: Value<'js>) -> rquickjs::Result<Self> {
164+
let array = rquickjs::TypedArray::<'js, u8>::from_value(value)?;
165+
Ok(UInt8Array(
166+
array
167+
.as_bytes()
168+
.expect("the UInt8Array passed to decode is detached")
169+
.to_vec(),
170+
))
171+
}
172+
}

crates/wasm-rquickjs/src/types.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,22 @@ pub fn get_wrapped_type_internal(
353353

354354
match &typ.kind {
355355
TypeDefKind::Tuple(tuple) => get_wrapped_type_tuple(ctx, &typ.name, tuple),
356+
TypeDefKind::List(Type::U8) => {
357+
// Special case for list<u8> to be represented by UInt8Array
358+
Ok(WrappedType {
359+
wrap: Box::new(move |ts| quote! { crate::wrappers::UInt8Array(#ts) }),
360+
unwrap: Box::new(move |ts| quote! { #ts.0 }),
361+
wrapped_type_ref: quote! { crate::wrappers::UInt8Array },
362+
original_type_ref: quote! { Vec<u8> },
363+
unwrap_for_imported: Box::new(move |ts| {
364+
if ctx.mode.lists_borrowed {
365+
quote! {&#ts.0 }
366+
} else {
367+
quote! { #ts.0 }
368+
}
369+
}),
370+
})
371+
}
356372
TypeDefKind::List(elem_type) => get_wrapped_type_list(ctx, elem_type),
357373
TypeDefKind::Option(elem_type) => get_wrapped_type_option(ctx, elem_type),
358374
TypeDefKind::Result(result) => get_wrapped_type_result(ctx, result),
@@ -379,9 +395,9 @@ pub fn get_wrapped_type_internal(
379395
Type::S64 | Type::U64 => {
380396
let original_type_ref = ctx.original_type_ref;
381397
Ok(WrappedType {
382-
wrap: Box::new(move |ts| quote! { crate::internal::BigIntWrapper(#ts) }),
398+
wrap: Box::new(move |ts| quote! { crate::wrappers::BigIntWrapper(#ts) }),
383399
unwrap: Box::new(move |ts| quote! { #ts.0 }),
384-
wrapped_type_ref: quote! { crate::internal::BigIntWrapper<#original_type_ref> },
400+
wrapped_type_ref: quote! { crate::wrappers::BigIntWrapper<#original_type_ref> },
385401
original_type_ref,
386402
unwrap_for_imported: Box::new(move |ts| quote! { #ts.0 }),
387403
})

crates/wasm-rquickjs/src/typescript.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,7 @@ fn ts_type_definition(
609609
.unwrap_or("Error".to_string());
610610
Ok(format!("Result<{ok_type}, {err_type}>"))
611611
}
612+
TypeDefKind::List(Type::U8) => Ok("Uint8Array".to_string()),
612613
TypeDefKind::List(elem_type) | TypeDefKind::FixedSizeList(elem_type, _) => Ok(format!(
613614
"{}[]",
614615
ts_type_reference(context, elem_type, interface_stack)?

examples/imports3/src/imports3.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,10 @@ export const test = () => {
7777
// f14: func(a: u64) -> u64;
7878
const f14 = types.f14(1234567890n);
7979
console.log(`f14: ${f14}`);
80+
// f15: func(bytes: list<u8>) -> list<u8>
81+
const f15 = types.f15(new Uint8Array([1, 2, 3, 4, 5]));
82+
console.log(`f15: ${f15}`);
83+
if (f15 instanceof Uint8Array) {
84+
console.log(`f15 is a Uint8Array with length: ${f15.length}`);
85+
}
8086
};

examples/imports3/wit/deps/types-in-exports/types-in-exports.wit

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ interface types {
7474
f12: func(a: string) -> option<color>;
7575
f13: func(a: permissions) -> permissions;
7676
f14: func(a: u64) -> u64;
77+
f15: func(bytes: list<u8>) -> list<u8>;
7778
}
7879

7980
world types-in-exports {

examples/types-in-exports/src/types-in-exports.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,5 +128,9 @@ export const types = {
128128
console.log(`a: ${a}`);
129129
// return: u64
130130
return a;
131+
},
132+
f15: (bytes) => {
133+
console.log(`bytes: ${bytes}`);
134+
return bytes;
131135
}
132136
};

examples/types-in-exports/wit/types-in-exports.wit

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ interface types {
7474
f12: func(a: string) -> option<color>;
7575
f13: func(a: permissions) -> permissions;
7676
f14: func(a: u64) -> u64;
77+
f15: func(bytes: list<u8>) -> list<u8>;
7778
}
7879

7980
world types-in-exports {

tests/goldenfiles/generated_types_types-in-exports.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ declare module 'types-in-exports' {
1515
export function f12(a: string): Promise<Color | undefined>;
1616
export function f13(a: Permissions): Promise<Permissions>;
1717
export function f14(a: bigint): Promise<bigint>;
18+
export function f15(bytes: Uint8Array): Promise<Uint8Array>;
1819
export type Color = quickjsTypesInExportsOtherTypes.Color;
1920
export type ListOfStrings = quickjsTypesInExportsOtherTypes.ListOfStrings;
2021
export type Rec2 = quickjsTypesInExportsOtherTypes.Rec2;

tests/runtime.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,9 @@ async fn imports3(
657657
f13: {"read":true,"write":false,"execute":true}
658658
a: 1234567890
659659
f14: 1234567890
660+
bytes: 1,2,3,4,5
661+
f15: 1,2,3,4,5
662+
f15 is a Uint8Array with length: 5
660663
"#
661664
)
662665
);

0 commit comments

Comments
 (0)