-
-
Notifications
You must be signed in to change notification settings - Fork 910
Add bit array FFI functions #5284
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
base: main
Are you sure you want to change the base?
Conversation
| export function List$NonEmpty<T>(head: T, tail: List<T>): List<T>; | ||
| export function List$isEmpty<T>(list: List<T>): boolean; | ||
| export function List$isNonEmpty<T>(list: List<T>): boolean; | ||
| export function List$isEmpty(list: any): boolean; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can write this as:
export function List$isEmpty(list: any): list is List<unknown>...and the same for the other guard functions.
This lets typescript actually refine the type of a value based on the guard.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't List$isEmpty take a List as an argument though? Or is the api supposed to work no matter what we pass to the function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It needs to take any otherwise we can't use these functions for dynamic.classify or string.inspect
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does that still effectively return a boolean @hayleigh-dot-dev ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it look right to you now @hayleigh-dot-dev ?
|
Does that mean all the properties/getters on BitArray should be considered private? |
Yes, everything not in the documented public API is private. |
|
I think there's no way to work with non-byte-aligned/non-zero bitSizes then? |
| export const BitArray$BitArray = (buffer, bitSize, bitOffset) => | ||
| new BitArray(buffer, bitSize, bitOffset); | ||
| export const BitArray$isBitArray = (value) => value instanceof BitArray; | ||
| export const BitArray$BitArray$data = (bitArray) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that the DataView returned here doesn't work for an unaligned bit array input, and if bitArray.bitOffset is non-zero the DataView will give the wrong result in all cases.
Unfortunately, it's not possible to return a valid DataView object for anything except a perfectly byte-aligned BitArray.
One option is to throw an exception similar to what's done above where it'll throw "BitArray.buffer does not support unaligned bit arrays".
Is there a desire to provide functions for safely working with bit arrays in JS FFI code (and that also work with unaligned bit arrays)?
|
@yoshi-monster @richard-viney How could unaligned bit arrays be used at all in JavaScript? The language doesn't have any capability to work with data like that, that I'm aware of. I couldn't think of a design that would provide something that wouldn't be replicating the functionality they have in the Gleam language, and if they can do it in Gleam without loss of performance (or some other drawback) then I don't want to encourage doing it with FFI instead. |
I have to admit every time I FFI to BitArrays I always assert they are byte-aligned, I think my initial reaction was just based on feeling there should be a way to do this without a concrete use-case in mind. |
I think the only sensible use case for FFI is conversion to a Uint8Array / DataView etc. My suggestion would be:
export const BitArray$BitArray$data = (bitArray) => {
if (bitArray.bitSize % 8 !== 0) {
throw Error("Bit arrays that aren't a whole number of bytes can't be read in JavaScript");
}
let array = bitArray.rawBuffer;
if (bitOffset !== 0) {
array = new Uint8Array(bitArray.byteSize);
for (let i = 0; i < array.length; i++) {
array[i] = bitArray.byteAt(i);
}
}
return new DataView(array.buffer, array.byteOffset, array.byteLength);
}; |
No description provided.