[whatwg] API for encoding/decoding ArrayBuffers into text

Joshua Bell jsbell at chromium.org
Fri Mar 16 09:19:44 PDT 2012

On Thu, Mar 15, 2012 at 5:20 PM, Glenn Maynard <glenn at zewt.org> wrote:

> On Thu, Mar 15, 2012 at 6:51 PM, Jonas Sicking <jonas at sicking.cc> wrote:
>> What's the use-case for the "stringLength" function? You can't decode
>> into an existing datastructure anyway, so you're ultimately forced to
>> call "decode" at which point the "stringLength" function hasn't helped
>> you.
> stringLength doesn't return the length of the decoded string.  It returns
> the byte offset of the first \0 (or the length of the whole buffer, if
> none), for decoding null-terminated strings.  For multibyte encodings (eg.
> everything except UTF-16 and friends), it's just memchr(), so it's much
> faster than actually decoding the string.

And just to be clear, the use case is decoding data formats where string
fields are variable length null terminated.

> Currently the use-case of simply wanting to convert a string to a
>> binary buffer is a bit cumbersome. You first have to call the
>> "encodedLength" function, then allocate a buffer of the right size,
>> then call the "encode" function.
> I suggested eg.
> result = encode("string", "utf-8", null).output;
> which would create an ArrayBuffer of the required size.  Presumably the
> null ArrayBufferView argument would be optional, so you could just say
> encode("string", "utf-8").

I think we want both encoding and destination to be optional. That leads us
to an API like:

out_dict = stringEncoding.encode("string", opt_dict);

.. where both out_dict and opt_dict are WebIDL Dictionaries:

opt_dict keys: view, encoding
out_dict keys: charactersWritten, byteWritten, output

... where output === view if view is supplied, otherwise a new Uint8Array
(or Uint8ClampedArray??)

If this instead is attached to String, it would look like:

out_dict = my_string.encode(opt_dict);

If it were attached to ArrayBufferView, having a right-size buffer
allocated for the caller gets uglier unless we include a static version.

It doesn't seem possible to implement the 'encode' function without
>> doing multiple scans over the string. The implementation seems
>> required both to check that the data can be decoded using the
>> specified encoding, as well as check that the data will fit in the
>> passed in buffer. Only then can the implementation start decoding the
>> data. This seems problematic.
> Only if it guarantees that it doesn't write anything to the output buffer
> unless the entire result will fit.  I don't think we need to do that; just
> guarantee that it'll be truncated on a whole codepoint.

Agreed. Input/output dicts mean the API documentation a caller needs to
read to understand the usage is more complex than a function signature
which is why I resisted them, but it does seem like the best approach.
Thanks for pushing, Glenn!

In the create-a-buffer-on-the-fly case there will be some memory juggling
going on, either by initially over allocating or reallocating/moving.

> I also don't think it's a good idea to throw an exception for encoding
>> errors. Better to convert characters to the unicode replacement
>> character. I believe we made a similar change to the WebSockets
>> specification recently.
> Was that change made?  I filed
> https://www.w3.org/Bugs/Public/show_bug.cgi?id=16157, but it still seems
> to be undecided.

Settling on an options dict means adding a flag to control this behavior
(throws: true ?) doesn't extend the API surface significantly.

More information about the whatwg mailing list