elm / bytes

Work with bytes and implement network protocols

Home Page:https://package.elm-lang.org/packages/elm/bytes/latest/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support for simple serialization to more generally useful type

aarondl opened this issue · comments

I was working with this library in order to implement bidirectional communication over grpc-web using a new elm protocol buffer library that makes use of this.

In order to get the bytes that the elm-protocol-buffers library created to the javascript library I used a port. But I found that taking this type from Elm to the outside world was sort of difficult.

In the end I used loop and unsignedUint8 to change it from Bytes.Bytes to List Int so I could throw it through the port at which point I had some thoughts:

  1. Given the state of Elm 0.19 with respect to kernel code in order to support more complicated protocols (grpc) the bytes type will almost certainly need to be given to a port so maybe it should become one of the natively supported pass-through types listed here: https://guide.elm-lang.org/interop/flags.html
  2. Even if the above is done it's probably still required to be able to serialize this to JSON easily. Though I understand that JSON has no native bytes representation so we'd have to pick our poison to solve that.
  3. In lieu of the above two options maybe just a built-in way to marshal between List Int and the Bytes type?

Appreciate any thoughts on this issue.

I too hit this wall when I was sending Protobuf messages over WebSockets. I resorted to the same hack of coercing to a List Int and then sending across the port. I can't speak to the performance implications but something about having to await a binary ArrayBuffer to then turn into a Uint8Array and THEN finally map to a plain-Jane JS list feels very very wrong and do lots of needless work:

// On the receiving side in JS
var ws = new WebSocket("ws://host.site/path/to/websocket");
ws.onmessage = function(event) {
    event.arrayBuffer().then(buf => {
        let intList = [];
        for (let val of buf) {
            intList.push(val)
        }
        app.ports.ws.send(intList);
    });
}

Yuck!

I stopped by to say though that I think this issue of the Bytes object being so opaque and therefore cumbersome feels more like a symptom of a problem than an actual problem. What I am getting at is this: take the elm/http package. It has no issue whatsoever in dealing with binary request and response bodies. Yet there isn't even native support for WebSockets in Elm at all!

Really it's a bit silly when you think about it. Elm, a language that targets the Internet and works towards being a JS replacement, natively (or at least transparently) supports HTTP but not WebSockets? That seems like an almost-intentional shot to the foot.

I exaggerate of course. 😄 Understandably, Elm has it's priorities and WebSockets requiring some JS hackery is a minor transgression. Perfectly reasonable 👍

Overall I am fantastically impressed everything in the ecosystem. I thought it worth noting however that if Elm's support for WebSockets were better, then this conversation wouldn't be happening in the first place. Let's solve X instead of Y!