// 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.
///|
priv struct OrderEdge {
target : Int
width : Int
}
///|
pub struct OverflowRecord {
parent : Int
child : Int
offset : Int
min : Int
max : Int
width : Int
is_signed : Bool
} derive(Eq, Show)
let inf_distance : Int64 = Int64::from_int(1) << 60
let space_stride : Int64 = Int64::from_int(1) << 32
fn edge_weight(width : Int, child_size : Int) -> Int64 {
let size = Int64::from_int(child_size)
if width <= 0 {
return size
}
let limit = Int64::from_int(1) << (width * 8)
size + limit
}
fn collect_order_edges(
objects : ArrayView[SerializeObject],
) -> Result[(Array[Array[OrderEdge]], Array[Int]), SerializeError] {
let count = objects.length()
let edges : Array[Array[OrderEdge]] = []
let indegree : Array[Int] = Array::make(count, 0)
for _ in 0..= count {
return Err(SerializeError::InvalidLink)
}
edges[i].push(OrderEdge::{ target, width: 0 })
indegree[target] = indegree[target] + 1
}
for link in obj.real_links {
if link.objidx < 0 || link.objidx >= count {
return Err(SerializeError::InvalidLink)
}
if link.width == 0 {
edges[i].push(OrderEdge::{ target: link.objidx, width: 0 })
indegree[link.objidx] = indegree[link.objidx] + 1
continue
}
if link.is_signed {
continue
}
if link.whence == SerializeWhence::Absolute {
continue
}
edges[i].push(OrderEdge::{ target: link.objidx, width: link.width })
indegree[link.objidx] = indegree[link.objidx] + 1
}
}
Ok((edges, indegree))
}
fn assign_spaces(edges : Array[Array[OrderEdge]]) -> Array[Int] {
let count = edges.length()
let spaces : Array[Int] = Array::make(count, 0)
let reachable : Array[Bool] = Array::make(count, false)
let queue : Array[Int] = []
for i in 0..= 4 {
queue.push(edge.target)
}
}
}
let mut index = 0
while index < queue.length() {
let node = queue[index]
index = index + 1
if reachable[node] {
continue
}
reachable[node] = true
for edge in edges[node] {
if !reachable[edge.target] {
queue.push(edge.target)
}
}
}
if queue.length() == 0 {
return spaces
}
let undirected : Array[Array[Int]] = []
for _ in 0.. Array[Int64] {
let count = objects.length()
let dist : Array[Int64] = Array::make(count, inf_distance)
let visited : Array[Bool] = Array::make(count, false)
for i in 0.. Result[Array[Int], SerializeError] {
let count = edges.length()
let indeg = indegree.copy()
let ready : Array[Int] = []
for i in 0.. 0 {
let mut best_idx = 0
let mut best_node = ready[0]
for i in 1.. Result[Array[Int], SerializeError] {
let count = objects.length()
if order.length() != count {
return Err(SerializeError::InvalidLink)
}
let starts : Array[Int] = Array::make(count, 0)
let seen : Array[Bool] = Array::make(count, false)
let mut offset = 0
for idx in order {
if idx < 0 || idx >= count {
return Err(SerializeError::InvalidLink)
}
if seen[idx] {
return Err(SerializeError::InvalidLink)
}
seen[idx] = true
starts[idx] = offset
offset = offset + objects[idx].data.length()
}
Ok(starts)
}
fn collect_overflows(
objects : ArrayView[SerializeObject],
order : ArrayView[Int],
) -> Result[Array[OverflowRecord], SerializeError] {
let count = objects.length()
let starts = match compute_starts(objects, order) {
Ok(value) => value
Err(err) => return Err(err)
}
let overflows : Array[OverflowRecord] = []
for i in 0..= count {
return Err(SerializeError::InvalidLink)
}
if link.position < 0 || link.position + link.width > obj.data.length() {
return Err(SerializeError::OutOfBounds)
}
let target_start = starts[link.objidx]
let origin = match link.whence {
SerializeWhence::Head => starts[i]
SerializeWhence::Tail => starts[i] + obj.data.length()
SerializeWhence::Absolute => 0
}
let offset = target_start + link.bias - origin
if link.is_signed {
let limits = match signed_limits(link.width) {
None => return Err(SerializeError::InvalidWidth)
Some((min, max)) => (min, max)
}
if offset < limits.0 || offset > limits.1 {
overflows.push(OverflowRecord::{
parent: i,
child: link.objidx,
offset,
min: limits.0,
max: limits.1,
width: link.width,
is_signed: true,
})
}
} else {
let max_value = match max_value_for_width(link.width) {
None => return Err(SerializeError::InvalidWidth)
Some(value) => value
}
let max_int = max_value.reinterpret_as_int()
if offset < 0 || offset > max_int {
overflows.push(OverflowRecord::{
parent: i,
child: link.objidx,
offset,
min: 0,
max: max_int,
width: link.width,
is_signed: false,
})
}
}
}
}
Ok(overflows)
}
fn priority_delta(width : Int, child_size : Int) -> Int64 {
if width <= 0 {
return Int64::from_int(1)
}
edge_weight(width, child_size) + Int64::from_int(1)
}
///|
pub fn repack_object_order(
objects : ArrayView[SerializeObject],
max_iterations? : Int = 32,
) -> Result[Array[Int], SerializeError] {
let count = objects.length()
if count == 0 {
return Ok([])
}
let (edges, indegree) = match collect_order_edges(objects) {
Ok(value) => value
Err(err) => return Err(err)
}
let spaces = assign_spaces(edges)
let priorities : Array[Int64] = Array::make(count, Int64::from_int(0))
let mut iter = 0
while iter < max_iterations {
let base_dist = compute_shortest_dist(objects, edges, indegree)
let scores : Array[Int64] = Array::make(count, Int64::from_int(0))
for i in 0.. value
Err(err) => return Err(err)
}
let overflows = match collect_overflows(objects, order[:]) {
Ok(value) => value
Err(err) => return Err(err)
}
if overflows.length() == 0 {
return Ok(order)
}
for overflow in overflows {
let child_size = objects[overflow.child].data.length()
let delta = priority_delta(overflow.width, child_size)
priorities[overflow.child] = priorities[overflow.child] - delta
}
iter = iter + 1
}
Err(SerializeError::OffsetOverflow)
}
///|
pub fn serialize_objects_repacked(
objects : ArrayView[SerializeObject],
max_iterations? : Int = 32,
) -> Result[Bytes, SerializeError] {
let order = match repack_object_order(objects, max_iterations=max_iterations) {
Ok(value) => value
Err(err) => return Err(err)
}
serialize_objects_in_order(objects, order[:])
}
///|
pub fn serialize_objects_repacked_with_order(
objects : ArrayView[SerializeObject],
max_iterations? : Int = 32,
) -> Result[(Bytes, Array[Int]), SerializeError] {
let order = match repack_object_order(objects, max_iterations=max_iterations) {
Ok(value) => value
Err(err) => return Err(err)
}
let bytes = match serialize_objects_in_order(objects, order[:]) {
Ok(value) => value
Err(err) => return Err(err)
}
Ok((bytes, order))
}