Skip to main content

brdb/wrapper/
wire.rs

1use std::fmt::Display;
2
3use crate::{
4    BrdbSchemaError,
5    schema::{
6        BrdbValue,
7        as_brdb::{AsBrdbIter, AsBrdbValue, BrdbArrayIter},
8    },
9    wrapper::{BString, BitFlags, ChunkIndex},
10};
11
12pub struct LocalWirePortSource {
13    pub brick_index_in_chunk: u32,
14    pub component_type_index: u16,
15    pub port_index: u16,
16}
17
18impl AsBrdbValue for LocalWirePortSource {
19    fn as_brdb_struct_prop_value(
20        &self,
21        schema: &crate::schema::BrdbSchema,
22        _struct_name: crate::schema::BrdbInterned,
23        prop_name: crate::schema::BrdbInterned,
24    ) -> Result<&dyn AsBrdbValue, BrdbSchemaError> {
25        let field = prop_name.get(schema).unwrap();
26        match field {
27            "BrickIndexInChunk" => Ok(&self.brick_index_in_chunk),
28            "ComponentTypeIndex" => Ok(&self.component_type_index),
29            "PortIndex" => Ok(&self.port_index),
30            n => unimplemented!("unimplemented struct field {n}"),
31        }
32    }
33}
34
35impl TryFrom<&BrdbValue> for LocalWirePortSource {
36    type Error = BrdbSchemaError;
37
38    fn try_from(value: &BrdbValue) -> Result<Self, Self::Error> {
39        Ok(Self {
40            brick_index_in_chunk: value.prop("BrickIndexInChunk")?.as_brdb_u32()?,
41            component_type_index: value.prop("ComponentTypeIndex")?.as_brdb_u16()?,
42            port_index: value.prop("PortIndex")?.as_brdb_u16()?,
43        })
44    }
45}
46
47pub struct RemoteWirePortSource {
48    pub grid_persistent_index: u32,
49    pub chunk_index: ChunkIndex,
50    pub brick_index_in_chunk: u32,
51    pub component_type_index: u16,
52    pub port_index: u16,
53}
54impl AsBrdbValue for RemoteWirePortSource {
55    fn as_brdb_struct_prop_value(
56        &self,
57        schema: &crate::schema::BrdbSchema,
58        _struct_name: crate::schema::BrdbInterned,
59        prop_name: crate::schema::BrdbInterned,
60    ) -> Result<&dyn AsBrdbValue, BrdbSchemaError> {
61        let field = prop_name.get(schema).unwrap();
62        match field {
63            "GridPersistentIndex" => Ok(&self.grid_persistent_index),
64            "ChunkIndex" => Ok(&self.chunk_index),
65            "BrickIndexInChunk" => Ok(&self.brick_index_in_chunk),
66            "ComponentTypeIndex" => Ok(&self.component_type_index),
67            "PortIndex" => Ok(&self.port_index),
68            n => unimplemented!("unimplemented struct field {n}"),
69        }
70    }
71}
72impl TryFrom<&BrdbValue> for RemoteWirePortSource {
73    type Error = BrdbSchemaError;
74
75    fn try_from(value: &BrdbValue) -> Result<Self, Self::Error> {
76        Ok(Self {
77            grid_persistent_index: value.prop("GridPersistentIndex")?.as_brdb_u32()?,
78            chunk_index: value.prop("ChunkIndex")?.try_into()?,
79            brick_index_in_chunk: value.prop("BrickIndexInChunk")?.as_brdb_u32()?,
80            component_type_index: value.prop("ComponentTypeIndex")?.as_brdb_u16()?,
81            port_index: value.prop("PortIndex")?.as_brdb_u16()?,
82        })
83    }
84}
85
86pub struct WirePortTarget {
87    pub brick_index_in_chunk: u32,
88    pub component_type_index: u16,
89    pub port_index: u16,
90}
91impl AsBrdbValue for WirePortTarget {
92    fn as_brdb_struct_prop_value(
93        &self,
94        schema: &crate::schema::BrdbSchema,
95        _struct_name: crate::schema::BrdbInterned,
96        prop_name: crate::schema::BrdbInterned,
97    ) -> Result<&dyn AsBrdbValue, BrdbSchemaError> {
98        let field = prop_name.get(schema).unwrap();
99        match field {
100            "BrickIndexInChunk" => Ok(&self.brick_index_in_chunk),
101            "ComponentTypeIndex" => Ok(&self.component_type_index),
102            "PortIndex" => Ok(&self.port_index),
103            n => unimplemented!("unimplemented struct field {n}"),
104        }
105    }
106}
107impl TryFrom<&BrdbValue> for WirePortTarget {
108    type Error = BrdbSchemaError;
109
110    fn try_from(value: &BrdbValue) -> Result<Self, Self::Error> {
111        Ok(Self {
112            brick_index_in_chunk: value.prop("BrickIndexInChunk")?.as_brdb_u32()?,
113            component_type_index: value.prop("ComponentTypeIndex")?.as_brdb_u16()?,
114            port_index: value.prop("PortIndex")?.as_brdb_u16()?,
115        })
116    }
117}
118
119#[derive(Default)]
120pub struct WireChunkSoA {
121    pub remote_wire_sources: Vec<RemoteWirePortSource>,
122    pub local_wire_sources: Vec<LocalWirePortSource>,
123    pub remote_wire_targets: Vec<WirePortTarget>,
124    pub local_wire_targets: Vec<WirePortTarget>,
125    pub pending_propagation_flags: BitFlags,
126}
127impl AsBrdbValue for WireChunkSoA {
128    fn as_brdb_struct_prop_value(
129        &self,
130        schema: &crate::schema::BrdbSchema,
131        _struct_name: crate::schema::BrdbInterned,
132        prop_name: crate::schema::BrdbInterned,
133    ) -> Result<&dyn AsBrdbValue, BrdbSchemaError> {
134        match prop_name.get(schema).unwrap() {
135            "PendingPropagationFlags" => Ok(&self.pending_propagation_flags),
136            n => unimplemented!("unimplemented struct field {n}"),
137        }
138    }
139    fn as_brdb_struct_prop_array(
140        &self,
141        schema: &crate::schema::BrdbSchema,
142        _struct_name: crate::schema::BrdbInterned,
143        prop_name: crate::schema::BrdbInterned,
144    ) -> Result<BrdbArrayIter<'_>, BrdbSchemaError> {
145        match prop_name.get(schema).unwrap() {
146            "RemoteWireSources" => Ok(self.remote_wire_sources.as_brdb_iter()),
147            "LocalWireSources" => Ok(self.local_wire_sources.as_brdb_iter()),
148            "RemoteWireTargets" => Ok(self.remote_wire_targets.as_brdb_iter()),
149            "LocalWireTargets" => Ok(self.local_wire_targets.as_brdb_iter()),
150            n => unimplemented!("unimplemented struct field {n}"),
151        }
152    }
153}
154impl TryFrom<&BrdbValue> for WireChunkSoA {
155    type Error = BrdbSchemaError;
156
157    fn try_from(value: &BrdbValue) -> Result<Self, Self::Error> {
158        Ok(Self {
159            remote_wire_sources: value
160                .prop("RemoteWireSources")?
161                .try_into()
162                .map_err(|e: BrdbSchemaError| e.wrap("RemoteWireSources"))?,
163            local_wire_sources: value
164                .prop("LocalWireSources")?
165                .try_into()
166                .map_err(|e: BrdbSchemaError| e.wrap("LocalWireSources"))?,
167            remote_wire_targets: value
168                .prop("RemoteWireTargets")?
169                .try_into()
170                .map_err(|e: BrdbSchemaError| e.wrap("RemoteWireTargets"))?,
171            local_wire_targets: value
172                .prop("LocalWireTargets")?
173                .try_into()
174                .map_err(|e: BrdbSchemaError| e.wrap("LocalWireTargets"))?,
175            pending_propagation_flags: value
176                .prop("PendingPropagationFlags")?
177                .try_into()
178                .map_err(|e: BrdbSchemaError| e.wrap("PendingPropagationFlags"))?,
179        })
180    }
181}
182
183impl WireChunkSoA {
184    pub fn add_local_wire(&mut self, source: LocalWirePortSource, target: WirePortTarget) {
185        self.local_wire_sources.push(source);
186        self.local_wire_targets.push(target);
187    }
188
189    pub fn add_remote_wire(&mut self, source: RemoteWirePortSource, target: WirePortTarget) {
190        self.remote_wire_sources.push(source);
191        self.remote_wire_targets.push(target);
192    }
193}
194
195#[derive(Debug, Clone)]
196pub struct WireConnection {
197    pub source: WirePort,
198    pub target: WirePort,
199}
200
201impl Display for WireConnection {
202    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
203        write!(f, "{} to {}", self.source, self.target)
204    }
205}
206
207impl WireConnection {
208    pub fn new(source: WirePort, target: WirePort) -> Self {
209        Self { source, target }
210    }
211}
212
213#[derive(Debug, Clone)]
214pub struct WirePort {
215    /// The remote brick where the port is located
216    pub brick_id: usize,
217    /// Name of the component in the brick to connect
218    pub component_type: BString,
219    /// Name of the port in the component to connect
220    pub port_name: BString,
221}
222
223impl WirePort {
224    pub fn new(
225        brick_id: usize,
226        component_type: impl Into<BString>,
227        port_name: impl Into<BString>,
228    ) -> Self {
229        Self {
230            brick_id,
231            component_type: component_type.into(),
232            port_name: port_name.into(),
233        }
234    }
235}
236
237impl Display for WirePort {
238    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
239        write!(
240            f,
241            "brick {} {}.{}",
242            self.brick_id, self.component_type, self.port_name
243        )
244    }
245}