1. rude
  2. love

Issues

Issue #583 wontfix

A more elegant way of creating objects from data-containing strings

hahawoo
created an issue

When creating FileData with love.filesystem.newFileData, a name is required. However, this name isn't required for most uses, so a meaningless name has to be given (as seen in boot.lua, repler, etc.).

So, I propose that this argument have a blank default name.

Also, I assume that it is more common to create FileData from base64 encoded strings than it is to create FileData which uses the name (base64 encoded images are used in boot.lua). And in any case, I think it's more innocuous to have to specify a file decoder if the need arises than to create a meaningless name.

So, I propose that the name argument be shifted along to the third argument of newFileData.

Comments (11)

  1. Alex Szpakowski

    In 0.9.0, if a single string argument is given to love.filesystem.newFileData, it will interpret the string as a file path and try to load the contents of the file at the path into a new FileData, if the file exists.

    love.filesystem.newFileData can also be used to load LÖVE objects from Lua's io module instead of the regular physfs filesystem, by passing the contents and filepath of the io file to newFileData, and then using the resulting FileData instead of a filename string as an argument to the object constructor.

  2. hahawoo reporter

    Ah, so having a single encoded string wouldn't work, and when using Lua's io module, you'd want to specify the file path rather than how it's encoded, right?

    Why does love.filesystem.newFileData accept a file path?

    I may be missing something more obvious (and I'm not sure how it's used internally), but the only thing I can think of is if you wanted to load a file into a memory to be used to construct another object later, but the module for creating that object isn't available right now.

    I thought of File objects as being for "fast and flexible reading and writing to real files", and FileData as being "an intermediate object to create other objects from encoded strings", which is why I couldn't see the sense in creating a FileData from a file path or File, or creating a File from a FileData.

  3. Bart van Strien

    The FileData represents the contents of any file (with a filename hint), and thereby can be used internally a lot better. Before every wrapper accepting a file had to open, then read it, close it, and then use its Data, now they can just cast it to FileData. Also, this means that they are as "native" as Files, which, apart from being nice, is also nice to make sure everything that accepts a File will also accept FileData in the future (within reason), because it's the standard workflow.

  4. Bart van Strien

    I don't see any real advantages for this, especially since I consider the filename more important than the optional base64 decode, and that the change would possibly introduce ambiguity in the API.

  5. hahawoo reporter

    Ah, that sounds cool.

    Although, I do think that currently using newFileData for its "encoded string intermediary" role isn't as elegant as it could be, by the necessary "making up an arbitrary name".

    A couple of thoughts on resolving this:

    • Perhaps newFileData is actually serving two separate purposes? Is base64 decoding used internally, or is it just for external use with encoded strings? Making FileData from files seems to make sense only internally, whereas base64 encoding (I assume) makes more sense externally. Perhaps there could be two separate functions, one for the "loading Data from a file", and one for "making an object from an encoded string", each with their own parameters which make sense for their usage?
    • If the audio format of a file could be identified without the file extension, perhaps there'd be no need for storing file names at all? But uh, I have a feeling making this happen might be... non-trivial. :D
  6. hahawoo reporter

    Oh right, I just assumed because I think audio objects where the only ones which I couldn't create from a FileData with a blank file name.

  7. hahawoo reporter
    • changed status to open

    I think... I may have a solution.

    • Remove the decoding style from newFileData, and its ability to create FileData from data-containing strings.
    love.filesystem.newFileData(iofile, name)
    love.filesystem.newFileData(filepath)
    
    • Adding two new functions for creating FileData from strings, one for unencoded data and one for base64 encoded data:
    love.filesystem.newRawData(string, name)
    love.filesystem.newBase64Data(string, name)
    
    • The name parameters default to a blank string.

    Pros:

    • No need to make up anything or specify something unnecessarily.
    • newFileData is simplified.
    • No need for the file decoder enum.

    Cons:

    • Two new functions.
    • The overloading of newFileData is kind of weird. The filepath seems like an internally used thing, whereas io userdata seems like something for lovers to use (perhaps I'm mistaken though?).

    A variation to address the second con:

    • newFileData is only for loading files, and is meant for internal use.
    love.filesystem.newFileData(filepath)
    
    • Three functions for creating FileData from different sources.
    love.filesystem.newLuaFileData(iofile, name)
    love.filesystem.newRawData(string, name)
    love.filesystem.newBase64Data(string, name)
    

    Pros:

    • As above.

    Cons:

    • Three new functions. Although, perhaps they both have the same number of functions useful to lovers, because maybe newFileData now moves into "only really useful internally" territory.

    (I'm not sure how good the names I chose are. :D)

    Now, you may be thinking "new functions for such a trivial thing?!", but creating objects from strings is a real thing that people do, and the current way it works seems really inelegant.

  8. hahawoo reporter

    Actually there are a couple of problems with what I was suggesting. Apart from making two or three new functions, the names are misleading. For example, newBase64Data doesn't make "base64 data", it makes something from base64 encoded data.

    So, here's my new proposal:

    • One function for creating FileData from a filepath.
    love.filesystem.newFileData(filepath)
    
    • One function for creating FileData from an io file or from a string.
    love.filesystem.newFileData2(iofile, extension)
    love.filesystem.newFileData2(string, "file", extension)
    love.filesystem.newFileData2(string, "base64", extension)
    

    extension would default to a blank string, and I guess it would default to "file" if only a string was given, and it wouldn't be called newFileData2. :D

    Now, at the cost of one extra function, nothing needs to be made up, and there's a nice divide between the internally useful newFileData and the externally useful newFileData2.

  9. Log in to comment