weftcodec 1.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- weftcodec/__init__.py +62 -0
- weftcodec/__main__.py +6 -0
- weftcodec/ai_modes.py +3360 -0
- weftcodec/cli.py +252 -0
- weftcodec/crc32c.py +33 -0
- weftcodec/dcp.py +2108 -0
- weftcodec/dependency.py +224 -0
- weftcodec/errors.py +119 -0
- weftcodec/frame.py +455 -0
- weftcodec/hashing.py +56 -0
- weftcodec/huffman.py +212 -0
- weftcodec/identity.py +141 -0
- weftcodec/limits.py +58 -0
- weftcodec/modes.py +718 -0
- weftcodec/orbax.py +1734 -0
- weftcodec/service.py +959 -0
- weftcodec/torch.py +94 -0
- weftcodec/varint.py +88 -0
- weftcodec/wcb.py +310 -0
- weftcodec-1.2.0.dist-info/METADATA +257 -0
- weftcodec-1.2.0.dist-info/RECORD +24 -0
- weftcodec-1.2.0.dist-info/WHEEL +5 -0
- weftcodec-1.2.0.dist-info/entry_points.txt +2 -0
- weftcodec-1.2.0.dist-info/top_level.txt +1 -0
weftcodec/frame.py
ADDED
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
"""WFT1 frame header/table parsing and strict structural validation.
|
|
2
|
+
|
|
3
|
+
Layout (WEFTCODEC-FORMAT §2)::
|
|
4
|
+
|
|
5
|
+
header (96 bytes) || dependency table || chunk table || body || trailer (4)
|
|
6
|
+
|
|
7
|
+
This module parses and validates structure only; payload modes live in
|
|
8
|
+
:mod:`weftcodec.modes`.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from dataclasses import dataclass
|
|
14
|
+
|
|
15
|
+
from .crc32c import crc32c
|
|
16
|
+
from .errors import (
|
|
17
|
+
Corrupt,
|
|
18
|
+
Malformed,
|
|
19
|
+
UnsupportedFeature,
|
|
20
|
+
UnsupportedMode,
|
|
21
|
+
UnsupportedVersion,
|
|
22
|
+
LimitExceeded,
|
|
23
|
+
)
|
|
24
|
+
from .limits import Limits
|
|
25
|
+
|
|
26
|
+
MAGIC = b"WFT1"
|
|
27
|
+
HEADER_LEN = 96
|
|
28
|
+
TRAILER_LEN = 4
|
|
29
|
+
DEP_ENTRY_LEN = 48
|
|
30
|
+
CHUNK_ENTRY_LEN = 48
|
|
31
|
+
HASH_LEN = 32
|
|
32
|
+
|
|
33
|
+
FORMAT_MAJOR = 1
|
|
34
|
+
FORMAT_MINOR = 0
|
|
35
|
+
|
|
36
|
+
DOMAIN_PAYLOAD = 0
|
|
37
|
+
DOMAIN_STRUCTURED = 1
|
|
38
|
+
|
|
39
|
+
DEP_DOMAIN_PAYLOAD = 0
|
|
40
|
+
DEP_DOMAIN_STRUCTURED = 1
|
|
41
|
+
DEP_DOMAIN_DICTIONARY = 2
|
|
42
|
+
|
|
43
|
+
DEP_FLAG_REQUIRED = 0x01
|
|
44
|
+
|
|
45
|
+
FLAG_CHUNKED = 0x0001
|
|
46
|
+
FLAG_SELF_CONTAINED = 0x0002
|
|
47
|
+
FLAG_DICT_RAW = 0x0004
|
|
48
|
+
FLAG_ORIGINAL_HASH = 0x0008
|
|
49
|
+
|
|
50
|
+
FEATURE_DEPENDENCIES = 0x0001
|
|
51
|
+
FEATURE_CHUNK_HASHES = 0x0002
|
|
52
|
+
|
|
53
|
+
MODE_NAMES = {
|
|
54
|
+
0: "raw",
|
|
55
|
+
1: "zstd",
|
|
56
|
+
2: "reference",
|
|
57
|
+
3: "delta",
|
|
58
|
+
4: "dictionary",
|
|
59
|
+
5: "structured",
|
|
60
|
+
6: "tensor",
|
|
61
|
+
7: "tokens",
|
|
62
|
+
8: "quantized_tensor",
|
|
63
|
+
9: "float_tensor",
|
|
64
|
+
10: "tensor_sharded",
|
|
65
|
+
11: "weight_delta",
|
|
66
|
+
12: "kv_cache",
|
|
67
|
+
13: "activation_stream",
|
|
68
|
+
14: "semantic_delta",
|
|
69
|
+
15: "tensor_tiled",
|
|
70
|
+
16: "sparse_delta",
|
|
71
|
+
17: "float_tiled",
|
|
72
|
+
18: "float_tiled_streams",
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
#: Modes this Python reader can actually materialize plaintext for.
|
|
76
|
+
IMPLEMENTED_MODES = frozenset(MODE_NAMES)
|
|
77
|
+
|
|
78
|
+
#: Modes whose wire value is allocated but not implemented here.
|
|
79
|
+
UNIMPLEMENTED_MODES = frozenset()
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@dataclass(frozen=True)
|
|
83
|
+
class Dependency:
|
|
84
|
+
hash: bytes
|
|
85
|
+
decoded_len: int
|
|
86
|
+
dep_domain: int
|
|
87
|
+
dep_flags: int
|
|
88
|
+
codec_hint: int
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@dataclass(frozen=True)
|
|
92
|
+
class ChunkEntry:
|
|
93
|
+
encoded_off: int
|
|
94
|
+
encoded_len: int
|
|
95
|
+
decoded_len: int
|
|
96
|
+
hash: bytes
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
@dataclass(frozen=True)
|
|
100
|
+
class FrameHeader:
|
|
101
|
+
format_major: int
|
|
102
|
+
format_minor: int
|
|
103
|
+
domain: int
|
|
104
|
+
mode: int
|
|
105
|
+
flags: int
|
|
106
|
+
level: int
|
|
107
|
+
decoded_len: int
|
|
108
|
+
body_len: int
|
|
109
|
+
dep_count: int
|
|
110
|
+
chunk_count: int
|
|
111
|
+
features: int
|
|
112
|
+
content_hash: bytes
|
|
113
|
+
table_len: int
|
|
114
|
+
|
|
115
|
+
@property
|
|
116
|
+
def mode_name(self) -> str:
|
|
117
|
+
return MODE_NAMES.get(self.mode, "unknown")
|
|
118
|
+
|
|
119
|
+
@property
|
|
120
|
+
def is_chunked(self) -> bool:
|
|
121
|
+
return bool(self.flags & FLAG_CHUNKED)
|
|
122
|
+
|
|
123
|
+
def flag_names(self) -> "list[str]":
|
|
124
|
+
names = []
|
|
125
|
+
if self.flags & FLAG_CHUNKED:
|
|
126
|
+
names.append("CHUNKED")
|
|
127
|
+
if self.flags & FLAG_SELF_CONTAINED:
|
|
128
|
+
names.append("SELF_CONTAINED")
|
|
129
|
+
if self.flags & FLAG_DICT_RAW:
|
|
130
|
+
names.append("DICT_RAW")
|
|
131
|
+
if self.flags & FLAG_ORIGINAL_HASH:
|
|
132
|
+
names.append("ORIGINAL_HASH")
|
|
133
|
+
return names
|
|
134
|
+
|
|
135
|
+
def feature_names(self) -> "list[str]":
|
|
136
|
+
names = []
|
|
137
|
+
if self.features & FEATURE_DEPENDENCIES:
|
|
138
|
+
names.append("DEPENDENCIES")
|
|
139
|
+
if self.features & FEATURE_CHUNK_HASHES:
|
|
140
|
+
names.append("CHUNK_HASHES")
|
|
141
|
+
return names
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
@dataclass(frozen=True)
|
|
145
|
+
class Frame:
|
|
146
|
+
header: FrameHeader
|
|
147
|
+
dependencies: "tuple[Dependency, ...]"
|
|
148
|
+
chunks: "tuple[ChunkEntry, ...]"
|
|
149
|
+
body: bytes
|
|
150
|
+
raw: bytes
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def _le_u16(data: bytes, offset: int) -> int:
|
|
154
|
+
return int.from_bytes(data[offset : offset + 2], "little")
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def _le_u32(data: bytes, offset: int) -> int:
|
|
158
|
+
return int.from_bytes(data[offset : offset + 4], "little")
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def _le_u64(data: bytes, offset: int) -> int:
|
|
162
|
+
return int.from_bytes(data[offset : offset + 8], "little")
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def _check_len(length: int, maximum: int, what: str) -> None:
|
|
166
|
+
if length > maximum:
|
|
167
|
+
raise LimitExceeded("%s length %d exceeds limit %d" % (what, length, maximum))
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def mode_from_u8(value: int) -> int:
|
|
171
|
+
if value in MODE_NAMES:
|
|
172
|
+
return value
|
|
173
|
+
if 17 <= value <= 127:
|
|
174
|
+
raise UnsupportedMode("reserved mode %d is not defined in v1" % value)
|
|
175
|
+
raise UnsupportedMode("experimental mode %d must not be persisted" % value)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def parse(data: bytes, limits: "Limits | None" = None) -> Frame:
|
|
179
|
+
"""Parse and fully validate a frame's structure."""
|
|
180
|
+
limits = limits or Limits()
|
|
181
|
+
if len(data) < HEADER_LEN + TRAILER_LEN:
|
|
182
|
+
raise Malformed(
|
|
183
|
+
"frame length %d is below the minimum %d"
|
|
184
|
+
% (len(data), HEADER_LEN + TRAILER_LEN)
|
|
185
|
+
)
|
|
186
|
+
_check_len(len(data), limits.max_frame_bytes, "frame")
|
|
187
|
+
|
|
188
|
+
if data[0:4] != MAGIC:
|
|
189
|
+
raise Malformed("bad frame magic (expected WFT1)")
|
|
190
|
+
format_major = data[4]
|
|
191
|
+
format_minor = data[5]
|
|
192
|
+
if format_major != FORMAT_MAJOR:
|
|
193
|
+
raise UnsupportedVersion("unsupported format major %d" % format_major)
|
|
194
|
+
if format_minor != FORMAT_MINOR:
|
|
195
|
+
raise UnsupportedVersion("unsupported format minor %d" % format_minor)
|
|
196
|
+
|
|
197
|
+
# The header checksum is verified before any length field is trusted.
|
|
198
|
+
stored_header_crc = _le_u32(data, 72)
|
|
199
|
+
if crc32c(data[0:72] + data[76:96]) != stored_header_crc:
|
|
200
|
+
raise Corrupt("header CRC32C mismatch")
|
|
201
|
+
|
|
202
|
+
domain = data[6]
|
|
203
|
+
mode = mode_from_u8(data[7])
|
|
204
|
+
flags = _le_u16(data, 8)
|
|
205
|
+
level = _le_u16(data, 10)
|
|
206
|
+
decoded_len = _le_u64(data, 12)
|
|
207
|
+
body_len = _le_u64(data, 20)
|
|
208
|
+
dep_count = _le_u32(data, 28)
|
|
209
|
+
chunk_count = _le_u32(data, 32)
|
|
210
|
+
feature_bits = _le_u16(data, 36)
|
|
211
|
+
reserved0 = _le_u16(data, 38)
|
|
212
|
+
content_hash = bytes(data[40:72])
|
|
213
|
+
table_len = _le_u64(data, 76)
|
|
214
|
+
reserved1 = _le_u32(data, 84)
|
|
215
|
+
reserved2 = _le_u64(data, 88)
|
|
216
|
+
|
|
217
|
+
if reserved0 != 0 or reserved1 != 0 or reserved2 != 0:
|
|
218
|
+
raise Malformed("reserved header fields must be zero")
|
|
219
|
+
if domain > DOMAIN_STRUCTURED:
|
|
220
|
+
raise Malformed("invalid domain value %d" % domain)
|
|
221
|
+
if flags & ~(FLAG_CHUNKED | FLAG_SELF_CONTAINED | FLAG_DICT_RAW | FLAG_ORIGINAL_HASH):
|
|
222
|
+
raise UnsupportedFeature("unknown critical flag bits 0x%04x" % (flags & ~0x000F))
|
|
223
|
+
if flags & FLAG_ORIGINAL_HASH:
|
|
224
|
+
raise UnsupportedFeature("ORIGINAL_HASH flag is reserved in v1")
|
|
225
|
+
if flags & FLAG_SELF_CONTAINED:
|
|
226
|
+
raise UnsupportedFeature("SELF_CONTAINED is reserved and not produced in v1")
|
|
227
|
+
if feature_bits & ~(FEATURE_DEPENDENCIES | FEATURE_CHUNK_HASHES):
|
|
228
|
+
raise UnsupportedFeature(
|
|
229
|
+
"unknown critical feature bits 0x%04x" % (feature_bits & ~0x0003)
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
_check_len(decoded_len, limits.max_decoded_bytes, "decoded data")
|
|
233
|
+
_check_len(dep_count, limits.max_dependency_count, "dependency count")
|
|
234
|
+
_check_len(chunk_count, limits.max_chunks, "chunk count")
|
|
235
|
+
|
|
236
|
+
expected_table_len = dep_count * DEP_ENTRY_LEN + chunk_count * CHUNK_ENTRY_LEN
|
|
237
|
+
if table_len != expected_table_len:
|
|
238
|
+
raise Malformed(
|
|
239
|
+
"table_len %d does not match %d dependencies and %d chunks"
|
|
240
|
+
% (table_len, dep_count, chunk_count)
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
expected_total = HEADER_LEN + table_len + body_len + TRAILER_LEN
|
|
244
|
+
if expected_total != len(data):
|
|
245
|
+
raise Malformed(
|
|
246
|
+
"frame length %d does not match header-derived length %d"
|
|
247
|
+
% (len(data), expected_total)
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
chunked = bool(flags & FLAG_CHUNKED)
|
|
251
|
+
if chunked:
|
|
252
|
+
if chunk_count == 0:
|
|
253
|
+
raise Malformed("CHUNKED set with an empty chunk table")
|
|
254
|
+
if not feature_bits & FEATURE_CHUNK_HASHES:
|
|
255
|
+
raise Malformed("CHUNKED set without the CHUNK_HASHES feature")
|
|
256
|
+
else:
|
|
257
|
+
if chunk_count != 0:
|
|
258
|
+
raise Malformed("chunk table present without the CHUNKED flag")
|
|
259
|
+
if feature_bits & FEATURE_CHUNK_HASHES:
|
|
260
|
+
raise Malformed("CHUNK_HASHES set without the CHUNKED flag")
|
|
261
|
+
if dep_count > 0 and not feature_bits & FEATURE_DEPENDENCIES:
|
|
262
|
+
raise Malformed("dependency table present without the DEPENDENCIES feature")
|
|
263
|
+
|
|
264
|
+
body_start = HEADER_LEN + table_len
|
|
265
|
+
body_end = body_start + body_len
|
|
266
|
+
body = bytes(data[body_start:body_end])
|
|
267
|
+
|
|
268
|
+
trailer_at = len(data) - TRAILER_LEN
|
|
269
|
+
stored_trailer_crc = _le_u32(data, trailer_at)
|
|
270
|
+
if crc32c(data[:trailer_at]) != stored_trailer_crc:
|
|
271
|
+
raise Corrupt("frame trailer CRC32C mismatch")
|
|
272
|
+
|
|
273
|
+
dependencies = []
|
|
274
|
+
for index in range(dep_count):
|
|
275
|
+
offset = HEADER_LEN + index * DEP_ENTRY_LEN
|
|
276
|
+
dep_hash = bytes(data[offset : offset + HASH_LEN])
|
|
277
|
+
dep_len = _le_u64(data, offset + 32)
|
|
278
|
+
dep_domain = data[offset + 40]
|
|
279
|
+
dep_flags = data[offset + 41]
|
|
280
|
+
reserved = _le_u16(data, offset + 42)
|
|
281
|
+
codec_hint = _le_u32(data, offset + 44)
|
|
282
|
+
if dep_flags & ~DEP_FLAG_REQUIRED:
|
|
283
|
+
raise Malformed("dependency %d has unknown flag bits" % index)
|
|
284
|
+
if not dep_flags & DEP_FLAG_REQUIRED:
|
|
285
|
+
raise Malformed("dependency %d does not set REQUIRED" % index)
|
|
286
|
+
if reserved != 0:
|
|
287
|
+
raise Malformed("dependency %d reserved field must be zero" % index)
|
|
288
|
+
if dep_domain > DEP_DOMAIN_DICTIONARY:
|
|
289
|
+
raise Malformed("dependency %d has invalid domain %d" % (index, dep_domain))
|
|
290
|
+
_check_len(dep_len, limits.max_decoded_bytes, "dependency decoded data")
|
|
291
|
+
dependencies.append(
|
|
292
|
+
Dependency(dep_hash, dep_len, dep_domain, dep_flags, codec_hint)
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
chunk_table_start = HEADER_LEN + dep_count * DEP_ENTRY_LEN
|
|
296
|
+
chunks = []
|
|
297
|
+
for index in range(chunk_count):
|
|
298
|
+
offset = chunk_table_start + index * CHUNK_ENTRY_LEN
|
|
299
|
+
chunks.append(
|
|
300
|
+
ChunkEntry(
|
|
301
|
+
encoded_off=_le_u64(data, offset),
|
|
302
|
+
encoded_len=_le_u32(data, offset + 8),
|
|
303
|
+
decoded_len=_le_u32(data, offset + 12),
|
|
304
|
+
hash=bytes(data[offset + 16 : offset + 48]),
|
|
305
|
+
)
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
if chunked:
|
|
309
|
+
next_offset = 0
|
|
310
|
+
decoded_sum = 0
|
|
311
|
+
for index, chunk in enumerate(chunks):
|
|
312
|
+
if chunk.encoded_off != next_offset:
|
|
313
|
+
raise Malformed(
|
|
314
|
+
"chunk %d starts at %d but expected %d (gap or overlap)"
|
|
315
|
+
% (index, chunk.encoded_off, next_offset)
|
|
316
|
+
)
|
|
317
|
+
if chunk.encoded_len == 0:
|
|
318
|
+
raise Malformed("chunk %d has zero encoded length" % index)
|
|
319
|
+
next_offset += chunk.encoded_len
|
|
320
|
+
decoded_sum += chunk.decoded_len
|
|
321
|
+
if next_offset != body_len:
|
|
322
|
+
raise Malformed(
|
|
323
|
+
"chunk extents end at %d but body_len is %d" % (next_offset, body_len)
|
|
324
|
+
)
|
|
325
|
+
if decoded_sum != decoded_len:
|
|
326
|
+
raise Malformed(
|
|
327
|
+
"chunk decoded lengths sum to %d but decoded_len is %d"
|
|
328
|
+
% (decoded_sum, decoded_len)
|
|
329
|
+
)
|
|
330
|
+
|
|
331
|
+
header = FrameHeader(
|
|
332
|
+
format_major=format_major,
|
|
333
|
+
format_minor=format_minor,
|
|
334
|
+
domain=domain,
|
|
335
|
+
mode=mode,
|
|
336
|
+
flags=flags,
|
|
337
|
+
level=level,
|
|
338
|
+
decoded_len=decoded_len,
|
|
339
|
+
body_len=body_len,
|
|
340
|
+
dep_count=dep_count,
|
|
341
|
+
chunk_count=chunk_count,
|
|
342
|
+
features=feature_bits,
|
|
343
|
+
content_hash=content_hash,
|
|
344
|
+
table_len=table_len,
|
|
345
|
+
)
|
|
346
|
+
_validate_mode_rules(header, dependencies, limits)
|
|
347
|
+
return Frame(header, tuple(dependencies), tuple(chunks), body, bytes(data))
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
def _validate_mode_rules(
|
|
351
|
+
header: FrameHeader, dependencies: "list[Dependency]", limits: Limits
|
|
352
|
+
) -> None:
|
|
353
|
+
mode = header.mode
|
|
354
|
+
dict_flag = bool(header.flags & FLAG_DICT_RAW)
|
|
355
|
+
|
|
356
|
+
def payload_domain(what: str) -> None:
|
|
357
|
+
if header.domain != DOMAIN_PAYLOAD:
|
|
358
|
+
raise Malformed("%s frame must use the payload domain" % what)
|
|
359
|
+
|
|
360
|
+
def no_dict(what: str) -> None:
|
|
361
|
+
if dict_flag:
|
|
362
|
+
raise Malformed("DICT_RAW is only valid for DICTIONARY (%s)" % what)
|
|
363
|
+
|
|
364
|
+
if mode == 0: # RAW
|
|
365
|
+
payload_domain("RAW")
|
|
366
|
+
no_dict("RAW")
|
|
367
|
+
if header.dep_count != 0:
|
|
368
|
+
raise Malformed("RAW frame must not have dependencies")
|
|
369
|
+
if header.body_len != header.decoded_len:
|
|
370
|
+
raise Malformed("RAW body_len must equal decoded_len")
|
|
371
|
+
elif mode == 1: # ZSTD
|
|
372
|
+
payload_domain("ZSTD")
|
|
373
|
+
no_dict("ZSTD")
|
|
374
|
+
if header.dep_count != 0:
|
|
375
|
+
raise Malformed("ZSTD frame must not have dependencies in v1")
|
|
376
|
+
elif mode == 2: # REFERENCE
|
|
377
|
+
payload_domain("REFERENCE")
|
|
378
|
+
no_dict("REFERENCE")
|
|
379
|
+
if header.body_len != 0:
|
|
380
|
+
raise Malformed("REFERENCE body must be empty")
|
|
381
|
+
if header.dep_count != 1:
|
|
382
|
+
raise Malformed("REFERENCE requires exactly one dependency")
|
|
383
|
+
if header.chunk_count != 0:
|
|
384
|
+
raise Malformed("REFERENCE must not be chunked")
|
|
385
|
+
if header.decoded_len != dependencies[0].decoded_len:
|
|
386
|
+
raise Malformed(
|
|
387
|
+
"REFERENCE decoded_len must equal dependency decoded_len"
|
|
388
|
+
)
|
|
389
|
+
elif mode == 3: # DELTA
|
|
390
|
+
payload_domain("DELTA")
|
|
391
|
+
no_dict("DELTA")
|
|
392
|
+
if header.dep_count != 1:
|
|
393
|
+
raise Malformed("DELTA requires exactly one dependency")
|
|
394
|
+
if header.chunk_count != 0:
|
|
395
|
+
raise Malformed("DELTA must not be chunked")
|
|
396
|
+
elif mode == 4: # DICTIONARY
|
|
397
|
+
payload_domain("DICTIONARY")
|
|
398
|
+
if not dict_flag:
|
|
399
|
+
raise Malformed("DICTIONARY requires the DICT_RAW flag")
|
|
400
|
+
if header.dep_count != 1:
|
|
401
|
+
raise Malformed("DICTIONARY requires exactly one dependency")
|
|
402
|
+
if dependencies[0].dep_domain != DEP_DOMAIN_DICTIONARY:
|
|
403
|
+
raise Malformed(
|
|
404
|
+
"DICTIONARY dependency must use dep_domain 2 (dictionary bytes)"
|
|
405
|
+
)
|
|
406
|
+
if header.chunk_count != 0:
|
|
407
|
+
raise Malformed("DICTIONARY must not be chunked")
|
|
408
|
+
_check_len(
|
|
409
|
+
dependencies[0].decoded_len,
|
|
410
|
+
limits.max_dictionary_bytes,
|
|
411
|
+
"dictionary",
|
|
412
|
+
)
|
|
413
|
+
elif mode == 5: # STRUCTURED
|
|
414
|
+
if header.domain != DOMAIN_STRUCTURED:
|
|
415
|
+
raise Malformed("STRUCTURED frame must use the structured domain")
|
|
416
|
+
no_dict("STRUCTURED")
|
|
417
|
+
if header.dep_count != 0:
|
|
418
|
+
raise Malformed("STRUCTURED must not have dependencies in v1")
|
|
419
|
+
if header.chunk_count != 0:
|
|
420
|
+
raise Malformed("STRUCTURED must not be chunked")
|
|
421
|
+
if header.body_len != header.decoded_len:
|
|
422
|
+
raise Malformed("STRUCTURED body_len must equal decoded_len")
|
|
423
|
+
elif mode in (6, 7, 8, 9, 10, 12, 13, 15): # AI modes without dependencies
|
|
424
|
+
payload_domain("AI-mode")
|
|
425
|
+
no_dict("AI-mode")
|
|
426
|
+
if header.dep_count != 0:
|
|
427
|
+
raise Malformed("AI-mode frames must not have dependencies in v1")
|
|
428
|
+
if header.chunk_count != 0:
|
|
429
|
+
raise Malformed("AI-mode frames must not be chunked")
|
|
430
|
+
if header.body_len < 4:
|
|
431
|
+
raise Malformed("AI-mode body is shorter than its 4-byte metadata length")
|
|
432
|
+
elif mode in (11, 14, 16): # WEIGHT_DELTA / SEMANTIC_DELTA / SPARSE_DELTA
|
|
433
|
+
name = {
|
|
434
|
+
11: "WEIGHT_DELTA",
|
|
435
|
+
14: "SEMANTIC_DELTA",
|
|
436
|
+
16: "SPARSE_DELTA",
|
|
437
|
+
}[mode]
|
|
438
|
+
payload_domain(name)
|
|
439
|
+
no_dict(name)
|
|
440
|
+
if header.dep_count != 1:
|
|
441
|
+
raise Malformed("%s requires exactly one dependency" % name)
|
|
442
|
+
if header.chunk_count != 0:
|
|
443
|
+
raise Malformed("%s must not be chunked" % name)
|
|
444
|
+
if header.body_len < 4:
|
|
445
|
+
raise Malformed(
|
|
446
|
+
"%s body is shorter than its 4-byte metadata length" % name
|
|
447
|
+
)
|
|
448
|
+
if dependencies[0].dep_domain != DEP_DOMAIN_PAYLOAD:
|
|
449
|
+
raise Malformed(
|
|
450
|
+
"%s dependency must use dep_domain 0 (payload)" % name
|
|
451
|
+
)
|
|
452
|
+
if header.decoded_len != dependencies[0].decoded_len:
|
|
453
|
+
raise Malformed(
|
|
454
|
+
"%s decoded_len must equal the base decoded_len" % name
|
|
455
|
+
)
|
weftcodec/hashing.py
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""Domain-separated BLAKE3-256 hashing (WEFTCODEC-FORMAT §1.1).
|
|
2
|
+
|
|
3
|
+
Exactly one construction is used in v1::
|
|
4
|
+
|
|
5
|
+
H(domain, data) = BLAKE3-256(u32le(|domain|) || domain || data)
|
|
6
|
+
|
|
7
|
+
Domain strings are ASCII, contain no NUL, and are versioned.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from blake3 import blake3
|
|
13
|
+
|
|
14
|
+
HASH_LEN = 32
|
|
15
|
+
|
|
16
|
+
DOMAIN_CHUNK = "weft/chunk/v1"
|
|
17
|
+
DOMAIN_MANIFEST = "weft/manifest/v1"
|
|
18
|
+
DOMAIN_STRUCTURED = "weft/structured/v1"
|
|
19
|
+
DOMAIN_TENSOR_PAYLOAD = "weft/tensor/payload/v1"
|
|
20
|
+
DOMAIN_TOKENS_PAYLOAD = "weft/tokens/payload/v1"
|
|
21
|
+
DOMAIN_QUANTIZED_TENSOR_PAYLOAD = "weft/quantized-tensor/payload/v1"
|
|
22
|
+
DOMAIN_FLOAT_TENSOR_PAYLOAD = "weft/float-tensor/payload/v1"
|
|
23
|
+
DOMAIN_TENSOR_SHARDED_PAYLOAD = "weft/tensor-sharded/payload/v1"
|
|
24
|
+
DOMAIN_TENSOR_VALUES = "weft/tensor/values/v1"
|
|
25
|
+
DOMAIN_TENSOR_LOGICAL = "weft/tensor/logical/v1"
|
|
26
|
+
DOMAIN_TENSOR_TILE = "weft/tensor/tile/v1"
|
|
27
|
+
DOMAIN_TENSOR_FLOAT_TILE = "weft/tensor/float_tile/v1"
|
|
28
|
+
#: Independently decodable multi-stream float-tile identity
|
|
29
|
+
#: (WEFT-AI-CODEC §19).
|
|
30
|
+
DOMAIN_TENSOR_FLOAT_TILE_STREAMS = "weft/tensor/float_tile_streams/v1"
|
|
31
|
+
DOMAIN_TENSOR_SEMANTIC = "weft/tensor/semantic/v1"
|
|
32
|
+
DOMAIN_TENSOR_SEMANTIC_VALUES = "weft/tensor/semantic-values/v1"
|
|
33
|
+
DOMAIN_AI_STREAM = "weft/ai/stream/v1"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def hash_domain(domain: str, data: bytes) -> bytes:
|
|
37
|
+
"""Return the 32-byte domain-separated digest."""
|
|
38
|
+
raw = domain.encode("ascii")
|
|
39
|
+
hasher = blake3()
|
|
40
|
+
hasher.update(len(raw).to_bytes(4, "little"))
|
|
41
|
+
hasher.update(raw)
|
|
42
|
+
hasher.update(data)
|
|
43
|
+
return hasher.digest()
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def hash_domain_hex(domain: str, data: bytes) -> str:
|
|
47
|
+
return hash_domain(domain, data).hex()
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def content_root(data: bytes) -> bytes:
|
|
51
|
+
"""``H("weft/chunk/v1", data)`` — the content root of plaintext bytes."""
|
|
52
|
+
return hash_domain(DOMAIN_CHUNK, data)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def content_root_hex(data: bytes) -> str:
|
|
56
|
+
return content_root(data).hex()
|