Skip to content

Commit 7a30557

Browse files
committed
refactor(msgpack): optimize ext and timestamp parsing logic
- simplify and consolidate ext value reading methods - enhance timestamp detection and parsing efficiency - remove redundant code paths in extension type handling - improve code readability through inline function extraction
1 parent 5553699 commit 7a30557

File tree

1 file changed

+50
-113
lines changed

1 file changed

+50
-113
lines changed

src/msgpack.zig

Lines changed: 50 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -1539,132 +1539,69 @@ pub fn Pack(
15391539
return Payload{ .ext = EXT{ .type = ext_type, .data = ext_data } };
15401540
}
15411541

1542-
/// read ext value or timestamp if it's timestamp type (-1)
1543-
fn readExtValueOrTimestamp(self: Self, marker: Markers, allocator: Allocator) !Payload {
1544-
// Fast path: not a timestamp candidate
1545-
if (!isTimestampCandidate(marker)) {
1546-
const val = try self.readExtValue(marker, allocator);
1547-
return Payload{ .ext = val };
1548-
}
1549-
1550-
// Determine actual length
1551-
const actual_len: usize = switch (marker) {
1542+
/// Get EXT data length from marker
1543+
inline fn getExtLength(marker: Markers) usize {
1544+
return switch (marker) {
1545+
.FIXEXT1 => FIXEXT1_LEN,
1546+
.FIXEXT2 => FIXEXT2_LEN,
15521547
.FIXEXT4 => FIXEXT4_LEN,
15531548
.FIXEXT8 => FIXEXT8_LEN,
1554-
.EXT8 => blk: {
1555-
const len = try self.readV8Value();
1556-
// If not timestamp 96 length, read as regular EXT
1557-
if (len != TIMESTAMP96_DATA_LEN) {
1558-
const ext_type = try self.readI8Value();
1559-
return try self.readRegularExt(ext_type, len, allocator);
1560-
}
1561-
break :blk len;
1562-
},
1549+
.FIXEXT16 => FIXEXT16_LEN,
15631550
else => unreachable,
15641551
};
1552+
}
15651553

1566-
// Read the extension type
1567-
const ext_type = try self.readI8Value();
1568-
1569-
// Check if it's a timestamp
1570-
if (ext_type == TIMESTAMP_EXT_TYPE) {
1571-
const timestamp: Timestamp = switch (marker) {
1572-
.FIXEXT4 => try self.readTimestamp32(),
1573-
.FIXEXT8 => try self.readTimestamp64(),
1574-
.EXT8 => try self.readTimestamp96(),
1575-
else => unreachable,
1576-
};
1577-
return Payload{ .timestamp = timestamp };
1554+
/// Read and validate EXT8 length for timestamp detection
1555+
fn readExt8Length(self: Self) !struct { len: usize, is_timestamp_candidate: bool } {
1556+
const len = try self.readV8Value();
1557+
// Only timestamp 96 format uses 12 bytes in EXT8
1558+
if (len != TIMESTAMP96_DATA_LEN) {
1559+
return .{ .len = len, .is_timestamp_candidate = false };
15781560
}
1561+
return .{ .len = len, .is_timestamp_candidate = true };
1562+
}
15791563

1580-
// Not a timestamp, read as regular EXT
1581-
return try self.readRegularExt(ext_type, actual_len, allocator);
1564+
/// Read timestamp payload based on marker
1565+
inline fn readTimestampPayload(self: Self, marker: Markers) !Payload {
1566+
const timestamp: Timestamp = switch (marker) {
1567+
.FIXEXT4 => try self.readTimestamp32(),
1568+
.FIXEXT8 => try self.readTimestamp64(),
1569+
.EXT8 => try self.readTimestamp96(),
1570+
else => unreachable,
1571+
};
1572+
return Payload{ .timestamp = timestamp };
15821573
}
15831574

1584-
/// try to read timestamp from ext data, return error if not timestamp
1585-
fn tryReadTimestamp(self: Self, marker: Markers, _: Allocator) !Timestamp {
1586-
switch (marker) {
1587-
.FIXEXT4 => {
1588-
// timestamp 32 format
1589-
const ext_type = try self.readI8Value();
1590-
if (ext_type != TIMESTAMP_EXT_TYPE) {
1591-
return MsgPackError.InvalidType;
1592-
}
1593-
const seconds = try self.readU32Value();
1594-
return Timestamp.new(@intCast(seconds), 0);
1595-
},
1596-
.FIXEXT8 => {
1597-
// timestamp 64 format
1598-
const ext_type = try self.readI8Value();
1599-
if (ext_type != TIMESTAMP_EXT_TYPE) {
1600-
return MsgPackError.InvalidType;
1601-
}
1602-
const data64 = try self.readU64Value();
1603-
const nanoseconds: u32 = @intCast(data64 >> TIMESTAMP64_SECONDS_BITS);
1604-
const seconds: i64 = @intCast(data64 & TIMESTAMP64_SECONDS_MASK);
1605-
return Timestamp.new(seconds, nanoseconds);
1606-
},
1607-
.EXT8 => {
1608-
// timestamp 96 format (length should be 12)
1609-
const len = try self.readV8Value();
1610-
if (len != TIMESTAMP96_DATA_LEN) {
1611-
return MsgPackError.InvalidType;
1612-
}
1613-
const ext_type = try self.readI8Value();
1614-
if (ext_type != TIMESTAMP_EXT_TYPE) {
1615-
return MsgPackError.InvalidType;
1616-
}
1617-
const nanoseconds = try self.readU32Value();
1618-
const seconds = try self.readI64Value();
1619-
return Timestamp.new(seconds, nanoseconds);
1620-
},
1621-
else => {
1622-
return MsgPackError.InvalidType;
1623-
},
1575+
/// read ext value or timestamp if it's timestamp type (-1)
1576+
fn readExtValueOrTimestamp(self: Self, marker: Markers, allocator: Allocator) !Payload {
1577+
// Fast path: not a timestamp candidate
1578+
if (!isTimestampCandidate(marker)) {
1579+
const val = try self.readExtValue(marker, allocator);
1580+
return Payload{ .ext = val };
16241581
}
1625-
}
16261582

1627-
/// read timestamp from ext data
1628-
fn readTimestamp(self: Self, marker: Markers, _: Allocator) !Timestamp {
1629-
switch (marker) {
1630-
.FIXEXT4 => {
1631-
// timestamp 32 format
1632-
const ext_type = try self.readI8Value();
1633-
if (ext_type != TIMESTAMP_EXT_TYPE) {
1634-
return MsgPackError.InvalidType;
1635-
}
1636-
const seconds = try self.readU32Value();
1637-
return Timestamp.new(@intCast(seconds), 0);
1638-
},
1639-
.FIXEXT8 => {
1640-
// timestamp 64 format
1583+
// Handle EXT8 special case (need to read length first)
1584+
if (marker == .EXT8) {
1585+
const len_info = try self.readExt8Length();
1586+
1587+
// If not timestamp length, read as regular EXT
1588+
if (!len_info.is_timestamp_candidate) {
16411589
const ext_type = try self.readI8Value();
1642-
if (ext_type != TIMESTAMP_EXT_TYPE) {
1643-
return MsgPackError.InvalidType;
1644-
}
1645-
const data64 = try self.readU64Value();
1646-
const nanoseconds: u32 = @intCast(data64 >> TIMESTAMP64_SECONDS_BITS);
1647-
const seconds: i64 = @intCast(data64 & TIMESTAMP64_SECONDS_MASK);
1648-
return Timestamp.new(seconds, nanoseconds);
1649-
},
1650-
.EXT8 => {
1651-
// timestamp 96 format (length should be 12)
1652-
const len = try self.readV8Value();
1653-
if (len != TIMESTAMP96_DATA_LEN) {
1654-
return MsgPackError.InvalidType;
1655-
}
1656-
const ext_type = try self.readI8Value();
1657-
if (ext_type != TIMESTAMP_EXT_TYPE) {
1658-
return MsgPackError.InvalidType;
1659-
}
1660-
const nanoseconds = try self.readU32Value();
1661-
const seconds = try self.readI64Value();
1662-
return Timestamp.new(seconds, nanoseconds);
1663-
},
1664-
else => {
1665-
return MsgPackError.InvalidType;
1666-
},
1590+
return try self.readRegularExt(ext_type, len_info.len, allocator);
1591+
}
16671592
}
1593+
1594+
// Read extension type to determine if it's a timestamp
1595+
const ext_type = try self.readI8Value();
1596+
1597+
// Timestamp type: read timestamp data
1598+
if (ext_type == TIMESTAMP_EXT_TYPE) {
1599+
return try self.readTimestampPayload(marker);
1600+
}
1601+
1602+
// Regular EXT: read remaining data
1603+
const actual_len = if (marker == .EXT8) TIMESTAMP96_DATA_LEN else getExtLength(marker);
1604+
return try self.readRegularExt(ext_type, actual_len, allocator);
16681605
}
16691606

16701607
fn readExtValue(self: Self, marker: Markers, allocator: Allocator) !EXT {

0 commit comments

Comments
 (0)