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