Skip to content

Mid-Level File API Proposal #50

Closed
Closed
@rylev

Description

@rylev

Addresses #47 in part by proposing a mid-level API. The possibility for a higher level API is left open.

File API

The mid-level file API aims to implement File I/O on top of the raw JS apis found here: https://w3c.github.io/FileAPI/ which includes listing files, creating files, and reading files.

General Differences

In general this API will mostly differ from the web_sys interface in the following ways:

No js_sys Types

js_sys tends to be fairly "stringly" typed, so where we have known enums, the crate will provide bespoke types.

This is also true for errors which are usually exposed as JsValues. In this crate they will be exposed as well-formed Rust types.

Callbacks

All callbacks will be of the appropriate closure type (e.g., FnOnce).

The API

FileList

JS provides a basic collection type over files (usually from an tag). In general FileList will be an opaque struct that offers a rich interface to the collection through an Iterator implementation.

Blob

Blob is a "file like" interface. The crate would expose this as a Rust interface from which the specific types File and RawData inherit. These types would be roughly 1 to 1 translations of the File and Blob objects just with less "stringly" typed interfaces. For example, RawData would accept a known list of mime-types

FileReader

The FileReader API is a bit wonky and can easily be used in the incorrect way. For instance, if the user calls readAsArrayBuffer or other "read" APIs before the data is loaded, the operation won't return data. The crate will expose an API that more properly models the "read" state machine.

This will be done through a futures API which takes the user through the state machine:

let file_reader = FileReader::new();
file_reader.read_as_text(&blob).map(move |contents| {
  element.set_inner_html(contents);
})

The various "read" methods will take ownership of self so that users can't try to read multiple files at once. These methods return an InProgressRead struct that is a future and also contains an abort method for aborting the upload.

The events "error", "load", and "loadend" are all representable through the future and thus aren't exposed on the file reader. The events "progress", "loadstart", and "abort" are still exposed as methods that take the appropriate Rust closure.

FileReaderSync

This API would mirror the future based API just in a different namespace.

Drawbacks, Rationale, and Alternatives

FileReader exposes a very different API from its JS counterpart. We could do a more 1 to 1 translation of the API and leave the improved API for a higher-level crate. This would make this crate only a very marginal improvement on what is already exposed in js_sys.

Unresolved Questions

Is there an ergonomic way to expose FileReader "progress", "loadstart", and "abort" events as part of the future API?
Is there a better way to model the relationship between Blob and File? Possibilities include an enum and a File type which contains a Blob type.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions