Skip to content
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

feat(neon): Add extractor for TypedArray #1089

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

Conversation

kjvalencik
Copy link
Member

This removes the TryIntoJs implementation for Arc to free it up for a Boxed implementation.

In order to maintain the ability to return borrowed buffers (e.g., Arc<Vec<u8>>), I've added extractors for typed arrays. It requires slightly more type noise (e.g., Uint8Array<Arc<Vec<u8>> instead of Arc<Vec<u8>>), but it is more powerful because it will work across all types that are AsRef<[T]>.

The implementation in this PR opts for bespoke struct extractors for each of the typed array types (e.g., Uint8Array, Int8Array). The benefits of this approach are the simplicity of implementation and the ability to directly use them as new types. The most significant downside is that there's no trait to unify them for generic buffer functions.

If we wanted to include a trait for handling these types generically, we have two options.

PhantomData

pub struct TypedArray<T, I>(pub T, PhantomData<I>);

In this approach, we add a PhantomData to carry the type of array (e.g., u8 for Uint8Array). The downside of this approach is that we need a new constructor for creating it and need a placeholder for destructuring.

#[neon::export]
fn example(
    TypedArray(arg, _): Uint16Array<Vec<u16>>,
) -> Uint8Array<Vec<u8>> {
    TypedArray::<u8>::new(vec![0])
}

The advantage is that it is simple and eliminates the duplicate/macro generated code in this PR.

Marker and Trait

Alternatively, we can create a trait to carry the two types (container and array type) as associated types and implement it for a marker type.

pub trait ArrayType: private::Sealed {
    type Type;
    type Item: Binary;
}

pub struct ArrayMarker<T, B>(PhantomData<T>, PhantomData<B>);

impl<T, I> ArrayType for ArrayMarker<T, I>
where
    I: Binary,
{
    type Type = T;
    type Item = I;
}

pub type Uint8Array<T> = TypedArray<ArrayMarker<T, u8>>;

#[neon::export]
fn example(
    TypedArray(_arg): Uint16Array<Vec<u16>>,
) -> Uint8Array<Vec<u8>> {
    TypedArray(vec![0])
}

This ends up having very similar ergonomics to the version in the PR, except we also have an ArrayType trait that can be used to unify the buffer types. The main disadvantage is that it implements an additional pub struct and pub trait to the the API.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant