diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6d1c5e2..5c17dea 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,7 +16,7 @@ jobs: matrix: # 架构配置标识符 arch_config: [linux-x86_64, linux-aarch64, macos-arm64, windows-x86_64] - version: ["0.14.1", "0.15.1", "0.16.0"] + version: ["0.16.0", "master"] include: # Linux x86_64 - arch_config: linux-x86_64 diff --git a/README.md b/README.md index 1f43633..677aa4f 100644 --- a/README.md +++ b/README.md @@ -45,14 +45,15 @@ This library is tested and optimized for all major platforms and architectures: | Zig Version | Library Version | Status | | -------------------- | --------------- | ------------------------------------- | | 0.13 and older | 0.0.6 | Legacy support | -| 0.14.0 | Current | ✅ Fully supported | -| 0.15.x | Current | ✅ Fully supported | -| 0.16.0 | Current | ✅ Supported with compatibility layer | +| 0.14.x / 0.15.x | Earlier releases | Not supported by the current version | +| 0.16.0 | Current | Supported with compatibility layer | +| 0.17.0-dev | Current | Initial support; CI tracks `master` | > **Note:** For Zig 0.13 and older versions, please use version `0.0.6` of this library. +> **Note:** The current library requires Zig `0.16.0` or later. Zig `0.17.0-dev` is unreleased; compatibility may change as development continues. > **Note:** Zig 0.16+ removes `std.io.FixedBufferStream`, but this library provides a compatibility layer to maintain the same API across all supported versions. -For Zig `0.14.0`, `0.15.x`, and `0.16.0`, follow these steps: +For Zig `0.16.0` and `0.17.0-dev`, follow these steps: 1. **Add as a dependency:** Add the library to your `build.zig.zon` file. You can fetch a specific commit or branch. @@ -64,9 +65,9 @@ For Zig `0.14.0`, `0.15.x`, and `0.16.0`, follow these steps: 2. **Configure your `build.zig`:** Add the `zig-msgpack` module to your executable. -### Using std.io.Reader and std.io.Writer (Zig 0.15+) +### Using std.Io.Reader and std.Io.Writer -For Zig 0.15 and later, you can use the convenient `PackerIO` API with standard I/O interfaces: +On supported Zig versions, you can use the convenient `PackerIO` API with standard I/O interfaces: ```zig const std = @import("std"); @@ -185,9 +186,9 @@ For maximum compatibility or when you need more control, use the generic `Pack` ## Usage -### Using std.io.Reader and std.io.Writer (Zig 0.15+) +### Using std.Io.Reader and std.Io.Writer -For Zig 0.15 and later, you can use the convenient `PackerIO` API with standard I/O interfaces: +On supported Zig versions, you can use the convenient `PackerIO` API with standard I/O interfaces: ```zig const std = @import("std"); @@ -479,8 +480,8 @@ msgpack.MsgPackError.ExtDataTooLarge // Extension payload too large - **`msgpack.Pack`**: The main struct for packing and unpacking MessagePack data with default safety limits. - **`msgpack.PackWithLimits`**: Create a packer with custom safety limits for specific security requirements. - **`msgpack.Payload`**: A union that represents any MessagePack type. It provides methods for creating and interacting with different data types (e.g., `mapPayload`, `strToPayload`, `mapGet`). -- **`msgpack.PackerIO`**: (Zig 0.15+) Convenient wrapper for working with `std.io.Reader` and `std.io.Writer`. -- **`msgpack.packIO`**: (Zig 0.15+) Convenience function to create a `PackerIO` instance. +- **`msgpack.PackerIO`**: Convenient wrapper for working with `std.Io.Reader` and `std.Io.Writer`. +- **`msgpack.packIO`**: Convenience function to create a `PackerIO` instance. - **`msgpack.ParseLimits`**: Configuration struct for parser safety limits. - **Constant Structures**: `FixLimits`, `IntBounds`, `FixExtLen`, `TimestampExt`, `MarkerBase` - organized constants for better code clarity. @@ -530,15 +531,15 @@ This library uses an **iterative parser** (not recursive) to provide strong secu - Zero memory leaks verified by GPA (General Purpose Allocator) in tests - Safe to parse untrusted data from network, files, or user input -### Zig 0.16 Compatibility +### Zig 0.16 and 0.17 Development Compatibility Starting from Zig 0.16, the standard library underwent significant changes to the I/O subsystem. The `std.io.FixedBufferStream` was removed as part of a broader redesign. This library includes a compatibility layer (`src/compat.zig`) that: - Provides a `BufferStream` implementation for Zig 0.16+ that mimics the behavior of the old `FixedBufferStream` -- Uses conditional compilation to maintain backward compatibility with Zig 0.14 and 0.15 -- Ensures all existing functionality works seamlessly across different Zig versions +- Keeps the same buffer-stream API on Zig 0.16 and 0.17 development builds +- Is exercised by CI on Zig `0.16.0` and the latest `master` development build -This means you can use the same API regardless of your Zig version, and the library will handle the differences internally. +The current minimum supported Zig version is `0.16.0`; older compatibility branches in the source do not imply support for older compilers. Code formatting is checked with Zig `0.16.0`, since development compiler formatters may introduce syntax migrations. ## Testing diff --git a/README_CN.md b/README_CN.md index a606c0a..7d788f6 100644 --- a/README_CN.md +++ b/README_CN.md @@ -45,14 +45,15 @@ Zig 编程语言的 MessagePack 实现。此库提供了一种简单高效的方 | Zig 版本 | 库版本 | 状态 | | -------------------- | -------- | ----------------- | | 0.13 及更早版本 | 0.0.6 | 旧版支持 | -| 0.14.0 | 当前版本 | ✅ 完全支持 | -| 0.15.x | 当前版本 | ✅ 完全支持 | -| 0.16.0 | 当前版本 | ✅ 通过兼容层支持 | +| 0.14.x / 0.15.x | 历史版本 | 当前版本不再支持 | +| 0.16.0 | 当前版本 | 通过兼容层支持 | +| 0.17.0-dev | 当前版本 | 初步支持;CI 跟踪 `master` | > **注意**: 对于 Zig 0.13 及更早版本,请使用本库的 `0.0.6` 版本。 +> **注意**: 当前库要求 Zig `0.16.0` 或更高版本。Zig `0.17.0-dev` 尚未发布,兼容性可能随开发进展而变化。 > **注意**: Zig 0.16+ 移除了 `std.io.FixedBufferStream`,但本库提供了兼容层以在所有支持的版本中维持相同的 API。 -对于 Zig `0.14.0`、`0.15.x` 和 `0.16.0` 版本,请按以下步骤操作: +对于 Zig `0.16.0` 和 `0.17.0-dev` 版本,请按以下步骤操作: 1. **添加为依赖项**: 将库添加到您的 `build.zig.zon` 文件中。您可以获取特定的提交或分支。 @@ -64,9 +65,9 @@ Zig 编程语言的 MessagePack 实现。此库提供了一种简单高效的方 2. **配置您的 `build.zig`**: 将 `zig-msgpack` 模块添加到您的可执行文件中。 -### 使用 std.io.Reader 和 std.io.Writer(Zig 0.15+) +### 使用 std.Io.Reader 和 std.Io.Writer -对于 Zig 0.15 及更高版本,您可以使用便捷的 `PackerIO` API 配合标准 I/O 接口: +在受支持的 Zig 版本上,您可以使用便捷的 `PackerIO` API 配合标准 I/O 接口: ```zig const std = @import("std"); @@ -387,8 +388,8 @@ msgpack.MsgPackError.ExtDataTooLarge // 扩展类型数据过大 - **`msgpack.Pack`**: 用于打包和解包 MessagePack 数据的主要结构体,带默认安全限制。 - **`msgpack.PackWithLimits`**: 创建带自定义安全限制的 packer,满足特定安全需求。 - **`msgpack.Payload`**: 表示任何 MessagePack 类型的联合体。提供创建和与不同数据类型交互的方法(例如 `mapPayload`、`strToPayload`、`mapGet`)。 -- **`msgpack.PackerIO`**:(Zig 0.15+)用于处理 `std.io.Reader` 和 `std.io.Writer` 的便捷包装器。 -- **`msgpack.packIO`**:(Zig 0.15+)创建 `PackerIO` 实例的便捷函数。 +- **`msgpack.PackerIO`**: 用于处理 `std.Io.Reader` 和 `std.Io.Writer` 的便捷包装器。 +- **`msgpack.packIO`**: 创建 `PackerIO` 实例的便捷函数。 - **`msgpack.ParseLimits`**: 解析器安全限制的配置结构体。 - **常量结构体**: `FixLimits`、`IntBounds`、`FixExtLen`、`TimestampExt`、`MarkerBase` - 组织化的常量,提高代码清晰度。 @@ -438,15 +439,15 @@ msgpack.MsgPackError.ExtDataTooLarge // 扩展类型数据过大 - 零内存泄漏(测试中由 GPA 验证) - 可安全解析来自网络、文件或用户输入的不可信数据 -### Zig 0.16 兼容性 +### Zig 0.16 和 0.17 开发版兼容性 从 Zig 0.16 开始,标准库的 I/O 子系统经历了重大变更。作为更广泛重新设计的一部分,`std.io.FixedBufferStream` 被移除。本库包含一个兼容层(`src/compat.zig`),它: - 为 Zig 0.16+ 提供了一个 `BufferStream` 实现,模拟旧版 `FixedBufferStream` 的行为 -- 使用条件编译来保持与 Zig 0.14 和 0.15 的向后兼容性 -- 确保所有现有功能在不同 Zig 版本间无缝工作 +- 在 Zig 0.16 和 0.17 开发版上保持相同的缓冲流 API +- 通过 CI 在 Zig `0.16.0` 和最新的 `master` 开发版上进行验证 -这意味着无论您使用哪个 Zig 版本,都可以使用相同的 API,库会在内部处理差异。 +当前最低支持 Zig `0.16.0`;源码中保留的旧版兼容分支不代表仍支持旧编译器。代码格式检查固定使用 Zig `0.16.0`,因为开发版编译器的格式工具可能引入语法迁移。 ## 测试 diff --git a/build.zig.zon b/build.zig.zon index a371d45..3213b53 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -2,7 +2,7 @@ .name = .zig_msgpack, .version = "0.0.14", .fingerprint = 0x14a3e10e78eefb7a, - .minimum_zig_version = "0.14.0", + .minimum_zig_version = "0.16.0", .dependencies = .{}, .paths = .{ "build.zig", diff --git a/src/bench.zig b/src/bench.zig index b667979..73d89e4 100644 --- a/src/bench.zig +++ b/src/bench.zig @@ -83,7 +83,7 @@ fn benchNilRead(allocator: std.mem.Allocator) !void { const BufferLen = 100; const State = struct { var initialized = false; - var buffer: [BufferLen]u8 = [_]u8{0} ** BufferLen; + var buffer: [BufferLen]u8 = @splat(0); }; if (!State.initialized) { @@ -115,7 +115,7 @@ fn benchBoolRead(allocator: std.mem.Allocator) !void { const BufferLen = 100; const State = struct { var initialized = false; - var buffer: [BufferLen]u8 = [_]u8{0} ** BufferLen; + var buffer: [BufferLen]u8 = @splat(0); }; if (!State.initialized) { @@ -147,7 +147,7 @@ fn benchSmallIntRead(allocator: std.mem.Allocator) !void { const BufferLen = 100; const State = struct { var initialized = false; - var buffer: [BufferLen]u8 = [_]u8{0} ** BufferLen; + var buffer: [BufferLen]u8 = @splat(0); }; if (!State.initialized) { @@ -179,7 +179,7 @@ fn benchLargeIntRead(allocator: std.mem.Allocator) !void { const BufferLen = 100; const State = struct { var initialized = false; - var buffer: [BufferLen]u8 = [_]u8{0} ** BufferLen; + var buffer: [BufferLen]u8 = @splat(0); }; if (!State.initialized) { @@ -211,7 +211,7 @@ fn benchFloatRead(allocator: std.mem.Allocator) !void { const BufferLen = 100; const State = struct { var initialized = false; - var buffer: [BufferLen]u8 = [_]u8{0} ** BufferLen; + var buffer: [BufferLen]u8 = @splat(0); }; if (!State.initialized) { @@ -248,7 +248,7 @@ fn benchShortStrRead(allocator: std.mem.Allocator) !void { const BufferLen = 1000; const State = struct { var initialized = false; - var buffer: [BufferLen]u8 = [_]u8{0} ** BufferLen; + var buffer: [BufferLen]u8 = @splat(0); }; if (!State.initialized) { @@ -276,9 +276,14 @@ fn benchMediumStrWrite(allocator: std.mem.Allocator) !void { var read_buffer = fixedBufferStream(&arr); var p = pack.init(&write_buffer, &read_buffer); - const test_str = "This is a medium length string for benchmarking MessagePack performance. " ** 4; + const base = + "This is a medium length string for benchmarking MessagePack performance. "; + + const test_str = base ++ base ++ base ++ base; + const str = try Payload.strToPayload(test_str, allocator); defer str.free(allocator); + try p.write(str); } @@ -286,7 +291,7 @@ fn benchMediumStrRead(allocator: std.mem.Allocator) !void { const BufferLen = 2000; const State = struct { var initialized = false; - var buffer: [BufferLen]u8 = [_]u8{0} ** BufferLen; + var buffer: [BufferLen]u8 = @splat(0); }; if (!State.initialized) { @@ -294,9 +299,14 @@ fn benchMediumStrRead(allocator: std.mem.Allocator) !void { var read_buffer = fixedBufferStream(State.buffer[0..]); var p = pack.init(&write_buffer, &read_buffer); - const test_str = "This is a medium length string for benchmarking MessagePack performance. " ** 4; + const base = + "This is a medium length string for benchmarking MessagePack performance. "; + + const test_str = base ++ base ++ base ++ base; + const str = try Payload.strToPayload(test_str, allocator); defer str.free(allocator); + try p.write(str); State.initialized = true; @@ -319,7 +329,7 @@ fn benchSmallBinWrite(allocator: std.mem.Allocator) !void { var read_buffer = fixedBufferStream(&arr); var p = pack.init(&write_buffer, &read_buffer); - var data = [_]u8{1} ** 32; + var data: [32]u8 = @splat(1); const bin = try Payload.binToPayload(&data, allocator); defer bin.free(allocator); try p.write(bin); @@ -329,7 +339,7 @@ fn benchSmallBinRead(allocator: std.mem.Allocator) !void { const BufferLen = 1000; const State = struct { var initialized = false; - var buffer: [BufferLen]u8 = [_]u8{0} ** BufferLen; + var buffer: [BufferLen]u8 = @splat(0); }; if (!State.initialized) { @@ -337,7 +347,7 @@ fn benchSmallBinRead(allocator: std.mem.Allocator) !void { var read_buffer = fixedBufferStream(State.buffer[0..]); var p = pack.init(&write_buffer, &read_buffer); - var data = [_]u8{1} ** 32; + var data: [32]u8 = @splat(1); const bin = try Payload.binToPayload(&data, allocator); defer bin.free(allocator); try p.write(bin); @@ -371,7 +381,7 @@ fn benchLargeBinRead(allocator: std.mem.Allocator) !void { const BufferLen = 2000; const State = struct { var initialized = false; - var buffer: [BufferLen]u8 = [_]u8{0} ** BufferLen; + var buffer: [BufferLen]u8 = @splat(0); }; if (!State.initialized) { @@ -419,7 +429,7 @@ fn benchSmallArrayRead(allocator: std.mem.Allocator) !void { const BufferLen = 1000; const State = struct { var initialized = false; - var buffer: [BufferLen]u8 = [_]u8{0} ** BufferLen; + var buffer: [BufferLen]u8 = @splat(0); }; if (!State.initialized) { @@ -462,7 +472,7 @@ fn benchMediumArrayRead(allocator: std.mem.Allocator) !void { const BufferLen = 5000; const State = struct { var initialized = false; - var buffer: [BufferLen]u8 = [_]u8{0} ** BufferLen; + var buffer: [BufferLen]u8 = @splat(0); }; if (!State.initialized) { @@ -513,7 +523,7 @@ fn benchSmallMapRead(allocator: std.mem.Allocator) !void { const BufferLen = 2000; const State = struct { var initialized = false; - var buffer: [BufferLen]u8 = [_]u8{0} ** BufferLen; + var buffer: [BufferLen]u8 = @splat(0); }; if (!State.initialized) { @@ -564,7 +574,7 @@ fn benchMediumMapRead(allocator: std.mem.Allocator) !void { const BufferLen = 10000; const State = struct { var initialized = false; - var buffer: [BufferLen]u8 = [_]u8{0} ** BufferLen; + var buffer: [BufferLen]u8 = @splat(0); }; if (!State.initialized) { @@ -603,7 +613,7 @@ fn benchExtWrite(allocator: std.mem.Allocator) !void { var read_buffer = fixedBufferStream(&arr); var p = pack.init(&write_buffer, &read_buffer); - var data = [_]u8{1} ** 16; + var data: [16]u8 = @splat(1); const ext = try Payload.extToPayload(42, &data, allocator); defer ext.free(allocator); try p.write(ext); @@ -613,7 +623,7 @@ fn benchExtRead(allocator: std.mem.Allocator) !void { const BufferLen = 1000; const State = struct { var initialized = false; - var buffer: [BufferLen]u8 = [_]u8{0} ** BufferLen; + var buffer: [BufferLen]u8 = @splat(0); }; if (!State.initialized) { @@ -621,7 +631,7 @@ fn benchExtRead(allocator: std.mem.Allocator) !void { var read_buffer = fixedBufferStream(State.buffer[0..]); var p = pack.init(&write_buffer, &read_buffer); - var data = [_]u8{1} ** 16; + var data: [16]u8 = @splat(1); const ext = try Payload.extToPayload(42, &data, allocator); defer ext.free(allocator); try p.write(ext); @@ -655,7 +665,7 @@ fn benchTimestamp32Read(allocator: std.mem.Allocator) !void { const BufferLen = 1000; const State = struct { var initialized = false; - var buffer: [BufferLen]u8 = [_]u8{0} ** BufferLen; + var buffer: [BufferLen]u8 = @splat(0); }; if (!State.initialized) { @@ -691,7 +701,7 @@ fn benchTimestamp64Read(allocator: std.mem.Allocator) !void { const BufferLen = 1000; const State = struct { var initialized = false; - var buffer: [BufferLen]u8 = [_]u8{0} ** BufferLen; + var buffer: [BufferLen]u8 = @splat(0); }; if (!State.initialized) { @@ -746,7 +756,7 @@ fn benchNestedStructureRead(allocator: std.mem.Allocator) !void { const BufferLen = 10000; const State = struct { var initialized = false; - var buffer: [BufferLen]u8 = [_]u8{0} ** BufferLen; + var buffer: [BufferLen]u8 = @splat(0); }; if (!State.initialized) { @@ -798,7 +808,7 @@ fn benchMixedTypesWrite(allocator: std.mem.Allocator) !void { try mixed.setArrElement(4, Payload.floatToPayload(3.14)); try mixed.setArrElement(5, try Payload.strToPayload("hello", allocator)); - var bin_data = [_]u8{1} ** 8; + var bin_data: [8]u8 = @splat(1); try mixed.setArrElement(6, try Payload.binToPayload(&bin_data, allocator)); var inner_arr = try Payload.arrPayload(2, allocator); @@ -819,7 +829,7 @@ fn benchMixedTypesRead(allocator: std.mem.Allocator) !void { const BufferLen = 5000; const State = struct { var initialized = false; - var buffer: [BufferLen]u8 = [_]u8{0} ** BufferLen; + var buffer: [BufferLen]u8 = @splat(0); }; if (!State.initialized) { @@ -837,7 +847,7 @@ fn benchMixedTypesRead(allocator: std.mem.Allocator) !void { try mixed.setArrElement(4, Payload.floatToPayload(3.14)); try mixed.setArrElement(5, try Payload.strToPayload("hello", allocator)); - var bin_data = [_]u8{1} ** 8; + var bin_data: [8]u8 = @splat(1); try mixed.setArrElement(6, try Payload.binToPayload(&bin_data, allocator)); var inner_arr = try Payload.arrPayload(2, allocator); @@ -868,14 +878,16 @@ fn benchMixedTypesRead(allocator: std.mem.Allocator) !void { // ============================================================================ fn runBenchmarks() !void { + const equal_str: [80]u8 = @splat('='); + const minus_str: [80]u8 = @splat('-'); std.debug.print("\n", .{}); - std.debug.print("=" ** 80 ++ "\n", .{}); + std.debug.print(equal_str ++ "\n", .{}); std.debug.print("MessagePack Benchmark Suite\n", .{}); - std.debug.print("=" ** 80 ++ "\n\n", .{}); + std.debug.print(equal_str ++ "\n\n", .{}); // Basic Types std.debug.print("Basic Types:\n", .{}); - std.debug.print("-" ** 80 ++ "\n", .{}); + std.debug.print(minus_str ++ "\n", .{}); try benchmark("Nil Write", 1000000, benchNilWrite); try benchmark("Nil Read", 1000000, benchNilRead); try benchmark("Bool Write", 1000000, benchBoolWrite); @@ -890,7 +902,7 @@ fn runBenchmarks() !void { // Strings std.debug.print("Strings:\n", .{}); - std.debug.print("-" ** 80 ++ "\n", .{}); + std.debug.print(minus_str ++ "\n", .{}); try benchmark("Short String Write (5 bytes)", 500000, benchShortStrWrite); try benchmark("Short String Read (5 bytes)", 500000, benchShortStrRead); try benchmark("Medium String Write (~300 bytes)", 100000, benchMediumStrWrite); @@ -899,7 +911,7 @@ fn runBenchmarks() !void { // Binary Data std.debug.print("Binary Data:\n", .{}); - std.debug.print("-" ** 80 ++ "\n", .{}); + std.debug.print(minus_str ++ "\n", .{}); try benchmark("Small Binary Write (32 bytes)", 500000, benchSmallBinWrite); try benchmark("Small Binary Read (32 bytes)", 500000, benchSmallBinRead); try benchmark("Large Binary Write (1KB)", 100000, benchLargeBinWrite); @@ -908,7 +920,7 @@ fn runBenchmarks() !void { // Arrays std.debug.print("Arrays:\n", .{}); - std.debug.print("-" ** 80 ++ "\n", .{}); + std.debug.print(minus_str ++ "\n", .{}); try benchmark("Small Array Write (10 elements)", 100000, benchSmallArrayWrite); try benchmark("Small Array Read (10 elements)", 100000, benchSmallArrayRead); try benchmark("Medium Array Write (100 elements)", 50000, benchMediumArrayWrite); @@ -917,7 +929,7 @@ fn runBenchmarks() !void { // Maps std.debug.print("Maps:\n", .{}); - std.debug.print("-" ** 80 ++ "\n", .{}); + std.debug.print(minus_str ++ "\n", .{}); try benchmark("Small Map Write (10 entries)", 100000, benchSmallMapWrite); try benchmark("Small Map Read (10 entries)", 100000, benchSmallMapRead); try benchmark("Medium Map Write (50 entries)", 50000, benchMediumMapWrite); @@ -926,14 +938,14 @@ fn runBenchmarks() !void { // Extension Types std.debug.print("Extension Types:\n", .{}); - std.debug.print("-" ** 80 ++ "\n", .{}); + std.debug.print(minus_str ++ "\n", .{}); try benchmark("EXT Write (16 bytes)", 500000, benchExtWrite); try benchmark("EXT Read (16 bytes)", 500000, benchExtRead); std.debug.print("\n", .{}); // Timestamps std.debug.print("Timestamps:\n", .{}); - std.debug.print("-" ** 80 ++ "\n", .{}); + std.debug.print(minus_str ++ "\n", .{}); try benchmark("Timestamp32 Write", 1000000, benchTimestamp32Write); try benchmark("Timestamp32 Read", 1000000, benchTimestamp32Read); try benchmark("Timestamp64 Write", 1000000, benchTimestamp64Write); @@ -942,16 +954,16 @@ fn runBenchmarks() !void { // Complex Structures std.debug.print("Complex Structures:\n", .{}); - std.debug.print("-" ** 80 ++ "\n", .{}); + std.debug.print(minus_str ++ "\n", .{}); try benchmark("Nested Structure Write", 50000, benchNestedStructureWrite); try benchmark("Nested Structure Read", 50000, benchNestedStructureRead); try benchmark("Mixed Types Write", 50000, benchMixedTypesWrite); try benchmark("Mixed Types Read", 50000, benchMixedTypesRead); std.debug.print("\n", .{}); - std.debug.print("=" ** 80 ++ "\n", .{}); + std.debug.print(equal_str ++ "\n", .{}); std.debug.print("Benchmark Complete\n", .{}); - std.debug.print("=" ** 80 ++ "\n", .{}); + std.debug.print(equal_str ++ "\n", .{}); } const BenchEntry = if (is_zig_16) struct { diff --git a/src/msgpack.zig b/src/msgpack.zig index 51da2d8..51ac255 100644 --- a/src/msgpack.zig +++ b/src/msgpack.zig @@ -1047,7 +1047,7 @@ pub const Map = struct { @memcpy(new_key, key); gop.key_ptr.* = Payload{ .str = Str.init(new_key) }; - gop.value_ptr.* = Payload{ .nil = void{} }; + gop.value_ptr.* = Payload{ .nil = {} }; const key_str_ptr: *[]const u8 = @constCast(&gop.key_ptr.str.str); return .{ @@ -1159,7 +1159,7 @@ pub const Payload = union(enum) { /// get a NIL payload pub inline fn nilToPayload() Payload { return Payload{ - .nil = void{}, + .nil = {}, }; } @@ -2807,7 +2807,7 @@ pub fn PackWithLimits( /// Fast path for simple types that don't require heap allocation or complex state management inline fn readSimpleTypeFast(self: Self, marker: Markers, marker_u8: u8) !?Payload { return switch (marker) { - .NIL => Payload{ .nil = void{} }, + .NIL => Payload{ .nil = {} }, .TRUE => Payload{ .bool = true }, .FALSE => Payload{ .bool = false }, @@ -2891,7 +2891,7 @@ pub fn PackWithLimits( switch (marker) { // Simple types: construct directly .NIL => { - current_payload = Payload{ .nil = void{} }; + current_payload = Payload{ .nil = {} }; }, .TRUE, .FALSE => { const val = try self.readBoolValue(marker); diff --git a/src/test.zig b/src/test.zig index 8ffdd2c..e5c0c83 100644 --- a/src/test.zig +++ b/src/test.zig @@ -588,7 +588,7 @@ test "nil write and read" { &read_buffer, ); - try p.write(Payload{ .nil = void{} }); + try p.write(Payload{ .nil = {} }); const val = try p.read(allocator); defer val.free(allocator); } @@ -938,14 +938,14 @@ test "string size boundaries" { var p = pack.init(&write_buffer, &read_buffer); // Test fixstr (31 bytes) - const fixstr_31_data = "a" ** 31; - const fixstr_31_payload = try Payload.strToPayload(fixstr_31_data, allocator); + const fixstr_31_data: [31]u8 = @splat('a'); + const fixstr_31_payload = try Payload.strToPayload(&fixstr_31_data, allocator); defer fixstr_31_payload.free(allocator); try p.write(fixstr_31_payload); { const val = try p.read(allocator); defer val.free(allocator); - try expect(u8eql(fixstr_31_data, val.str.value())); + try expect(u8eql(&fixstr_31_data, val.str.value())); } // Reset buffers @@ -955,14 +955,14 @@ test "string size boundaries" { p = pack.init(&write_buffer, &read_buffer); // Test str8 (255 bytes) - const str8_255_data = "b" ** 255; - const str8_255_payload = try Payload.strToPayload(str8_255_data, allocator); + const str8_255_data: [255]u8 = @splat('b'); + const str8_255_payload = try Payload.strToPayload(&str8_255_data, allocator); defer str8_255_payload.free(allocator); try p.write(str8_255_payload); { const val = try p.read(allocator); defer val.free(allocator); - try expect(u8eql(str8_255_data, val.str.value())); + try expect(u8eql(&str8_255_data, val.str.value())); } } @@ -1539,15 +1539,15 @@ test "str16 and str32 write and read" { var p = pack.init(&write_buffer, &read_buffer); // Test str16 (256 characters) - const str16_data = "x" ** 256; - const str16_payload = try Payload.strToPayload(str16_data, allocator); + const str16_data: [256]u8 = @splat('x'); + const str16_payload = try Payload.strToPayload(&str16_data, allocator); defer str16_payload.free(allocator); try p.write(str16_payload); { const val = try p.read(allocator); defer val.free(allocator); try expect(val.str.value().len == 256); - try expect(u8eql(str16_data, val.str.value())); + try expect(u8eql(&str16_data, val.str.value())); } // Reset buffers for str32 test @@ -2028,8 +2028,8 @@ test "format markers verification" { p = pack.init(&write_buffer, &read_buffer); // Test str8 marker (32+ bytes string uses str8) - const test_str32 = "a" ** 32; - const str_payload = try Payload.strToPayload(test_str32, allocator); + const test_str32: [32]u8 = @splat('a'); + const str_payload = try Payload.strToPayload(&test_str32, allocator); defer str_payload.free(allocator); try p.write(str_payload); try expect(arr[0] == 0xd9); // STR8 marker @@ -2109,13 +2109,16 @@ test "fixstr boundary" { var read_buffer = fixedBufferStream(&arr); var p = pack.init(&write_buffer, &read_buffer); + const a_str: [31]u8 = @splat('a'); + const b_str: [32]u8 = @splat('b'); + // Test different fixstr lengths const test_strings = [_][]const u8{ "", // 0 bytes "a", // 1 byte "hello", // 5 bytes - "a" ** 31, // 31 bytes (max fixstr) - "b" ** 32, // 32 bytes (should use str8) + &a_str, // 31 bytes (max fixstr) + &b_str, // 32 bytes (should use str8) }; for (test_strings) |test_str| { @@ -5185,13 +5188,15 @@ test "PackerIO: string type" { var buffer: [1024]u8 = undefined; + const a_str: [100]u8 = @splat('a'); + const test_strings = [_][]const u8{ "", "a", "hello", "Hello, World!", "这是一个测试", // UTF-8 test - "a" ** 100, // Long string + &a_str, // Long string }; for (test_strings) |str| {