@@ -86,10 +86,21 @@ When using layout offsets we always return fields in declaration order within th
8686// ---------------------------------------------------------------------------
8787// Use the offsets when they are provided and the input length is sufficient.
8888rule #decodeValue(BYTES, typeInfoStructType(_, _, TYS, LAYOUT))
89- => Aggregate(variantIdx(0), #decodeStructFieldsWithOffsets(BYTES, TYS, #structOffsets(LAYOUT)))
90- requires #structOffsets(LAYOUT) =/=K .MachineSizes
91- andBool 0 <=Int #neededBytesForOffsets(TYS, #structOffsets(LAYOUT))
92- andBool lengthBytes(BYTES) >=Int #neededBytesForOffsets(TYS, #structOffsets(LAYOUT))
89+ => Aggregate(variantIdx(0), #decodeFieldsWithOffsets(BYTES, TYS, #layoutOffsets(LAYOUT)))
90+ requires #layoutOffsets(LAYOUT) =/=K .MachineSizes
91+ andBool 0 <=Int #neededBytesForOffsets(TYS, #layoutOffsets(LAYOUT))
92+ andBool lengthBytes(BYTES) >=Int #neededBytesForOffsets(TYS, #layoutOffsets(LAYOUT))
93+ [preserves-definedness]
94+
95+ rule #decodeValue(BYTES, typeInfoTupleType(.Tys, _))
96+ => Aggregate(variantIdx(0), .List)
97+ requires lengthBytes(BYTES) ==Int 0
98+
99+ rule #decodeValue(BYTES, typeInfoTupleType(TYS, LAYOUT))
100+ => Aggregate(variantIdx(0), #decodeFieldsWithOffsets(BYTES, TYS, #layoutOffsets(LAYOUT)))
101+ requires #layoutOffsets(LAYOUT) =/=K .MachineSizes
102+ andBool 0 <=Int #neededBytesForOffsets(TYS, #layoutOffsets(LAYOUT))
103+ andBool lengthBytes(BYTES) >=Int #neededBytesForOffsets(TYS, #layoutOffsets(LAYOUT))
93104 [preserves-definedness]
94105
95106// ---------------------------------------------------------------------------
@@ -100,6 +111,12 @@ syntax Int ::= #msBytes ( MachineSize ) [function, total]
100111rule #msBytes(machineSize(mirInt(NBITS))) => NBITS /Int 8 [preserves-definedness]
101112rule #msBytes(machineSize(NBITS)) => NBITS /Int 8 [owise, preserves-definedness]
102113
114+ // Extract field offsets from the struct layout when available (Arbitrary only).
115+ syntax MachineSizes ::= #layoutOffsets ( MaybeLayoutShape ) [function, total]
116+ rule #layoutOffsets(someLayoutShape(layoutShape(fieldsShapeArbitrary(mk(OFFSETS)), _, _, _, _))) => OFFSETS
117+ rule #layoutOffsets(noLayoutShape) => .MachineSizes
118+ rule #layoutOffsets(_) => .MachineSizes [owise]
119+
103120// Minimum number of input bytes required to decode all fields by the chosen offsets.
104121// Uses builtin maxInt to compute max(offset + size). The lists of types and
105122// offsets must have the same length; if not, this function returns -1 to signal
@@ -112,17 +129,17 @@ rule #neededBytesForOffsets(TY TYS, OFFSET OFFSETS)
112129rule #neededBytesForOffsets(_, _) => -1 [owise]
113130
114131// Decode each field at its byte offset and return values in declaration order.
115- syntax List ::= #decodeStructFieldsWithOffsets ( Bytes , Tys , MachineSizes ) [function, total]
116- rule #decodeStructFieldsWithOffsets (_, .Tys, _OFFSETS) => .List
117- rule #decodeStructFieldsWithOffsets (_, _TYS, .MachineSizes) => .List [owise]
118- rule #decodeStructFieldsWithOffsets (BYTES, TY TYS, OFFSET OFFSETS)
132+ syntax List ::= #decodeFieldsWithOffsets ( Bytes , Tys , MachineSizes ) [function, total]
133+ rule #decodeFieldsWithOffsets (_, .Tys, _OFFSETS) => .List
134+ rule #decodeFieldsWithOffsets (_, _TYS, .MachineSizes) => .List [owise]
135+ rule #decodeFieldsWithOffsets (BYTES, TY TYS, OFFSET OFFSETS)
119136 => ListItem(
120137 #decodeValue(
121138 substrBytes(BYTES, #msBytes(OFFSET), #msBytes(OFFSET) +Int #elemSize(lookupTy(TY))),
122139 lookupTy(TY)
123140 )
124141 )
125- #decodeStructFieldsWithOffsets (BYTES, TYS, OFFSETS)
142+ #decodeFieldsWithOffsets (BYTES, TYS, OFFSETS)
126143 requires lengthBytes(BYTES) >=Int (#msBytes(OFFSET) +Int #elemSize(lookupTy(TY)))
127144 [preserves-definedness]
128145```
@@ -176,10 +193,10 @@ Known element sizes for common types:
176193 [owise]
177194
178195 // ---- Tuples ----
179- // Without layout, approximate as sum of element sizes (ignores padding).
180- rule #elemSize(typeInfoTupleType(.Tys)) => 0
181- rule #elemSize(typeInfoTupleType(TY TYS))
182- => #elemSize(lookupTy(TY)) +Int #elemSize(typeInfoTupleType(TYS))
196+ rule #elemSize(typeInfoTupleType(_TYS, someLayoutShape(layoutShape(_, _, _, _, SIZE)))) => #msBytes(SIZE)
197+ rule #elemSize(typeInfoTupleType(.Tys, noLayoutShape )) => 0
198+ rule #elemSize(typeInfoTupleType(TY TYS, noLayoutShape ))
199+ => #elemSize(lookupTy(TY)) +Int #elemSize(typeInfoTupleType(TYS, noLayoutShape ))
183200
184201 // ---- Structs and Enums with layout ----
185202 rule #elemSize(typeInfoStructType(_, _, _, someLayoutShape(layoutShape(_, _, _, _, SIZE)))) => #msBytes(SIZE)
0 commit comments