From 632cccc4bb8a94d12b9b1db902836c99ac048c25 Mon Sep 17 00:00:00 2001 From: Micah Date: Wed, 17 Apr 2024 15:07:04 -0700 Subject: [PATCH] Add initial draft of RFC --- docs/function-buffer-24-bit.md | 48 ++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 docs/function-buffer-24-bit.md diff --git a/docs/function-buffer-24-bit.md b/docs/function-buffer-24-bit.md new file mode 100644 index 0000000..01f0a9f --- /dev/null +++ b/docs/function-buffer-24-bit.md @@ -0,0 +1,48 @@ +# 24-Bit Operations for Buffers + +## Summary + +The built-in `buffer` library will gain 4 new functions: + +- `buffer.writeu24` +- `buffer.readu24` +- `buffer.writei24` +- `buffer.readi24` + +These functions would read and write 24-bit integers to and from a buffer. + +## Motivation + +When working with or creating binary data, it's often desirable to reduce the amount of data written by as much as possible. In the event a 32-bit integer is excessive and a 16-bit integer is too small, people often desire 24-bit integers because it is the next byte-aligned integer width. + +Implementing `writeu24` and `readu24` using the existing `buffer` functions is trivial, but it is inefficient. It requires two seperate bounds checks for the `buffer` function calls, and requires some form of bit manipulation, whether it be through `bit32` or arithmetic. Implementing `readi24` and `writei24` may also be difficult for some people, as it requires considering sign extensions and two's complement representations, so it may cause problems. + +Both of these issues can be overcome by simply providing an efficient and correct implementation for handling 24-bit integers. + +## Design + +Reading and writing both signed and unsigned integers is well defined by the [the buffer RFC](./type-byte-buffer.md). This RFC simply extends the widths supported to include 24-bit integers. + +For the sake of clarity, the functions would have the following type signatures: + +`buffer.writeu24(b: buffer, offset: number, value: number): ()` + +`buffer.writei24(b: buffer, offset: number, value: number): ()` + +`buffer.readu24(b: buffer, offset: number): number` + +`buffer.readi24(b: buffer, offset: number): number` + +This matches the signatures of comparable functions in the `buffer` library + +## Drawbacks + +There is a general expectation that `buffer` functions be given a built-in optimization and that they lower to efficient instructions when native codegen is enabled. This means that any additions like this will either break that trend or take up valuable built-in slots and add to the overall complexity of native codegen. + +Adding support functions in this nature may raise the logical question "why not add X?" because it is accomodating a common use case while neglecting others. This is considered a relatively minor drawback as anyone is allowed to submit an RFC if they wish. + +## Alternatives + +We could simply not do this. It would be fast, easy, and free. The consequence is that everyone who needs 24-bit integer support for buffers must handroll it themselves, potentially introducing bugs. + +An interesting alternative is a `buffer` function to read/write arbitrary width integers. This solves the problem for 24-bit integers but it does not lend itself to having an efficient implementation. Supporting potentially non-byte aligned integer widths (e.g. 1 bit) has complicated semantics, and implementing support for it efficiently would be very difficult. Thus, this design was rejected. \ No newline at end of file