@@ -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