///|
/// JWWドキュメントシリアライザー
///|
/// JWWドキュメントをバイト列にシリアライズする
pub fn serialize(doc~ : Document) -> Bytes {
let writer = Writer::new()
// シグネチャ
writer.write_bytes(data=signature())
// バージョン
writer.write_dword(d=doc.version)
// ヘッダー情報
write_cstring(writer~, s=doc.memo)
writer.write_dword(d=doc.paper_size)
writer.write_dword(d=doc.write_layer_group)
// レイヤグループ(16グループ)
for lg in doc.layer_groups {
writer.write_dword(d=lg.state)
writer.write_dword(d=lg.write_layer)
writer.write_double(d=lg.scale)
writer.write_dword(d=lg.protect)
for l in lg.layers {
writer.write_dword(d=l.state)
writer.write_dword(d=l.protect)
}
}
// エンティティリスト
write_entity_list(writer~, entities=doc.entities, version=doc.version)
writer.to_bytes()
}
///|
/// エンティティリストを書き込む
fn write_entity_list(
writer~ : Writer,
entities~ : Array[Entity],
version~ : UInt,
) -> Unit {
let count = entities.length()
writer.write_word(w=count.to_uint16())
// PID トラッキング
let mut class_map : Array[String] = Array::new()
for _ in 0..<256 {
class_map.push("")
}
let mut next_pid : UInt = 1U
for entity in entities {
let (class_name, updated_map, updated_pid) = track_class(
entity~,
class_map~,
next_pid~,
)
write_entity(writer~, entity~, class_name~, version~)
class_map = updated_map
next_pid = updated_pid
}
}
///|
/// クラス名をトラッキングして PID を管理
fn track_class(
entity~ : Entity,
class_map~ : Array[String],
next_pid~ : UInt,
) -> (String, Array[String], UInt) {
let class_name = entity_class_name(entity~)
// 既存の PID を検索
let mut found_pid : UInt = 0U
let mut i = 1
while i <= 255 && i <= class_map.length() - 1 {
if class_map[i] == class_name {
found_pid = i.reinterpret_as_uint()
break
}
i = i + 1
}
let (updated_map, updated_next_pid) = if found_pid != 0U {
(class_map, next_pid)
} else {
// 新しいクラス定義を書き込む必要がある
let pid = next_pid
let new_map = class_map
if pid < 256U {
new_map[pid.reinterpret_as_int()] = class_name
}
(new_map, pid + 1)
}
(class_name, updated_map, updated_next_pid)
}