Repository navigation
Add opt-in byte strings (LuaPlatform.ByteStrings) - #367
Open
billythekidz wants to merge 3 commits into
Open
billythekidz wants to merge 3 commits into
billythekidz wants to merge 3 commits into
Conversation
Lua strings are UTF-16 by default, so #"x" and string.sub differ from the reference implementation for non-ASCII text. With ByteStrings enabled every char holds one byte, files and standard I/O are read and written as raw bytes, character classes, upper and lower follow the C locale and string.char rejects values above 255. Default behavior is unchanged.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds an opt-in mode in which every
charof a Lua string holds one byte (0-255), so string behavior matches the reference C implementation for UTF-8 data. The default (UTF-16) is unchanged. The README documents the UTF-16 representation as intentional, so nothing changes unless a host setsByteStrings = true.Motivation: with UTF-8 text from files,
string.len("あいうえお")is 5 instead of 15,#,sub,byte,findandformat("%5s")count UTF-16 code units, andstring.upper/%achange non-ASCII characters. Scripts written for C Lua (or LuaJIT / xLua) that handle UTF-8 as bytes then behave differently. Hosts can work around it by converting to Latin-1 themselves, but I measured that this still differs (pattern classes, file contents on disk, file names, stdout), see "Verification".What changes with
ByteStrings = trueLuaStream/Utf8Reader: bytes map 1:1 to chars on read and write. The BOM is not skipped on reads (io.read,io.lines).io.read("*n")skips only ASCII whitespace.LuaState.Load(ReadOnlySpan<byte>): only a UTF-8 BOM is skipped, the rest is kept byte by byte (soLoadFile,dofileandrequirekeep UTF-8 literals as bytes).MatchState:%a %c %d %g %l %p %s %u %w %xuse the C locale (ASCII only).string.upper/lower: ASCII only.string.charrejects values above 255.string.format("%c")takes the low 8 bits.os.getenv,os.tmpnameand the text of I/O and OS errors cross the OS boundary as UTF-8: Lua strings are decoded to .NET strings on the way in and encoded on the way out. Without this a non-ASCII file name would be created with mojibake.API
LuaPlatform.ByteStrings(init property, defaultfalse) andLuaPlatform.DefaultByteStrings.byteStringsparameter onFileSystem,ConsoleStandardIOandLuaStream, and anILuaStream.CreateFromStreamoverload.Lua.LuaByteStringhelper (FromString,ToString,FromBytes,ToBytes) and an internalLuaByteEncoding.FileSystem(string?),LuaStream(mode, stream)andConsoleStandardIO()gained an optional parameter. That is source compatible but a binary break for already compiled callers. I can add explicit overloads instead if you prefer.Verification
dotnet test tests/Lua.Tests/Lua.Tests.csproj -c Release --filter "TestCategory!=ExpectedFailure": 642 passed (610 onmain+ 32 new), 0 failed.Lua.SourceGenerator.Tests: 69 passed.ByteStringTestscome from Lua 5.2.4, and the test scripts also run as is on Lua 5.2.4.cmp, directory listing, stdout and stdin compared byte by byte): identical in byte mode. The same probe onmainwith a host Latin-1 workaround still differs on many checks, 11 of the 12 files and stdout.strings.lua,literals.lua,sort.luaanderrors.luapass in byte mode.dotnet csharpier check .is clean.src/Luabuilds fornet10.0,net8.0,net6.0andnetstandard2.1.Not covered
netstandard2.1runtime, only compiled.ILuaFileSystem/ILuaStandardIOimplementations must read and write bytes themselves.string.dumpis still unsupported. UTF-16/32 BOM files are treated as plain bytes in this mode (as in C Lua).?when written; useLuaByteString.FromStringto pass .NET text in.Related
Unrelated bugs found while building the differential tests are sent separately: #364 (
os.rename), #365 (w+on a missing file), #366 (gsubreplacement strings,%f). This PR does not depend on them.This is a larger design change than the other three. If you would rather discuss the approach first, or want it split (platform flag, I/O, pattern classes), I am happy to rework it.