tiny.trace.store.format.codec
Defined in store.format.
API (5)
Actions
Public operations.
Types and contracts
Public types and contracts.
Values and defaults
Public values and defaults.
Source
Source: lib/trace/src/store/format/codec.zig
zig
const std = @import("std");const event = @import("../../root.zig").event;pub const header_bytes: usize = 92;pub const Error = error{ CapacityOverflow, InvalidEvent, OutputTooSmall,};const magic = [_]u8{ 't', 't', 'm', 'e' };const version: u8 = 1;const operation_flag: u8 = 1 << 0;const label_flag: u8 = 1 << 1;const data_flag: u8 = 1 << 2;const known_flags = operation_flag | label_flag | data_flag;const version_offset: usize = 4;const kind_offset: usize = 5;const flags_offset: usize = 6;const reserved_offset: usize = 7;const epoch_offset: usize = 8;const thread_offset: usize = 16;const sequence_offset: usize = 20;const function_offset: usize = 28;const site_offset: usize = 36;const stack_map_offset: usize = 44;const object_offset: usize = 52;const size_offset: usize = 60;const alignment_offset: usize = 68;const status_offset: usize = 72;const operation_length_offset: usize = 80;const label_length_offset: usize = 84;const data_length_offset: usize = 88;pub fn encodedSize(item: event.Event) Error!usize { var total = header_bytes; inline for (.{ item.operation, item.label, item.data }) |value| { if (value) |bytes| { if (bytes.len > std.math.maxInt(u32)) return error.CapacityOverflow; total = std.math.add(usize, total, bytes.len) catch return error.CapacityOverflow; } } return total;}pub fn encode(target: []u8, item: event.Event) Error![]u8 { const needed = try encodedSize(item); if (target.len < needed) return error.OutputTooSmall; const output = target[0..needed]; @memset(output, 0); @memcpy(output[0..magic.len], &magic); output[version_offset] = version; output[kind_offset] = @backingInt(item.kind); var flags: u8 = 0; if (item.operation != null) flags |= operation_flag; if (item.label != null) flags |= label_flag; if (item.data != null) flags |= data_flag; output[flags_offset] = flags; output[reserved_offset] = 0; std.mem.writeInt(u64, output[epoch_offset..][0..8], item.timepoint.epoch, .big); std.mem.writeInt(u32, output[thread_offset..][0..4], item.timepoint.thread_id, .big); std.mem.writeInt(u64, output[sequence_offset..][0..8], item.timepoint.seq, .big); std.mem.writeInt(u64, output[function_offset..][0..8], item.function_id, .big); std.mem.writeInt(u64, output[site_offset..][0..8], item.site_id, .big); std.mem.writeInt(u64, output[stack_map_offset..][0..8], item.stack_map_id, .big); std.mem.writeInt(u64, output[object_offset..][0..8], item.object_id, .big); std.mem.writeInt(u64, output[size_offset..][0..8], item.size, .big); std.mem.writeInt(u32, output[alignment_offset..][0..4], item.alignment, .big); std.mem.writeInt(i64, output[status_offset..][0..8], item.status, .big); writeLength(output, operation_length_offset, item.operation); writeLength(output, label_length_offset, item.label); writeLength(output, data_length_offset, item.data); var offset = header_bytes; inline for (.{ item.operation, item.label, item.data }) |value| { if (value) |bytes| { @memcpy(output[offset..][0..bytes.len], bytes); offset += bytes.len; } } std.debug.assert(offset == output.len); return output;}pub fn decode(bytes: []u8) Error!event.Event { if (bytes.len < header_bytes) return error.InvalidEvent; if (!std.mem.eql(u8, bytes[0..magic.len], &magic)) return error.InvalidEvent; if (bytes[version_offset] != version) return error.InvalidEvent; if (bytes[flags_offset] & ~known_flags != 0 or bytes[reserved_offset] != 0) return error.InvalidEvent; const kind = std.enums.fromInt(event.EventKind, bytes[kind_offset]) orelse return error.InvalidEvent; const operation_length = readLength(bytes, operation_length_offset); const label_length = readLength(bytes, label_length_offset); const data_length = readLength(bytes, data_length_offset); try validateOptional(bytes[flags_offset], operation_flag, operation_length); try validateOptional(bytes[flags_offset], label_flag, label_length); try validateOptional(bytes[flags_offset], data_flag, data_length); const operation_end = std.math.add(usize, header_bytes, operation_length) catch return error.InvalidEvent; const label_end = std.math.add(usize, operation_end, label_length) catch return error.InvalidEvent; const data_end = std.math.add(usize, label_end, data_length) catch return error.InvalidEvent; if (data_end != bytes.len) return error.InvalidEvent; return .{ .kind = kind, .timepoint = .{ .epoch = std.mem.readInt(u64, bytes[epoch_offset..][0..8], .big), .thread_id = std.mem.readInt(u32, bytes[thread_offset..][0..4], .big), .seq = std.mem.readInt(u64, bytes[sequence_offset..][0..8], .big), }, .function_id = std.mem.readInt(u64, bytes[function_offset..][0..8], .big), .site_id = std.mem.readInt(u64, bytes[site_offset..][0..8], .big), .stack_map_id = std.mem.readInt(u64, bytes[stack_map_offset..][0..8], .big), .object_id = std.mem.readInt(u64, bytes[object_offset..][0..8], .big), .size = std.mem.readInt(u64, bytes[size_offset..][0..8], .big), .alignment = std.mem.readInt(u32, bytes[alignment_offset..][0..4], .big), .status = std.mem.readInt(i64, bytes[status_offset..][0..8], .big), .operation = if (bytes[flags_offset] & operation_flag != 0) bytes[header_bytes..operation_end] else null, .label = if (bytes[flags_offset] & label_flag != 0) bytes[operation_end..label_end] else null, .data = if (bytes[flags_offset] & data_flag != 0) bytes[label_end..data_end] else null, };}fn writeLength(target: []u8, offset: usize, value: ?[]const u8) void { std.mem.writeInt(u32, target[offset..][0..4], if (value) |bytes| @intCast(bytes.len) else 0, .big);}fn readLength(bytes: []const u8, offset: usize) usize { return std.mem.readInt(u32, bytes[offset..][0..4], .big);}fn validateOptional(flags: u8, flag: u8, length: usize) Error!void { if (flags & flag == 0 and length != 0) return error.InvalidEvent;}test "binary event codec preserves every replay field" { const original = event.Event{ .kind = .boundary, .timepoint = .{ .epoch = std.math.maxInt(u64), .thread_id = std.math.maxInt(u32), .seq = std.math.maxInt(u64) - 1, }, .function_id = std.math.maxInt(u64), .site_id = 2, .stack_map_id = 3, .object_id = 4, .size = std.math.maxInt(u64), .alignment = std.math.maxInt(u32), .status = std.math.minInt(i64), .operation = "env.TEST", .label = "", .data = "value\x00bytes", }; var storage: [256]u8 = undefined; const encoded = try encode(&storage, original); const parsed = try decode(encoded); try std.testing.expect(original.eqlForReplay(parsed));}test "binary event codec rejects truncation and noncanonical optionals" { const original = event.Event.user(.{}, "label", "payload"); var storage: [256]u8 = undefined; const encoded = try encode(&storage, original); try std.testing.expectError(error.InvalidEvent, decode(encoded[0 .. encoded.len - 1])); encoded[flags_offset] &= ~label_flag; try std.testing.expectError(error.InvalidEvent, decode(encoded));}Source: lib/trace/src/store/format/root.zig:2
zig
pub const codec = @import("codec.zig");Audit
| Definitions | 6 |
|---|---|
| Public names | 6 |
| Members | 3 |
| Version | 26.7.0 |
| Revision | daab053ee433 |