///|
let overlay_encoding_version = 61
///|
pub fn FuseOverlay::encode_words(self : FuseOverlay) -> Array[Int] {
let base_words = self.base.encode_words()
let words : Array[Int] = [overlay_encoding_version, base_words.length()]
for word in base_words {
words.push(word)
}
append_optional_verified(words, self.additions)
append_optional_verified(words, self.removals)
words
}
///|
pub fn decode_overlay_words(
words : Array[Int],
) -> Result[FuseOverlay, FuseError] {
if words.length() < 3 || words[0] != overlay_encoding_version || words[1] <= 0 {
return Err(InvalidEncoding)
}
let base_length = words[1]
if base_length > words.length() - 2 {
return Err(InvalidEncoding)
}
let encoded_base = copy_word_range(words, 2, base_length)
let mut cursor = 2 + base_length
let additions_result = read_optional_verified(words, cursor)
let (additions, after_additions) = match additions_result {
Ok(value) => value
Err(error) => return Err(error)
}
cursor = after_additions
let removals_result = read_optional_verified(words, cursor)
let (removals, after_removals) = match removals_result {
Ok(value) => value
Err(error) => return Err(error)
}
if after_removals != words.length() {
return Err(InvalidEncoding)
}
match decode_verified_words(encoded_base) {
Ok(base) => {
let overlay = { base, additions, removals }
if overlay.validate() {
Ok(overlay)
} else {
Err(InvalidEncoding)
}
}
Err(_) => Err(InvalidEncoding)
}
}
///|
fn append_optional_verified(
words : Array[Int],
filter : VerifiedFuseFilter?,
) -> Unit {
match filter {
None => words.push(0)
Some(value) => {
let encoded = value.encode_words()
words.push(encoded.length())
for word in encoded {
words.push(word)
}
}
}
}
///|
fn read_optional_verified(
words : Array[Int],
cursor : Int,
) -> Result[(VerifiedFuseFilter?, Int), FuseError] {
if cursor >= words.length() {
return Err(InvalidEncoding)
}
let length = words[cursor]
if length == 0 {
return Ok((None, cursor + 1))
}
if length < 0 || length > words.length() - cursor - 1 {
return Err(InvalidEncoding)
}
let encoded = copy_word_range(words, cursor + 1, length)
match decode_verified_words(encoded) {
Ok(filter) => Ok((Some(filter), cursor + 1 + length))
Err(_) => Err(InvalidEncoding)
}
}
///|
fn copy_word_range(words : Array[Int], start : Int, length : Int) -> Array[Int] {
let copied = Array::make(length, 0)
for index in 0..