mirror of
https://github.com/aziascreations/PB-MessagePack.git
synced 2026-11-03 17:01:24 +01:00
9facb66ee8
Co-Authored-By: Claude <noreply@anthropic.com>
156 lines
6.4 KiB
Markdown
156 lines
6.4 KiB
Markdown
# PureBasic - MsgPack
|
|
PureBasic Include for serializing and deserializing MessagePack data.
|
|
|
|
Based on the [msgpack/msgpack](https://github.com/msgpack/msgpack) specification.
|
|
|
|
|
|
> **🤖 AI Disclaimer** \
|
|
> This project uses AI-assisted development tools. \
|
|
> See the [AI usage policy](ai-policy.md) for details.
|
|
|
|
|
|
## Features
|
|
* Full support of the [MessagePack](https://github.com/msgpack/msgpack) specification
|
|
* Explicit or implicit data formats when reading/writing
|
|
* *ReadInteger vs ReadI8/ReadU8/...*
|
|
* ~~Fully documented~~
|
|
* Supports all modern PureBasic setups
|
|
* x86/x64/arm64
|
|
* asm/c backends
|
|
* 5.73 to 6.41
|
|
|
|
|
|
## Limitations
|
|
* No custom `malloc`/`realloc`/`free` callbacks
|
|
* More involved Map and Array interactions
|
|
* *No dynamic typing*
|
|
* *Building arrays/maps requires special insertion in parent MsgPack (See [examples](#arrays--maps))*
|
|
* *Lots of internal checks for boundaries and counts before any reading can be done*
|
|
* *Deep nesting costs more time, see [Performances](#performances)*
|
|
* Usage of larger `.q` type for field sizes
|
|
* *Helps prevent unsigned numbers causing issues on x86*
|
|
* Particular handling of signaling `NaN` for *Float32*
|
|
* `0x7F800001` may be returned as `0x7FC00001` on x86 and x64 (x87 FPU limitation)
|
|
* ARM64 keeps them as-is
|
|
* `MsgPackReadFloat` does it on all architectures
|
|
* No implementation of the *Timestamp* extension
|
|
|
|
|
|
## Usage
|
|
|
|
### Submodule
|
|
Adding as a submodule:
|
|
```shell
|
|
git submodule add https://github.com/aziascreations/PB-MessagePack.git Includes/PB-MessagePack
|
|
```
|
|
|
|
Pull latest submodule version:
|
|
```shell
|
|
git submodule update --init --recursive
|
|
```
|
|
|
|
|
|
### Inclusion
|
|
Include the main file, it pulls in everything else, [PB-Endianness](https://github.com/aziascreations/PB-Endianness) included:
|
|
```purebasic
|
|
XIncludeFile "Includes/PB-MessagePack/Includes/MessagePack.pbi"
|
|
```
|
|
|
|
The options below can be defined before the inclusion:
|
|
* `#MsgPack_MaxDepth` - Maximum nesting depth of arrays and maps, from `1` to `4096`. (Default: `128`)
|
|
* `#MsgPack_DisableNullChecks` - Skips the `#Null` pointer checks when set to `#True`. (Default: `#False`)
|
|
|
|
### Double import safeguard
|
|
`Endianness.pbi` raises a `CompilerError` if it is included twice from different paths,
|
|
to prevent two versions of it from being mixed.
|
|
|
|
If your project, or another include, already uses its own copy of PB-Endianness,
|
|
include it **before** `MessagePack.pbi`, which will then skip its own copy:
|
|
```purebasic
|
|
XIncludeFile "Includes/PB-Endianness/Includes/Endianness.pbi"
|
|
XIncludeFile "Includes/PB-MessagePack/Includes/MessagePack.pbi"
|
|
```
|
|
|
|
Including it afterward will trigger the error, unless `#Endianness_BypassIncludeCheck` is defined.
|
|
|
|
|
|
## Performances
|
|
|
|
> [!WARNING]
|
|
> Parts of the library can be much slower than C# and Python.
|
|
>
|
|
> This is partially due to many security checks, and the rest is actively being investigated.
|
|
> We're also in the early stages of development, so there's also that...
|
|
|
|
### Security trade-offs
|
|
Arrays and maps are always validated before being used:
|
|
* `MsgPackExamine` checks the whole array/map before returning a view, so its content is read twice. \
|
|
Examining a nested array/map checks its content again, so data nested `N` levels deep can be read up to `N+1` times.
|
|
* `MsgPackWriteArray/Map` and their variants check and count the given fields, then copy them. \
|
|
Building nested arrays/maps copies the inner data once per level.
|
|
* `MsgPackGetFieldFullSize`, `MsgPackSkip` and `MsgPackNextEntry` walk through every contained field, they don't jump over them.
|
|
|
|
This is mostly noticeable with deeply nested data, which is why `#MsgPack_MaxDepth` defaults to `128` to prevent wasting time on hostile data.
|
|
|
|
`#MsgPack_ExaminationOptions_Unsafe` skips the check done by `MsgPackExamine`, and it can be used on non-root iterable values. \
|
|
However, using on an iterable element at the root means invalid data is only detected while iterating !
|
|
|
|
|
|
### Current status
|
|
* Binary data and skipping fields is faster than in msgpack and MessagePack-CSharp.
|
|
* Small fields, short strings and maps are slower than in MessagePack-CSharp.
|
|
* Writing maps is slower that C# and Python because of the checks mentionned above.
|
|
* Strings are about 4 times slower to write and up to 11 times slower to read than binary data of the same size.
|
|
* *Currently being [investigated](PerfTests/Investigations.md).*
|
|
* The new strings library in PureBasic 6.40+ is 2.5 to 4 times faster than older versions.
|
|
* Using the C backend instead of the ASM one is up to 3 times faster.
|
|
* Preallocate the buffer or using a bigger `GrowthIncrement` than the default of `1` makes small writes up to 35 times faster.
|
|
* `#MsgPack_DisableNullChecks` only saves about 5%.
|
|
* Examining nested data gets quadratically slower with the depth
|
|
* *It is up to 17 times slower when not using `#MsgPack_ExaminationOptions_Unsafe` at 128 levels.*
|
|
|
|
The detailed results, workloads and how to run them are in [PerfTests/readme.md](PerfTests/readme.md).
|
|
|
|
|
|
## Examples
|
|
|
|
### Explicit vs Implicit typing
|
|
* [BasicExplicitTyping.pb](Examples/BasicExplicitTyping/BasicExplicitTyping.pb)
|
|
* [BasicImplicitTyping.pb](Examples/BasicImplicitTyping/BasicImplicitTyping.pb)
|
|
|
|
### Data types
|
|
* [BasicStrings.pb](Examples/BasicStrings/BasicStrings.pb)
|
|
* [BasicBinary.pb](Examples/BasicBinary/BasicBinary.pb)
|
|
* [BasicExtensions.pb](Examples/BasicExtensions/BasicExtensions.pb)
|
|
|
|
### Arrays & Maps
|
|
* [BasicArrays.pb](Examples/BasicArrays/BasicArrays.pb)
|
|
* [BasicMaps.pb](Examples/BasicMaps/BasicMaps.pb)
|
|
|
|
### Dumping a buffer
|
|
* [DumpExplicitTypes.pb](Examples/DumpExplicitTypes/DumpExplicitTypes.pb) - Exact format code of each field
|
|
* [DumpImplicitTypes.pb](Examples/DumpImplicitTypes/DumpImplicitTypes.pb) - General data type of each field
|
|
|
|
|
|
## Cloning
|
|
Use this command to clone the repository and its submodules:
|
|
```
|
|
git clone --recurse-submodules https://github.com/aziascreations/PB-MessagePack.git
|
|
```
|
|
|
|
If you forgot the submodules, use this command:
|
|
```shell
|
|
git submodule update --init --recursive
|
|
```
|
|
|
|
|
|
## Special Thanks
|
|
* [AndyMK](https://www.purebasic.fr/english/memberlist.php?mode=viewprofile&u=2587) / [agorangetek](https://github.com/agorangetek)
|
|
* PureBasic Visual Studio Code Extension ([GitHub repository](https://github.com/agorangetek/purebasic-vscode-extension))
|
|
* [Louis Somers](https://github.com/mlsomers)
|
|
* LsMsgPack windows utility ([GitHub repository](https://github.com/mlsomers/LsMsgPack))
|
|
|
|
|
|
## License
|
|
All the code in this repo is released in the [Public Domain](LICENSE).
|