I think that elm’s story around parsing binary files is a non-starter.
I’m interested in writing applications based around streamable files, and this means that if I cannot jump around a file, I should at least be able to process it as lazily as possible, so that I can get something showing up on the user’s screen as fast as possible.
It’s important that there be asynchronous tooling to perform processing while the browser loads the file into memory–and not just byte-by-byte.
In Javascript, using the file picker to select a 1GB MKV file, I use the file’s ReadableStream to immediately chop off the first 4 bytes and instantly output them to the screen: https://codepen.io/illeatmyhat/pen/XWWNmVd
In elm, this same task takes 30 seconds before anything shows up to the screen: https://gist.github.com/illeatmyhat/801b60e64a30c01cc23e8a8b40ea2a05
For reference, in Javascript, it takes ~14 seconds to do the same thing synchronously using blob.arrayBuffer().
I use the File.toBytes function here to select the file as Bytes, which seems to be the culprit here.
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
FileRequested ->
( model
, Select.file ["video/x-matroska"] FileSelected
)
FileSelected file ->
( model
, Task.perform FileLoaded (File.toBytes file)
)
FileLoaded content ->
( { model | file = getEBMLID content }
, Cmd.none
)
getEBMLID is a pretty straight-forward function that just pops off a 32-bit int and converts it to a string.
getEBMLID: Bytes -> Maybe String
getEBMLID file =
Decode.decode (Decode.unsignedInt32 BE) file |> Maybe.map String.fromInt