use crate::{
ItemList,
specification::{A2lFile, A2lObject, A2lObjectName},
};
use std::cmp::Ordering;
pub(crate) fn sort_new_items(a2l_file: &mut A2lFile) {
if let Some(asap2version) = &mut a2l_file.asap2_version
&& asap2version.__block_info.uid == 0
{
asap2version.__block_info.uid = 1;
if let Some(a2ml_version) = &mut a2l_file.a2ml_version {
a2ml_version.__block_info.uid = 2;
}
a2l_file.project.__block_info.uid = 3;
}
if let Some(header) = &mut a2l_file.project.header
&& header.__block_info.uid == 0
{
header.__block_info.uid = 1;
header.__block_info.start_offset = 1;
}
for module in &mut a2l_file.project.module {
let next_uid = sort_optional_item(&mut module.a2ml, 1);
let next_uid = sort_optional_item(&mut module.mod_common, next_uid);
sort_optional_item(&mut module.mod_par, next_uid);
sort_objectlist_new(&mut module.axis_pts);
sort_objectlist_new(&mut module.blob);
sort_objectlist_new(&mut module.characteristic);
sort_objectlist_new(&mut module.compu_method);
sort_objectlist_new(&mut module.compu_tab);
sort_objectlist_new(&mut module.compu_vtab);
sort_objectlist_new(&mut module.compu_vtab_range);
sort_objectlist_new(&mut module.frame);
sort_objectlist_new(&mut module.function);
sort_objectlist_new(&mut module.group);
sort_objectlist_new(&mut module.instance);
sort_objectlist_new(&mut module.measurement);
sort_objectlist_new(&mut module.record_layout);
sort_objectlist_new(&mut module.transformer);
sort_objectlist_new(&mut module.typedef_axis);
sort_objectlist_new(&mut module.typedef_blob);
sort_objectlist_new(&mut module.typedef_characteristic);
sort_objectlist_new(&mut module.typedef_measurement);
sort_objectlist_new(&mut module.typedef_structure);
sort_objectlist_new(&mut module.unit);
for comment in &mut module.a2lcomment {
comment.uid *= 2;
}
if let Some(maxid) = module
.if_data
.iter()
.map(|item| item.get_layout().uid)
.max()
&& maxid > 0
{
module.if_data.iter_mut().for_each(|item| {
if item.get_layout_mut().uid != 0 {
item.get_layout_mut().uid *= 2;
} else {
item.get_layout_mut().uid = maxid * 2 + 1;
}
});
}
if let Some(maxid) = module
.user_rights
.iter()
.map(|item| item.get_layout().uid)
.max()
&& maxid > 0
{
module.user_rights.iter_mut().for_each(|item| {
if item.get_layout_mut().uid != 0 {
item.get_layout_mut().uid *= 2;
} else {
item.get_layout_mut().uid = maxid * 2 + 1;
}
});
}
sort_optional_item(&mut module.variant_coding, 0);
}
}
fn sort_optional_item<T, U>(a2lobject_option: &mut Option<T>, new_uid: u32) -> u32
where
T: A2lObject<U>,
{
let mut next_uid = new_uid;
if let Some(a2lobject) = a2lobject_option {
let layout = a2lobject.get_layout_mut();
if layout.uid == 0 {
layout.uid = new_uid;
} else {
layout.uid *= 2;
next_uid = layout.uid + 1;
}
}
next_uid
}
fn sort_objectlist_new<T, U>(a2lobject_list: &mut ItemList<T>)
where
T: A2lObject<U> + A2lObjectName,
{
a2lobject_list.sort_by(cmp_named_a2lobject);
let mut last_uid = 0;
for a2lobject in a2lobject_list {
let layout = a2lobject.get_layout_mut();
if layout.uid != 0 {
layout.uid *= 2;
last_uid = layout.uid + 1;
} else {
layout.uid = last_uid;
layout.start_offset = 2;
layout.end_offset = 1;
}
}
}
pub(crate) fn sort(a2l_file: &mut A2lFile) {
if let Some(asap2_version) = &mut a2l_file.asap2_version {
asap2_version.__block_info.uid = 1;
asap2_version.__block_info.start_offset = 1;
}
if let Some(a2ml_version) = &mut a2l_file.a2ml_version {
a2ml_version.__block_info.uid = 2;
a2ml_version.__block_info.start_offset = 2;
}
a2l_file.project.__block_info.uid = 3;
a2l_file.project.__block_info.start_offset = 2;
a2l_file.project.__block_info.end_offset = 1;
if let Some(header) = &mut a2l_file.project.header {
header.__block_info.uid = 1;
header.__block_info.start_offset = 1;
}
sort_objectlist_full(&mut a2l_file.project.module, 2);
for module in &mut a2l_file.project.module {
if let Some(a2ml) = &mut module.a2ml {
a2ml.__block_info.uid = 1;
a2ml.__block_info.start_offset = 1;
}
if let Some(mod_common) = &mut module.mod_common {
mod_common.__block_info.uid = 2;
mod_common.__block_info.start_offset = 2;
}
if let Some(mod_par) = &mut module.mod_par {
mod_par.__block_info.uid = 3;
mod_par.__block_info.start_offset = 2;
}
let mut uid = 4;
for if_data in &mut module.if_data {
if_data.__block_info.uid = uid;
uid += 1;
if_data.__block_info.start_offset = 2;
}
uid = sort_objectlist_full(&mut module.characteristic, uid);
uid = sort_objectlist_full(&mut module.measurement, uid);
uid = sort_objectlist_full(&mut module.axis_pts, uid);
uid = sort_objectlist_full(&mut module.instance, uid);
uid = sort_objectlist_full(&mut module.blob, uid);
uid = sort_objectlist_full(&mut module.compu_method, uid);
uid = sort_objectlist_full(&mut module.compu_tab, uid);
uid = sort_objectlist_full(&mut module.compu_vtab, uid);
uid = sort_objectlist_full(&mut module.compu_vtab_range, uid);
uid = sort_objectlist_full(&mut module.typedef_structure, uid);
uid = sort_objectlist_full(&mut module.typedef_characteristic, uid);
uid = sort_objectlist_full(&mut module.typedef_measurement, uid);
uid = sort_objectlist_full(&mut module.typedef_axis, uid);
uid = sort_objectlist_full(&mut module.typedef_blob, uid);
uid = sort_objectlist_full(&mut module.frame, uid);
uid = sort_objectlist_full(&mut module.function, uid);
uid = sort_objectlist_full(&mut module.group, uid);
uid = sort_objectlist_full(&mut module.record_layout, uid);
uid = sort_objectlist_full(&mut module.transformer, uid);
uid = sort_objectlist_full(&mut module.unit, uid);
module.a2lcomment.clear();
module
.user_rights
.sort_by(|a, b| a.user_level_id.cmp(&b.user_level_id));
for user_rights in &mut module.user_rights {
user_rights.__block_info.uid = uid;
uid += 1;
user_rights.__block_info.start_offset = 2;
}
if let Some(variant_coding) = &mut module.variant_coding {
variant_coding.__block_info.uid = uid;
variant_coding.__block_info.start_offset = 2;
}
}
}
fn sort_objectlist_full<T, U>(a2lobject_list: &mut ItemList<T>, start_uid: u32) -> u32
where
T: A2lObject<U> + A2lObjectName,
{
let mut current_uid = start_uid;
a2lobject_list.sort_by(|a, b| a.get_name().cmp(b.get_name()));
for a2lobject in a2lobject_list {
a2lobject.get_layout_mut().uid = current_uid;
a2lobject.get_layout_mut().start_offset = 2;
a2lobject.get_layout_mut().end_offset = 1;
current_uid += 1;
}
current_uid
}
fn cmp_named_a2lobject<T, U>(a: &T, b: &T) -> Ordering
where
T: A2lObject<U> + A2lObjectName,
{
let la = a.get_layout();
let lb = b.get_layout();
if la.uid == 0 && lb.uid != 0 {
Ordering::Greater
} else if lb.uid == 0 && la.uid != 0 {
Ordering::Less
} else if la.uid == lb.uid {
if la.line == lb.line {
a.get_name().cmp(b.get_name())
} else {
la.line.cmp(&lb.line)
}
} else {
la.uid.cmp(&lb.uid)
}
}