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 pub brick_id: usize,
217 pub component_type: BString,
219 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}