// Copyright 2026 International Digital Economy Academy
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
///|
pub struct MvarRecord {
tag : @common.Tag
var_idx : UInt
} derive(Eq, Show, ToJson)
///|
pub struct MvarTable {
records : Array[MvarRecord]
var_store : ItemVariationStore
} derive(Show, ToJson)
///|
pub fn MvarTable::parse(data : BytesView) -> Result[MvarTable, VarError] {
let version = read_u32(data, 0)
let value_record_size = read_u16_int(data, 6)
let value_record_count = read_u16_int(data, 8)
let var_store_offset = read_u16_int(data, 10)
match (version, value_record_size, value_record_count, var_store_offset) {
(Err(err), _, _, _) => Err(err)
(_, Err(err), _, _) => Err(err)
(_, _, Err(err), _) => Err(err)
(_, _, _, Err(err)) => Err(err)
(Ok(version), Ok(value_record_size), Ok(value_record_count), Ok(var_store_offset)) => {
let major = (version >> 16) & 0xFFFFU
if major != 1U {
return Err(InvalidFormat)
}
if value_record_size < 8 {
return Err(InvalidFormat)
}
if var_store_offset < 0 || var_store_offset >= data.length() {
return Err(UnexpectedEof)
}
let var_store = match ItemVariationStore::parse(data[var_store_offset:]) {
Err(err) => return Err(err)
Ok(value) => value
}
let mut offset = 12
let records : Array[MvarRecord] = []
for _ in 0.. data.length() {
return Err(UnexpectedEof)
}
let tag = read_tag(data, offset)
let var_idx = read_u32(data, offset + 4)
match (tag, var_idx) {
(Err(err), _) => return Err(err)
(_, Err(err)) => return Err(err)
(Ok(tag), Ok(var_idx)) =>
records.push(MvarRecord::{ tag, var_idx })
}
offset = offset + value_record_size
}
Ok(MvarTable::{ records, var_store })
}
}
}
///|
pub fn MvarTable::get_var(
self : MvarTable,
tag : @common.Tag,
coords : Array[Int],
) -> Double {
for record in self.records {
if record.tag == tag {
return self.var_store.get_delta(record.var_idx, coords)
}
}
0.0
}