From 6461133e87630caa03cd0f429cf49e3b4b9b7569 Mon Sep 17 00:00:00 2001 From: Dennis Kobert Date: Sun, 6 Apr 2025 10:41:55 +0200 Subject: [PATCH] Include more sample code --- node-graph/rfcs/dynamic-tables.md | 267 ++++++++++++++++++++++++++++++ 1 file changed, 267 insertions(+) diff --git a/node-graph/rfcs/dynamic-tables.md b/node-graph/rfcs/dynamic-tables.md index e59d6ff5b2..44c3a9ba49 100644 --- a/node-graph/rfcs/dynamic-tables.md +++ b/node-graph/rfcs/dynamic-tables.md @@ -198,3 +198,270 @@ Note that having something written down in the future-possibilities section is not a reason to accept the current or a future RFC; such notes should be in the section on motivation or rationale in this or subsequent RFCs. The section merely provides additional information. + + +# Implementation prototype +```rust +use std::{ + any::{Any, TypeId}, + collections::HashMap, + sync::Arc, +}; + +pub struct Transform; +pub struct BlendMode; +pub type VectorData = String; +type DVec2 = (); +type Segment = (); +type Region = (); + +// T = DynamicTable +pub struct TableRow { + primary: T, + // Each table type will only contain one row + attributes: HashMap, +} + +impl TableRow { + pub fn get_mut(&mut self, name: &str) -> &mut Vec { + let column = self.attributes.get_mut(name).unwrap(); + column.downcast_mut().unwrap() + } +} + + +#[derive(Clone)] +pub enum Attribute { + String(Vec), + U32(Vec), + Segment(Vec), + Region(Vec), + //Custom(DynAttribute), +} + +impl Attribute { + pub fn len(&self) -> usize { + match self { + Attribute::String(items) => items.len(), + Attribute::U32(items) => items.len(), + _ => todo!(), + } + } + pub fn is_empty(&self) -> bool { + match self { + Attribute::String(items) => items.is_empty(), + Attribute::U32(items) => items.is_empty(), + _ => todo!(), + } + } + pub fn push(&mut self, value: Option<&Attribute>) { + match (self, value) { + (Attribute::String(items), None) => items.push(Default::default()), + (Attribute::String(items), Some(Attribute::String(value))) => { + items.push(value[0].clone()) + } + (Attribute::U32(items), None) => items.push(Default::default()), + (Attribute::U32(items), Some(Attribute::U32(value))) => items.push(value[0]), + _ => unreachable!(), + } + } + pub fn append(&mut self, value: &mut Attribute) { + match (self, value) { + (Attribute::String(items), Attribute::String(value)) => items.append(value), + (Attribute::U32(items), Attribute::U32(value)) => items.append(value), + _ => unreachable!(), + } + } + fn our_type_id(&mut self) -> TypeId { + match self { + Attribute::String(_) => TypeId::of::(), + Attribute::U32(_) => TypeId::of::(), + _ => todo!(), + } + } + pub fn downcast_mut(&mut self) -> Option<&mut Vec> { + if self.our_type_id() != TypeId::of::() { + return None; + } + match self { + Attribute::String(items) => Some(unsafe { &mut *(items.as_mut_ptr() as *mut Vec) }), + Attribute::U32(items) => Some(unsafe { &mut *(items.as_mut_ptr() as *mut Vec) }), + _ => todo!(), + } + } +} + +#[derive(Clone)] +pub struct Table { + // primary_name: String, + primary: Vec, + // Box> + attributes: HashMap>, +} + +impl Default for Table { + fn default() -> Self { + Self { + primary: Default::default(), + attributes: Default::default(), + } + } +} +#[derive(Clone, Default)] +pub struct LazyTable { + previous: Option>>, + start_index: usize, + current: Arc>, +} + + +impl LazyTable { + pub fn flatten(&self) -> Table { + let Some(previous) = &self.previous else { + return Table::clone(self.current.as_ref()); + }; + let mut previous = previous.flatten(); + // todo fix + previous.append(Table::clone(self.current.as_ref())); + previous + } + pub fn len(&self) -> usize { + self.start_index + self.current.primary.len() + } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + pub fn append_lazy(self: Arc, table: Table) -> LazyTable + where + T: Clone, + { + let mut new_attributes = HashMap::new(); + let start_index = self.len(); + for name in self.current.attributes.keys() { + let value = table.attributes.get(name).unwrap().clone(); + + new_attributes.insert(name.clone(), value); + } + LazyTable { + previous: Some(self), + start_index, + current: Arc::new(Table { + primary: table.primary, + attributes: new_attributes, + }), + } + } +} + +impl From> for LazyTable { + fn from(value: Table) -> Self { + LazyTable { + current: Arc::new(value), + ..Default::default() + } + } +} + +impl Table { + pub fn get_column_mut(&mut self, name: &str) -> &mut Vec { + let column = self.attributes.get_mut(name).unwrap(); + Arc::make_mut(column).downcast_mut().unwrap() + } + // TODO: optimize + pub fn append_scalar(&mut self, scalar: TableRow>) + where + Table: Into, + { + self.primary.push(scalar.primary.into()); + for (name, value) in self.attributes.iter_mut() { + let old_value = scalar.attributes.get(name); + Arc::make_mut(value).push(old_value); + } + } + pub fn append(&mut self, mut table: Table) { + self.primary.append(&mut table.primary); + for (name, value) in self.attributes.iter_mut() { + let mut old_value = table.attributes.get(name).unwrap().clone(); + + let old_value = Arc::make_mut(&mut old_value); + Arc::make_mut(value).append(old_value); + } + } + pub fn append_lazy(self: Arc, table: Table) -> LazyTable + where + T: Clone, + { + let mut new_attributes = HashMap::new(); + for name in self.attributes.keys() { + let value = table.attributes.get(name).unwrap().clone(); + + new_attributes.insert(name.clone(), value); + } + LazyTable { + previous: Some(Arc::new(Table::clone(self.as_ref()).into())), + start_index: self.primary.len(), + current: Arc::new(Table { + primary: table.primary, + attributes: new_attributes, + }), + } + } +} + +impl Table { + fn from_one(t: T) -> Self { + Table { + primary: vec![t], + attributes: Default::default(), + } + } +} + +pub fn change_blend_mode_group( + mut instance: TableRow, + blend_mode: BlendMode, +) -> TableRow { + instance.get_mut("blend_mode")[0] = blend_mode; + instance +} + +pub fn change_fill( + mut instance: TableRow>, + fill: String, +) -> TableRow> { + instance.primary.primary[0] = fill; + instance +} + +pub fn merge(table: LazyTable, value: TableRow>) -> LazyTable +where + Table: Into, +{ + // todo optimize + let mut table = table.flatten(); + + table.append_scalar(value); + table.into() +} + +pub fn vector_data_table( + points: LazyTable, + segments: LazyTable, + regions: LazyTable, +) -> LazyTable { + let mut attributes = HashMap::new(); + attributes.insert( + "segments".into(), + Arc::new(Attribute::Segment(segments.flatten().primary)), + ); + attributes.insert( + "regions".into(), + Arc::new(Attribute::Region(regions.flatten().primary)), + ); + Table { + primary: points.flatten().primary, + attributes, + } + .into() +} +```