src/transfer/FormatInspect.bend
mylsm-lsm-store@0.6.0.0 · 140 lines · 0 definitions
1import Base
2import mylsm-lsm-store@0.6.0.0/src/ByteManifest.bend as ByteManifest
3import mylsm-lsm-store@0.6.0.0/src/Manifest.bend as LegacyManifest
4import bend-kit-bytes@0.3.2.0/bytes.bend as Bytes
5
6# Identifies the storage generation independently of the writing package.
7type StorageFormat is Data:
8 Format04{}
9 Format06{}
10 UnknownFormat{}
11
12# Reports package and storage identities as separate fields.
13type Identity is Data:
14 Identity{package_version: String, storage_version: String, generation: U32}
15
16# Reports validation status without conflating it with the format identity.
17type Integrity is Data:
18 Valid{}
19 UnsupportedVersion{generation: U32}
20 UnsupportedComparator{generation: U32}
21 UnrecognizedFormat{}
22 Corrupt{}
23 ResourceLimit{}
24
25# Separates API/storage version identity from manifest integrity.
26type Inspection is Data:
27 Inspection{identity: Identity, integrity: Integrity}
28
29# Converts a decoded hex literal to an owned buffer.
30def magic.from_hex(value: Maybe<&1, Bytes.Bytes>) -> Bytes.Bytes:
31 match value:
32 case Some{bytes}:
33 bytes
34 case None{}:
35 Bytes.new(0)
36
37# Produces the generation-three Manifest magic.
38def magic.legacy() -> Bytes.Bytes:
39 magic.from_hex(Bytes.from_hex("4d594c534d334d00"))
40
41# Produces the generation-four Manifest magic.
42def magic.current() -> Bytes.Bytes:
43 magic.from_hex(Bytes.from_hex("4d594c534d344d00"))
44
45# Classifies the current magic after an unsuccessful legacy comparison.
46def classify.current(comparison: Bytes.Bytes & Bytes.Bytes & Bool) -> StorageFormat:
47 match comparison:
48 case (_, _, True{}):
49 Format06{}
50 case (_, _, False{}):
51 UnknownFormat{}
52
53# Preserves the candidate bytes while checking the current manifest magic.
54def classify.legacy(comparison: Bytes.Bytes & Bytes.Bytes & Bool) -> StorageFormat:
55 match comparison:
56 case (_, candidate, True{}):
57 Format04{}
58 case (_, candidate, False{}):
59 classify.current(Bytes.eq(magic.current(), candidate))
60
61# Classifies known Manifest signatures without opening or modifying storage.
62def classify_manifest(magic: Bytes.Bytes) -> StorageFormat:
63 classify.legacy(Bytes.eq(magic.legacy(), magic))
64
65# Describes the package release and storage format separately.
66def describe(format: StorageFormat) -> Identity:
67 match format:
68 case Format04{}:
69 Identity{"0.5.0.0", "0.4.0.0", 3}
70 case Format06{}:
71 Identity{"0.6.0.0", "0.6.0.0", 4}
72 case UnknownFormat{}:
73 Identity{"unknown", "unknown", 0}
74
75# Identifies a Manifest and returns its separate version fields.
76def inspect_manifest(magic: Bytes.Bytes) -> Identity:
77 describe(classify_manifest(magic))
78
79def magic.slice.result(pair: Bytes.Bytes & Bytes.Bytes) -> Bytes.Bytes:
80 match pair:
81 case (_, bytes): bytes
82
83def bytes.clone.pair(+len: U32, copied: Array<U32> & Array<U32>) -> Bytes.Bytes & Bytes.Bytes:
84 match copied:
85 case (left, right): (Bytes.Bytes{len, left}, Bytes.Bytes{len, right})
86
87def bytes.clone.split(bytes: Bytes.Bytes) -> Bytes.Bytes & Bytes.Bytes:
88 match bytes:
89 case Bytes.Bytes{+len, buffer}:
90 bytes.clone.pair(len, Bytes.copy.bytes(len, buffer, Bytes.alloc(len), 0, 0))
91
92def inspect.legacy.result(result: LegacyManifest.ParseResult) -> Integrity:
93 match result:
94 case LegacyManifest.Parsed{_}: Valid{}
95 case LegacyManifest.UnsupportedVersion{version}:
96 UnsupportedVersion{version}
97 case LegacyManifest.ParseLimitExceeded{}: ResourceLimit{}
98 case LegacyManifest.Malformed{}: Corrupt{}
99
100def inspect.current.result(
101 result: Result<&1, &1, ByteManifest.Error, ByteManifest.ManifestValue>
102) -> Integrity:
103 match result:
104 case Done{_}: Valid{}
105 case Fail{ByteManifest.UnsupportedVersion{generation}}:
106 UnsupportedVersion{generation}
107 case Fail{ByteManifest.ComparatorMismatch{generation}}:
108 UnsupportedComparator{generation}
109 case Fail{_}: Corrupt{}
110
111def inspect.result(format: StorageFormat, bytes: Bytes.Bytes) -> Integrity:
112 match format:
113 case Format04{}: inspect.legacy.result(LegacyManifest.parse_result(bytes))
114 case Format06{}: inspect.current.result(ByteManifest.decode(bytes))
115 case UnknownFormat{}: UnrecognizedFormat{}
116
117def format.clone(format: StorageFormat) -> StorageFormat & StorageFormat:
118 match format:
119 case Format04{}: (Format04{}, Format04{})
120 case Format06{}: (Format06{}, Format06{})
121 case UnknownFormat{}: (UnknownFormat{}, UnknownFormat{})
122
123def inspect.bytes.format(
124 bytes: Bytes.Bytes,
125 formats: StorageFormat & StorageFormat
126) -> Inspection:
127 match formats:
128 case (identity_format, integrity_format):
129 Inspection{describe(identity_format), inspect.result(integrity_format, bytes)}
130
131def inspect.bytes.copies(copies: Bytes.Bytes & Bytes.Bytes) -> Inspection:
132 match copies:
133 case (data, magic_bytes):
134 inspect.bytes.format(data,
135 format.clone(classify_manifest(magic.slice.result(
136 Bytes.slice(magic_bytes, 0, 8)))))
137
138# Identifies and validates one complete manifest without changing storage.
139def inspect_manifest_bytes(bytes: Bytes.Bytes) -> Inspection:
140 inspect.bytes.copies(bytes.clone.split(bytes))