rupg_catalog/
enum_label.rs1use rupg_common::Result;
4
5use super::{Catalog, EnumLabel, no_object};
6
7impl Catalog {
8 #[allow(clippy::cast_precision_loss, clippy::manual_midpoint)]
14 pub fn add_enum_label(
15 &mut self,
16 ty: u32,
17 label: String,
18 neighbor: Option<(usize, bool)>,
19 ) -> Result<()> {
20 let labels = self.labels_mut(ty)?;
21 let (order, at) = loop {
22 let Some((at, after)) = neighbor else {
23 break (labels.last().map_or(1.0, |l| l.sort_order + 1.0), labels.len());
24 };
25 let near = labels[at].sort_order;
26 let other = if after { at.checked_add(1) } else { at.checked_sub(1) };
27 let place = if after { at + 1 } else { at };
28 let Some(other) = other.and_then(|o| labels.get(o)).map(|l| l.sort_order) else {
29 break (if after { near + 1.0 } else { near - 1.0 }, place);
30 };
31 let middle = (near + other) / 2.0;
33 if middle != near && middle != other {
34 break (middle, place);
35 }
36 for (i, label) in labels.iter_mut().enumerate() {
37 label.sort_order = (i + 1) as f32;
38 }
39 };
40 let even: Vec<(u32, f32)> =
41 labels.iter().filter(|l| l.oid & 1 == 0).map(|l| (l.oid, l.sort_order)).collect();
42 let oid = loop {
43 let oid = self.new_oid();
44 let sorts = even.iter().all(|&(e, o)| if o < order { e < oid } else { e > oid });
45 if sorts || oid & 1 == 1 {
46 break oid;
47 }
48 };
49 self.labels_mut(ty)?.insert(at, EnumLabel { oid, sort_order: order, label });
50 if !self.uncommitted_types.contains(&ty) {
51 self.uncommitted_labels.push(oid);
52 }
53 Ok(())
54 }
55
56 pub fn rename_enum_label(&mut self, ty: u32, at: usize, name: String) -> Result<()> {
62 if let Some(label) = self.labels_mut(ty)?.get_mut(at) {
63 label.label = name;
64 }
65 Ok(())
66 }
67
68 pub fn label_is_uncommitted(&self, label: u32) -> bool {
70 self.uncommitted_labels.contains(&label)
71 }
72
73 pub fn has_uncommitted_enums(&self) -> bool {
75 !self.uncommitted_types.is_empty() || !self.uncommitted_labels.is_empty()
76 }
77
78 pub fn commit_enums(&mut self) {
80 self.uncommitted_types.clear();
81 self.uncommitted_labels.clear();
82 }
83
84 fn labels_mut(&mut self, ty: u32) -> Result<&mut Vec<EnumLabel>> {
86 self.types.get_mut(&ty).and_then(|t| t.labels.as_mut()).ok_or_else(|| no_object("type", ty))
87 }
88}