use std::collections::{BTreeMap, BTreeSet};
use crate::parser::{Attribute, RawEntity, Span};
pub fn apply(map: &mut BTreeMap<u64, RawEntity>, norm: &mut Vec<&'static str>) {
let existing: BTreeSet<u64> = map.keys().copied().collect();
let mut next_id = map.keys().max().map_or(1, |m| m.saturating_add(1));
let alloc_id = |next: &mut u64| -> u64 {
while existing.contains(next) || *next == 0 {
*next = next.wrapping_add(1);
}
let id = *next;
*next = next.wrapping_add(1);
id
};
let mut synth: Vec<(u64, RawEntity)> = Vec::new();
for ent in map.values_mut() {
let RawEntity::Simple {
name, attributes, ..
} = ent
else {
continue;
};
match name.as_str() {
"SURFACE_STYLE_RENDERING" | "SURFACE_STYLE_RENDERING_WITH_PROPERTIES" => {
if let Some(a) = attributes.get_mut(0) {
let needs_default = match a {
Attribute::Enum(s) => !matches!(
s.as_str(),
"CONSTANT_SHADING"
| "COLOUR_SHADING"
| "DOT_SHADING"
| "NORMAL_SHADING"
),
_ => true,
};
if needs_default {
*a = Attribute::Enum("NORMAL_SHADING".to_string());
norm.push("entity: surface_style_rendering.rendering_method<-default");
}
}
if let Some(a) = attributes.get_mut(1)
&& matches!(a, Attribute::Unset)
{
let cid = alloc_id(&mut next_id);
synth.push((
cid,
RawEntity::Simple {
id: cid,
name: "COLOUR".to_string(),
attributes: vec![],
span: Span {
start: 0,
end: 0,
line: 0,
column: 0,
},
},
));
*a = Attribute::EntityRef(cid);
norm.push("entity: surface_style_rendering.surface_colour<-COLOUR()");
}
}
"PRESENTATION_STYLE_ASSIGNMENT" => {
if let Some(Attribute::List(styles)) = attributes.get_mut(0) {
for s in styles.iter_mut() {
if matches!(s, Attribute::Enum(_)) {
let val = std::mem::replace(s, Attribute::Unset);
*s = Attribute::Typed {
type_name: "NULL_STYLE".to_string(),
value: Box::new(val),
};
norm.push("entity: psa.styles bare-null-style->typed");
}
}
}
}
_ => {}
}
}
for (id, e) in synth {
map.insert(id, e);
}
}