Another project
0

Configure Feed

Select the types of activity you want to include in your feed.

1use bone_types::{FeatureId, SketchId}; 2use serde::{Deserialize, Serialize}; 3use slotmap::{Key, KeyData}; 4 5#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] 6pub enum PrincipalPlane { 7 Xy, 8 Yz, 9 Zx, 10} 11 12#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] 13pub enum FeatureNode { 14 Origin, 15 PrincipalPlane(PrincipalPlane), 16 Sketch(SketchId), 17} 18 19#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] 20#[serde(deny_unknown_fields)] 21struct FeatureEntry { 22 id: FeatureId, 23 node: FeatureNode, 24} 25 26#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] 27#[serde(deny_unknown_fields)] 28pub struct FeatureTree { 29 entries: Vec<FeatureEntry>, 30} 31 32impl FeatureTree { 33 #[must_use] 34 pub fn seeded() -> Self { 35 let seeds = [ 36 FeatureNode::Origin, 37 FeatureNode::PrincipalPlane(PrincipalPlane::Xy), 38 FeatureNode::PrincipalPlane(PrincipalPlane::Yz), 39 FeatureNode::PrincipalPlane(PrincipalPlane::Zx), 40 ]; 41 let entries = seeds 42 .into_iter() 43 .zip(1u32..) 44 .map(|(node, idx)| FeatureEntry { 45 id: feature_id_from_idx(idx), 46 node, 47 }) 48 .collect(); 49 Self { entries } 50 } 51 52 #[must_use] 53 pub fn node(&self, id: FeatureId) -> Option<FeatureNode> { 54 self.entries.iter().find(|e| e.id == id).map(|e| e.node) 55 } 56 57 pub fn iter(&self) -> impl Iterator<Item = (FeatureId, FeatureNode)> + '_ { 58 self.entries.iter().map(|e| (e.id, e.node)) 59 } 60 61 #[must_use] 62 pub fn feature_of_sketch(&self, sketch: SketchId) -> Option<FeatureId> { 63 self.entries 64 .iter() 65 .find(|e| matches!(e.node, FeatureNode::Sketch(s) if s == sketch)) 66 .map(|e| e.id) 67 } 68 69 pub fn push_sketch(&mut self, sketch: SketchId) -> FeatureId { 70 if let Some(existing) = self.feature_of_sketch(sketch) { 71 return existing; 72 } 73 let id = self.allocate(); 74 self.entries.push(FeatureEntry { 75 id, 76 node: FeatureNode::Sketch(sketch), 77 }); 78 id 79 } 80 81 pub fn remove_sketch(&mut self, sketch: SketchId) -> Option<FeatureId> { 82 let id = self.feature_of_sketch(sketch)?; 83 self.entries.retain(|e| e.id != id); 84 Some(id) 85 } 86 87 fn allocate(&self) -> FeatureId { 88 let highest = self.entries.iter().map(|e| idx_of(e.id)).max().unwrap_or(0); 89 let Some(next) = highest.checked_add(1) else { 90 panic!("FeatureTree exhausted 32-bit feature id space"); 91 }; 92 feature_id_from_idx(next) 93 } 94} 95 96fn feature_id_from_idx(idx: u32) -> FeatureId { 97 FeatureId::from(KeyData::from_ffi((1u64 << 32) | u64::from(idx))) 98} 99 100fn idx_of(id: FeatureId) -> u32 { 101 let Ok(idx) = u32::try_from(id.data().as_ffi() & 0xFFFF_FFFF) else { 102 panic!("lower 32 bits of ffi key fit in u32"); 103 }; 104 idx 105}