steel_registry/
attribute.rs1use rustc_hash::FxHashMap;
2use steel_utils::Identifier;
3
4#[derive(Debug)]
9pub struct Attribute {
10 pub key: Identifier,
11 pub translation_key: &'static str,
12 pub default_value: f64,
13 pub min_value: f64,
14 pub max_value: f64,
15 pub syncable: bool,
16}
17
18impl Attribute {
19 #[must_use]
21 pub fn sanitize_value(&self, value: f64) -> f64 {
22 value.clamp(self.min_value, self.max_value)
23 }
24}
25
26pub type AttributeRef = &'static Attribute;
27
28pub struct AttributeRegistry {
29 attributes_by_id: Vec<AttributeRef>,
30 attributes_by_key: FxHashMap<Identifier, usize>,
31 allows_registering: bool,
32}
33
34impl Default for AttributeRegistry {
35 fn default() -> Self {
36 Self::new()
37 }
38}
39
40impl AttributeRegistry {
41 #[must_use]
42 pub fn new() -> Self {
43 Self {
44 attributes_by_id: Vec::new(),
45 attributes_by_key: FxHashMap::default(),
46 allows_registering: true,
47 }
48 }
49
50 pub fn register(&mut self, attribute: AttributeRef) {
52 assert!(
53 self.allows_registering,
54 "Cannot register attributes after the registry has been frozen"
55 );
56 let idx = self.attributes_by_id.len();
57 self.attributes_by_key.insert(attribute.key.clone(), idx);
58 self.attributes_by_id.push(attribute);
59 }
60
61 #[must_use]
63 pub fn replace(&mut self, attribute: AttributeRef, id: usize) -> bool {
64 if id >= self.attributes_by_id.len() {
65 return false;
66 }
67 self.attributes_by_id[id] = attribute;
68 true
69 }
70
71 pub fn iter(&self) -> impl Iterator<Item = (usize, AttributeRef)> + '_ {
72 self.attributes_by_id
73 .iter()
74 .enumerate()
75 .map(|(id, &attr)| (id, attr))
76 }
77}
78
79crate::impl_registry!(
80 AttributeRegistry,
81 Attribute,
82 attributes_by_id,
83 attributes_by_key,
84 attributes
85);