{"id":"cipharius/msgpack-luau","name":"msgpack-luau","scope":"cipharius","platform":"roblox","description":"A pure MessagePack binary serialization format implementation in Luau.","version":"0.3.0","latest":"0.3.0","versions":["0.1.0","0.1.1","0.1.2","0.2.0","0.2.1","0.3.0"],"license":"MIT","licenseRating":"safe","licenseCaveats":[],"licenseVerified":true,"dependencies":{},"integrity":"4d844d7e1317c6fde9f581ecd0640e17373f646fae3bb9ae5f7946cd22c26d2b","likes":0,"downloads":0,"install":"forest install cipharius/msgpack-luau","url":"https://forest.dev/p/roblox/cipharius/msgpack-luau","files":"https://api.forest.dev/ai/package/roblox/cipharius/msgpack-luau/files","readme":"<!-- Project links -->\n[latest release]: https://github.com/cipharius/msgpack-luau/releases/latest\n\n<!-- Images -->\n[shield wally release]: https://img.shields.io/endpoint?url=https://runkit.io/clockworksquirrel/wally-version-shield/branches/master/cipharius/msgpack-luau&color=blue&label=wally&style=flat\n\n# MessagePack for Luau\n\n[![Wally release (latest)][shield wally release]][latest release]\n\nA pure MessagePack binary serialization format implementation in Luau.\n\n# Goals\n\n* Fulfill as much of MessagePack specification, as Luau allows\n* Be on par with HttpService's `JSONEncode` and `JSONDecode` performance wise\n* Keep code readable as long as it does not get in the way of prior goals\n\n## Example usage\n\n```lua\nlocal msgpack = require(path.to.msgpack)\nlocal message = msgpack.encode({\"hello\", \"world\", 123, key=\"value\"})\n\nfor i,v in pairs(msgpack.decode(message)) do\n  print(i, v)\nend\n\n-- To store MessagePack message in DataStore, it first needs to be wrapped in UTF8 format\n-- This is not nescessary for HttpService or RemoteEvents!\nlocal dataStore = game:GetService(\"DataStoreService\"):GetGlobalDataStore()\ndataStore:SetAsync(\"message\", msgpack.utf8Encode(message))\n\nlocal retrieved = msgpack.utf8Decode(dataStore:GetAsync(\"message\"))\nfor i,v in pairs(msgpack.decode(retrieved)) do\n  print(i, v)\nend\n```\n\n## API\n\n* `msgpack.encode(data: any): string`\n\n  Encodes any pure Luau datatype in MessagePack binary string format.\n  It does not currently handle any Roblox specific datatypes.\n\n* `msgpack.decode(message: string): any`\n\n  Decodes MessagePack binary string as pure Luau value.\n\n* `msgpack.utf8Encode(message: string): string`\n\n  Wraps binary string in a UTF-8 compatible encoding.\n  Nescessary to save binary strings (like MessagePack serialized data) in DataStore.\n\n* `msgpack.utf8Decode(blob: string): string`\n\n  Unwraps binary string from UTF-8 compatible encoding.\n\n* `msgpack.Extension.new(extensionType: number, blob: buffer): msgpack.Extension`\n\n  Create MessagePack extension type, which is used for custom datatype serialization purposes.\n  First argument `extensionType` must be an integer.\n\n* `msgpack.Int64.new(mostSignificantPart: number, leastSignificantPart: number): msgpack.Int64`\n\n  Represents 64-bit signed integer, which is too large to to represent as Luau integer.\n  Both arguments must be integers.\n\n* `msgpack.UInt64.new(mostSignificantPart: number, leastSignificantPart: number): msgpack.UInt64`\n\n  Represents 64-bit unsigned integer, which is too large to to represent as Luau integer.\n  Both arguments must be integers.\n\n## Performance\n\nOne of the project goals is to match or exceed the performance of Roblox offered data serialization and deserialization methods (HttpService's `JSONEncode` and `JSONDecode`).\nTo ensure fulfilment of this goal the module's methods need to be benchmarked.\n\nTo benchmark message decoding performance an approximately 210KB large JSON encoded payload has been chosen.\nThis JSON is then used as input for `HttpService:JSONEncode()` method and also encoded in MessagePack format so that it can be used as input for `msgpack.decode()` function.\nFor MessagePack encoding [an online msgpack-lite encoder](https://kawanet.github.io/msgpack-lite/) was used.\n\nAs visible in the [boatbomber's benchmarker plugin](https://devforum.roblox.com/t/benchmarker-plugin-compare-function-speeds-with-graphs-percentiles-and-more/829912) results, `msgpack.decode` considerably exceeds `JSONDecode` performance:\n![Figure with JSONDecode and msgpack.decode benchmark results](./assets/decode-benchmark.png)\n\nTo benchmark module's encoding performance same data is used as previously.\nIt is first decoded as table structure then both `msgpack.encode` and `JSONEncode` encode it with the following results:\n![Figure with JSONEncode and msgpack.encode benchmark results](./assets/encode-benchmark.png)\n\nAfter transitioning to Luau buffer based encoding strategy, MessagePack encoder significantly exceeds the performance of the `JSONEncode` function.\nAn interesting observation can be made on how consistent is it's execution time, even in comparision with the `msgpack.decode`.\nThis is most likely is because `msgpack.encode` performs only a single dynamic allocation by computing the nescessary amount of bytes to encode the data and then allocates the result buffer in one go.\n\nHere is another benchmark which combines both decoding and encoding steps and as it can be seen, thanks to much greater `msgpack.decode` speed, both methods together perform better than built-in `JSONEncode` and `JSONDecode`:\n![Figure with \"JSONEncode & JSONDecode\" and \"msgpack.encode & msgpack.decode\" benchmark results](./assets/decode-encode-benchmark.png)\n\nFor more details on the benchmark setup, look into `./benchmark` directory.\nTo construct the benchmarking place, the following shell command was used: `rojo build -o benchmark.rbxl benchmark.project.json`\n\n## State of project\n\nEncoding and decoding fully works, extensions are currently not specially treated.\n","readmeTruncated":false}