///|
/// Store this descriptor alongside the index, outside the ordered data keys.
pub fn KeySpec::layout(self : KeySpec) -> Bytes {
let descriptor = @buffer.Buffer(size_hint=3 + self.fields.length())
descriptor.write_bytes(b"OK\x01"[:])
for field in self.fields {
descriptor.write_byte(
match field {
BytesField(Asc) => 0x10
BytesField(Desc) => 0x11
Int64Field(Asc) => 0x20
Int64Field(Desc) => 0x21
},
)
}
descriptor.to_bytes()
}
///|
/// Reconstructs a spec from a persisted v1 layout descriptor.
pub fn KeySpec::from_layout(descriptor : Bytes) -> KeySpec raise KeyError {
if descriptor.length() == 0 || descriptor[0] != b'O' {
raise InvalidLayout(0)
}
if descriptor.length() < 2 || descriptor[1] != b'K' {
raise InvalidLayout(1)
}
if descriptor.length() < 3 {
raise InvalidLayout(2)
}
if descriptor[2] != 1 {
raise UnsupportedKeyFormat(descriptor[2])
}
if descriptor.length() == 3 {
raise InvalidLayout(3)
}
let fields = []
for index = 3; index < descriptor.length(); index = index + 1 {
fields.push(
match descriptor[index] {
0x10 => BytesField(Asc)
0x11 => BytesField(Desc)
0x20 => Int64Field(Asc)
0x21 => Int64Field(Desc)
_ => raise InvalidLayout(index)
},
)
}
{ fields, }
}
///|
/// Checks the stored key format, field types and directions before opening an index.
pub fn KeySpec::require_layout(
self : KeySpec,
descriptor : Bytes,
) -> Unit raise KeyError {
if descriptor != self.layout() {
KeySpec::from_layout(descriptor) |> ignore
raise LayoutMismatch
}
}