///|
/// ブロック定義リストパース結果
priv struct BlockDefListResult {
block_defs : Array[BlockDef]
end_offset : Int
}
///|
/// ブロック定義リストをパースする
fn parse_block_def_list(
data~ : Bytes,
offset~ : Int,
version~ : UInt,
) -> BlockDefListResult {
// offsetがデータ範囲外の場合は空配列を返す
if offset >= data.length() {
return { block_defs: Array::new(), end_offset: offset }
}
let block_data = Bytes::from_array(data.to_array()[offset:data.length()])
let reader = Reader::new(data=block_data)
let start_pos = reader.position()
// データが4バイト未満の場合は空配列を返す
if reader.remaining() < 4 {
return { block_defs: Array::new(), end_offset: offset }
}
let count = reader.read_dword()
// カウントが異常な値の場合は空配列を返す
if count > 10000U {
return { block_defs: Array::new(), end_offset: offset }
}
let block_defs = Array::new()
// MFC CArchive PIDトラッキング(UInt16版)
let mut class_map = Array::new()
for _ in 0..<256 {
class_map.push("")
}
let mut next_id : UInt16 = 1
for _ in 0.. block_defs.push(bd)
None => {
let _ = class_map
}
}
class_map = result.class_map
next_id = result.next_id
}
let end_pos = reader.position()
{ block_defs, end_offset: offset + (end_pos - start_pos) }
}
///|
/// ブロック定義パース結果
priv struct BlockDefResult {
block_def : BlockDef?
class_map : Array[String]
next_id : UInt16
}
///|
/// トラッキング付きでブロック定義をパースする
fn parse_block_def_with_tracking(
reader~ : Reader,
version~ : UInt,
class_map~ : Array[String],
next_id~ : UInt16,
) -> BlockDefResult {
let class_id = reader.read_word().to_int()
let (updated_class_map, updated_next_id) = if class_id == 0xFFFF {
// 新しいクラス定義
let _schema = reader.read_word()
let name_len = reader.read_word().to_int()
let name_bytes = reader.read_bytes(n=name_len)
// バイト列をASCII文字列として解釈
let mut name_chars = ""
for i in 0..