Giter VIP home page Giter VIP logo

bitbuffer's Introduction

BitBuffer is a bit stream module implemented in pure Lua. Its purpose is to provide an easy way to write and read binary data down to the bit level. It first found life as a replacement for a module that performed rather poorly, and was primarily meant for use on Roblox.

However, no Roblox specific API is used in the main file or tests of this module. The module was written and tested using Lua 5.2, though any version of Lua that has a bit module should be able to run this module with a few modifications. It will probably perform best with LuaJIT, as Roblox's Lua VM is extremely fast compared to PUC-Rio and this module makes use of some specific optimizations (ipairs, as an example, is faster than a numeric for in Roblox).

Why?

Numbers take up a lot of space. Take the number 24930. When written out, it's 5 bytes. That's not an awful lot, but if you had to save hundreds of thousands of numbers of a similiar size, that's a lot of space spent on numbers alone.

When written with this BitBuffer though, 24930 only takes up 2 bytes and becomes ab.

Obviously, the two bytes taken up by ab is less than the 5 bytes taken up by 24930. This difference gets a lot more dramatic the bigger the number: 1633837924 is 10 bytes to write out but in binary is abcd, and 107075202213222 is 15 bytes but turns into abcdef. That's a difference of 9 bytes per number!

For more information, visit the documentation site!

Why not string.pack/string.unpack?

For starters, they didn't exist when this module was written! They also don't exist until Lua 5.3, which is a huge downside.

They're also comparatively slow: BitBuffer does all of its calculations with pure arithmetic and bit32, which is always going to be faster than string creation.

The fact that you have to pass a format string to them is also a huge downside, as it means (un)serializing data that's dynamically generated is annoying.

bitbuffer's People

Contributors

dekkonot avatar jeparlefrancais avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

bitbuffer's Issues

Add functions for exporting in chunks

It would be beneficial to have the ability to output an X length chunk from the current pointer, as very large streams may cause problems if exported all at once.

Ideally in the form of dumpString(length: number?)

Add several common datatypes to module as shorthands

Should include things like Int32 and UInt32. Should also shorthand some like writeByte -> writeUInt8.

Unclear how to handle assertions and testing. Seems like it may add a lot of overhead to run assertions twice in cases like writeFloat32.

  • UInt8
  • Int8
  • UInt16
  • Int16
  • UInt32
  • Int32
  • UInt64
  • Int64
  • Float16
  • Float32
  • Float64

Assertion messages are inconsisent

In some cases (such as writeFloat) the assertion messages use the format bitBuffer.X and in others (such as readBit) they use X (n both cases, X is the name of the function)

Ideally, the format would be bitBuffer.X since it makes debugging easier.

Make sure all the write functions actually return `nil`

Early in development the plan was to have the buffer return false instead of throwing when something went wrong. Artifacts of that exist throughout the base functions but the documentation says they all return nil. Should be corrected at some point.

Switch to faster table.concat use

Creating several medium sized strings and then using table.concat on an array of them is faster than using table.concat on a bunch of small strings.

Remove adler32

After rethinking it, I believe adler32 is too niche to keep in the BitBuffer -- it's easy to implement on its own and is only useful for zlib.

dumpBase64 using incorrect table.create amount

In dumpBase64 for the roblox version, to create the table of output bytes the script will do table.create(math.ceil(byteCount * 0.333)). This is incorrect, as Base64 does not make the file size 1/3. it should be * 1.333.

Add documentation for the module

Documentation is a must, and a dedicated github pages site (made either by hand or with mkdocs) is a good idea, especially when #4 and #2 are dealt with.

Switch to using hex for all constants

The source of the module looks like it's filled with magic numbers, and hex will make it look less like that since numbers like 0x7f and 0xff are obvious to people who know what they're doing

Create roblox specific version of module

The Roblox specific version of the module should:

  • Run in Roblox
  • Use table.create where possible
  • Have type annotations
  • Have Roblox specific datatypes

And long-term should have support for the Roblox CLI when it comes out.

Read base64 string buffer

This request comes from the fact that I can't seem to assign the value I get from buffer.dumpString() into a StringValue object Value property. I tried using a ModuleScript's Source property to store the string but didn't have any luck with that neither.

My solution for this is to store the dumpBase64() string, but it would be nicer to have a way to make BitBuffer read it back ๐Ÿ™‚

It could be done by changing the API to something like this:

BitBuffer(stream: str, options?: { format = "byte" | "base64" | "binary" | "hex" })

Let me know what you think about that!

Reimplement writeUnsigned to finish off current byte when buffer isn't aligned

At the moment, writeUnsigned calls writeByte several times followed by writeBits. It should instead call writeBits with however many bits is needed to make the buffer aligned, call writeByte with whatever is left, then call writeBits after that.

Benchmarks forthcoming, but I assume this will be substantially faster than the current implementation.

Remove bit-level packing

The module currently has several functions that operate on a bit level that utterly thrash the performance of the module, to the point that there's a recommendation to not use them and functions that avoid them entirely. We should remove these entirely in the future.

This is rather far reaching because it involves removing some rather fundamental parts of the module, but it's a small price to pay for performance and futureproofing.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.