HNHacker News
TopNewBestAskShowJobs

GermlessPendant

4 karma · joined July 16, 2026

submissionscomments
GermlessPendant··on Optimizing Lua string literals to save 400 bytes
> Raw strings are started by [=[ (any number of =s) and terminated by ]=] (same number of =s) and must contain neither their starter nor their terminator. This makes [=[meow [=[ mrrp]=] an invalid string, but [[meow [=[ mrrp]] is valid.

That's not right. You can include the start delimiter in the string:

    Lua 5.2.4  Copyright (C) 1994-2015 Lua.org, PUC-Rio
    > print [=[meow [=[ mrrp]=]
    meow [=[ mrrp
Another note that this doesn't cover is ending with a part of the ending terminator. For instance, if you want to encode the string `foo]`, you can't just put it in zero-equal-sign long delimiters, because you'll have `[[foo]]]`, which fails because you actually have a trailing bracket. The same as if you have the string `]]foo]=`, so you use one equal sign, having `[=[]]foo]=]=]`, leaving you with a trailing `=]`. You need to consider partial end delimiters as well.

Another couple considerations from the reference manual:

> Literals in this bracketed form can run for several lines, do not interpret any escape sequences, and ignore long brackets of any other level. Any kind of end-of-line sequence (carriage return, newline, carriage return followed by newline, or newline followed by carriage return) is converted to a simple newline. When the opening long bracket is immediately followed by a newline, the newline is not included in the string.

So you can't just use the bracketed form to encode arbitrary byte sequences, even checking for the delimiters inside, if you care about the exact representation of line breaks (including if you're packing binary data into a literal lua source file, which you can otherwise do, as lua source files can contain arbitrary bytes), you have to be very careful with the bracketed form for that. Leading newlines are also removed.

So, to put an arbitrary sequence of bytes into a Lua string, you have these general options:

1. Encode the string into an ASCII form (such as base64) and set it as a string literal, and include a decoding step.

2. Encode it into a bracket-delimited string literal, scanning ahead of time to be sure you are using the right number of equal signs based on the enclosed closing brackets (including the ending), and deal with losing all carriage returns and having adjacent carriage returns and line feeds collapsed.

3. Put it as a single-or-double-quoted string literal, and escape the quote delimiter, carriage returns, line feeds, and backslashes.

This works for PUC Lua from 5.2+. I don't know about jlua or forks of that, though. Generally, Option 1 is the best for readable sources, 3 is the best for arbitrary payloads and compactness (but often makes your source file not actually a text file), and 2 is best for actual text where you don't care about the literal shape of the newlines.