1use std::collections::HashMap;
3use std::fmt;
4use std::fmt::Formatter;
5use std::hash::Hash;
6use std::vec::Vec;
7
8use derive_more::{Deref, DerefMut, Display, From, Into, TryFrom};
9
10use crate::error::Error;
11use crate::{ByteSpan, Span, parse};
12
13#[derive(Clone, Debug, Default)]
15pub struct Schematic<I> {
16 pub version: Version<I>,
17 pub vhdl_property: Option<VhdlProperty<I>>,
18 pub symbol_property: Option<SymbolProperty<I>>,
19 pub verilog_property: Option<VerilogProperty<I>>,
20 pub spice_property: Option<SpiceProperty<I>>,
21 pub tedax_property: Option<TedaXProperty<I>>,
22 pub texts: Objects<Text<I>>,
23 pub lines: Objects<Line<I>>,
24 pub rectangles: Objects<Rectangle<I>>,
25 pub polygons: Objects<Polygon<I>>,
26 pub arcs: Objects<Arc<I>>,
27 pub wires: Objects<Wire<I>>,
28 pub components: Objects<Component<I>>,
29}
30
31#[derive(Clone, Debug, Default, Display)]
33#[display("{{{prop}}}")]
34pub struct Property<I> {
35 pub prop: I,
37 pub attrs: HashMap<I, I>,
39}
40
41#[derive(Clone, Debug, Default, Display)]
43#[display("v {_0}")]
44pub struct Version<I>(pub Property<I>);
45
46#[derive(Clone, Debug, Default, Deref, Display, From)]
47#[display("G {_0}")]
48pub struct VhdlProperty<I>(pub Property<I>);
49
50#[derive(Clone, Debug, Default, Deref, Display, From)]
51#[display("K {_0}")]
52pub struct SymbolProperty<I>(pub Property<I>);
53
54#[derive(Clone, Debug, Default, Deref, Display, From)]
55#[display("V {_0}")]
56pub struct VerilogProperty<I>(pub Property<I>);
57
58#[derive(Clone, Debug, Default, Deref, Display, From)]
59#[display("S {_0}")]
60pub struct SpiceProperty<I>(pub Property<I>);
61
62#[derive(Clone, Debug, Default, Deref, Display, From)]
63#[display("E {_0}")]
64pub struct TedaXProperty<I>(pub Property<I>);
65
66#[derive(Clone, Debug, From)]
67#[from(forward)]
68#[allow(clippy::large_enum_variant)]
69pub enum Object<I> {
70 SpiceProperty(SpiceProperty<I>),
71 VerilogProperty(VerilogProperty<I>),
72 VhdlProperty(VhdlProperty<I>),
73 TedaXProperty(TedaXProperty<I>),
74 SymbolProperty(SymbolProperty<I>),
75
76 Arc(Arc<I>),
77 Component(Component<I>),
78 Line(Line<I>),
79 Polygon(Polygon<I>),
80 Rectangle(Rectangle<I>),
81 Text(Text<I>),
82 Wire(Wire<I>),
83}
84
85#[derive(Clone, Debug, Deref, DerefMut, From, Into, PartialEq)]
86pub struct Objects<O>(pub Vec<O>);
87
88#[derive(Clone, Debug, Default, Display)]
90#[display("A {layer} {center} {radius} {start_angle} {sweep_angle} {property}")]
91pub struct Arc<I> {
92 pub layer: u64,
93 pub center: Coordinate,
94 pub radius: FiniteDouble,
95 pub start_angle: FiniteDouble,
96 pub sweep_angle: FiniteDouble,
97 pub property: Property<I>,
98}
99
100#[derive(Clone, Debug, Default)]
102pub struct Component<I> {
103 pub reference: I,
104 pub position: Coordinate,
105 pub rotation: Rotation,
106 pub flip: Flip,
107 pub property: Property<I>,
108 pub embedding: Option<Embedding<I>>,
109}
110
111#[derive(Clone, Debug, Default, Display)]
113#[display("L {layer} {start} {end} {property}")]
114pub struct Line<I> {
115 pub layer: u64,
116 pub start: Coordinate,
117 pub end: Coordinate,
118 pub property: Property<I>,
119}
120
121#[derive(Clone, Debug, Default, Display)]
123#[display("P {layer} {npoints} {points} {property}", npoints = points.len())]
124pub struct Polygon<I> {
125 pub layer: u64,
126 pub points: Coordinates,
127 pub property: Property<I>,
128}
129
130#[derive(Clone, Debug, Default, Display)]
132#[display("B {layer} {start} {end} {property}")]
133pub struct Rectangle<I> {
134 pub layer: u64,
135 pub start: Coordinate,
136 pub end: Coordinate,
137 pub property: Property<I>,
138}
139
140#[derive(Clone, Debug, Default, Display)]
142#[display("T {{{text}}} {position} {rotation} {flip} {size} {property}")]
143pub struct Text<I> {
144 pub text: I,
145 pub position: Coordinate,
146 pub rotation: Rotation,
147 pub flip: Flip,
148 pub size: Size,
149 pub property: Property<I>,
150}
151
152#[derive(Clone, Debug, Default, Display)]
154#[display("N {start} {end} {property}")]
155pub struct Wire<I> {
156 pub start: Coordinate,
157 pub end: Coordinate,
158 pub property: Property<I>,
159}
160
161#[derive(Clone, Debug, Default, Deref, Display, From, Into)]
162#[display("[\n{_0}\n]")]
163pub struct Embedding<I>(pub Schematic<I>);
164
165#[derive(Clone, Copy, Debug, Default, Deref, Display, Into, PartialEq, PartialOrd)]
167pub struct FiniteDouble(f64);
168
169#[derive(Clone, Copy, Debug, Default, Display, From, Into, PartialEq, PartialOrd)]
170#[from((FiniteDouble, FiniteDouble))]
171#[into((FiniteDouble, FiniteDouble))]
172#[display("{x} {y}")]
173pub struct Vec2 {
174 pub x: FiniteDouble,
175 pub y: FiniteDouble,
176}
177
178pub type Coordinate = Vec2;
179pub type Size = Vec2;
180
181#[derive(Clone, Debug, Default, Deref, DerefMut, From, Into, PartialEq)]
182pub struct Coordinates(pub Vec<Coordinate>);
183
184#[derive(Clone, Copy, Debug, Default, Display, PartialEq, Eq, PartialOrd, Ord, TryFrom)]
185#[try_from(repr)]
186#[repr(u8)]
187pub enum Rotation {
188 #[default]
189 #[display("0")]
190 Zero,
191 #[display("1")]
192 One,
193 #[display("2")]
194 Two,
195 #[display("3")]
196 Three,
197}
198
199#[derive(Clone, Copy, Debug, Default, Display, PartialEq, Eq, PartialOrd, Ord, TryFrom)]
200#[try_from(repr)]
201#[repr(u8)]
202pub enum Flip {
203 #[default]
204 #[display("0")]
205 Unflipped,
206 #[display("1")]
207 Flipped,
208}
209
210impl<'a, X: Clone + Default> TryFrom<&'a str> for Schematic<Span<'a, X>> {
211 type Error = Error<Span<'a, X>>;
212
213 fn try_from(value: &'a str) -> Result<Self, Self::Error> {
215 Self::try_from(Span::new_extra(value, X::default()))
216 }
217}
218
219impl<'a, X: Clone + Default> TryFrom<&'a [u8]> for Schematic<ByteSpan<'a, X>> {
220 type Error = Error<ByteSpan<'a, X>>;
221
222 fn try_from(value: &'a [u8]) -> Result<Self, Self::Error> {
224 Self::try_from(ByteSpan::new_extra(value, X::default()))
225 }
226}
227
228impl<'a, X: Clone> TryFrom<Span<'a, X>> for Schematic<Span<'a, X>> {
229 type Error = Error<Span<'a, X>>;
230
231 fn try_from(value: Span<'a, X>) -> Result<Self, Self::Error> {
233 parse::schematic_full(value)
234 }
235}
236
237impl<'a, X: Clone> TryFrom<ByteSpan<'a, X>> for Schematic<ByteSpan<'a, X>> {
238 type Error = Error<ByteSpan<'a, X>>;
239
240 fn try_from(value: ByteSpan<'a, X>) -> Result<Self, Self::Error> {
242 parse::schematic_full(value)
243 }
244}
245
246impl<I> fmt::Display for Schematic<I>
247where
248 I: fmt::Display,
249{
250 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
251 write!(f, "{}", self.version)?;
252 if let Some(p) = &self.vhdl_property {
253 write!(f, "\n{p}")?;
254 }
255 if let Some(p) = &self.symbol_property {
256 write!(f, "\n{p}")?;
257 }
258 if let Some(p) = &self.verilog_property {
259 write!(f, "\n{p}")?;
260 }
261 if let Some(p) = &self.spice_property {
262 write!(f, "\n{p}")?;
263 }
264 if let Some(p) = &self.tedax_property {
265 write!(f, "\n{p}")?;
266 }
267 if !self.texts.is_empty() {
268 write!(f, "\n{}", self.texts)?;
269 }
270 if !self.lines.is_empty() {
271 write!(f, "\n{}", self.lines)?;
272 }
273 if !self.rectangles.is_empty() {
274 write!(f, "\n{}", self.rectangles)?;
275 }
276 if !self.polygons.is_empty() {
277 write!(f, "\n{}", self.polygons)?;
278 }
279 if !self.arcs.is_empty() {
280 write!(f, "\n{}", self.arcs)?;
281 }
282 if !self.wires.is_empty() {
283 write!(f, "\n{}", self.wires)?;
284 }
285 if !self.components.is_empty() {
286 write!(f, "\n{}", self.components)?;
287 }
288 Ok(())
289 }
290}
291
292impl<'a> Schematic<Span<'a>> {
293 pub fn parse_str<I: AsRef<str> + ?Sized>(input: &'a I) -> Result<Self, Error<Span<'a>>> {
295 Self::try_from(input.as_ref())
296 }
297}
298
299impl<'a, X: Clone> Schematic<Span<'a, X>> {
300 pub fn parse_str_with_extra<I: AsRef<str> + ?Sized>(
302 input: &'a I,
303 extra: X,
304 ) -> Result<Self, Error<Span<'a, X>>> {
305 Self::try_from(Span::new_extra(input.as_ref(), extra))
306 }
307}
308
309impl<'a> Schematic<ByteSpan<'a>> {
310 pub fn parse_slice<I: AsRef<[u8]> + ?Sized>(input: &'a I) -> Result<Self, Error<ByteSpan<'a>>> {
312 Self::try_from(input.as_ref())
313 }
314}
315
316impl<'a, X: Clone> Schematic<ByteSpan<'a, X>> {
317 pub fn parse_slice_with_extra<I: AsRef<[u8]> + ?Sized>(
319 input: &'a I,
320 extra: X,
321 ) -> Result<Self, Error<ByteSpan<'a, X>>> {
322 Self::try_from(ByteSpan::new_extra(input.as_ref(), extra))
323 }
324}
325
326impl<'a, X: Clone> Schematic<Span<'a, X>> {
327 pub fn parse_span(input: Span<'a, X>) -> Result<Self, Error<Span<'a, X>>> {
329 Self::try_from(input)
330 }
331}
332
333impl<'a, X: Clone> Schematic<ByteSpan<'a, X>> {
334 pub fn parse_span(input: ByteSpan<'a, X>) -> Result<Self, Error<ByteSpan<'a, X>>> {
336 Self::try_from(input)
337 }
338}
339
340impl<I: PartialEq> PartialEq for Schematic<I>
341where
342 Property<I>: PartialEq,
343{
344 fn eq(&self, other: &Self) -> bool {
345 self.version == other.version
346 && self.vhdl_property == other.vhdl_property
347 && self.symbol_property == other.symbol_property
348 && self.verilog_property == other.verilog_property
349 && self.spice_property == other.spice_property
350 && self.tedax_property == other.tedax_property
351 && self.texts == other.texts
352 && self.lines == other.lines
353 && self.rectangles == other.rectangles
354 && self.polygons == other.polygons
355 && self.arcs == other.arcs
356 && self.wires == other.wires
357 && self.components == other.components
358 }
359}
360
361impl<I> Schematic<I> {
362 pub fn new(version: Version<I>) -> Self {
363 Self {
364 version,
365 vhdl_property: Option::default(),
366 symbol_property: Option::default(),
367 verilog_property: Option::default(),
368 spice_property: Option::default(),
369 tedax_property: Option::default(),
370 texts: Objects::default(),
371 lines: Objects::default(),
372 rectangles: Objects::default(),
373 polygons: Objects::default(),
374 arcs: Objects::default(),
375 wires: Objects::default(),
376 components: Objects::default(),
377 }
378 }
379
380 #[must_use]
381 pub fn add_object(mut self, object: Object<I>) -> Self {
382 match object {
383 Object::VhdlProperty(p) => {
384 self.vhdl_property.replace(p);
385 }
386 Object::SymbolProperty(p) => {
387 self.symbol_property.replace(p);
388 }
389 Object::VerilogProperty(p) => {
390 self.verilog_property.replace(p);
391 }
392 Object::SpiceProperty(p) => {
393 self.spice_property.replace(p);
394 }
395 Object::TedaXProperty(p) => {
396 self.tedax_property.replace(p);
397 }
398 Object::Arc(o) => {
399 self.arcs.push(o);
400 }
401 Object::Component(o) => {
402 self.components.push(o);
403 }
404 Object::Line(o) => {
405 self.lines.push(o);
406 }
407 Object::Polygon(o) => {
408 self.polygons.push(o);
409 }
410 Object::Rectangle(o) => {
411 self.rectangles.push(o);
412 }
413 Object::Text(o) => {
414 self.texts.push(o);
415 }
416 Object::Wire(o) => {
417 self.wires.push(o);
418 }
419 }
420
421 self
422 }
423}
424
425impl<I: Eq + Hash + PartialEq> PartialEq for Property<I> {
426 fn eq(&self, other: &Self) -> bool {
427 self.prop == other.prop && self.attrs == other.attrs
428 }
429}
430
431impl<I> PartialEq for Version<I>
432where
433 Property<I>: PartialEq,
434{
435 fn eq(&self, other: &Self) -> bool {
436 self.0 == other.0
437 }
438}
439
440impl<I> PartialEq for SpiceProperty<I>
441where
442 Property<I>: PartialEq,
443{
444 fn eq(&self, other: &Self) -> bool {
445 self.0 == other.0
446 }
447}
448
449impl<I> PartialEq for VerilogProperty<I>
450where
451 Property<I>: PartialEq,
452{
453 fn eq(&self, other: &Self) -> bool {
454 self.0 == other.0
455 }
456}
457
458impl<I> PartialEq for VhdlProperty<I>
459where
460 Property<I>: PartialEq,
461{
462 fn eq(&self, other: &Self) -> bool {
463 self.0 == other.0
464 }
465}
466
467impl<I> PartialEq for TedaXProperty<I>
468where
469 Property<I>: PartialEq,
470{
471 fn eq(&self, other: &Self) -> bool {
472 self.0 == other.0
473 }
474}
475
476impl<I> PartialEq for SymbolProperty<I>
477where
478 Property<I>: PartialEq,
479{
480 fn eq(&self, other: &Self) -> bool {
481 self.0 == other.0
482 }
483}
484
485impl<I> PartialEq for Arc<I>
486where
487 Property<I>: PartialEq,
488{
489 fn eq(&self, other: &Self) -> bool {
490 self.layer == other.layer
491 && self.center == other.center
492 && self.radius == other.radius
493 && self.start_angle == other.start_angle
494 && self.sweep_angle == other.sweep_angle
495 && self.property == other.property
496 }
497}
498
499impl<I> fmt::Display for Component<I>
500where
501 I: fmt::Display,
502{
503 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
504 let Self {
505 reference,
506 position,
507 rotation,
508 flip,
509 property,
510 embedding,
511 } = self;
512 write!(
513 f,
514 "C {{{reference}}} {position} {rotation} {flip} {property}"
515 )?;
516 if let Some(e) = embedding {
517 write!(f, "\n{e}")?;
518 }
519 Ok(())
520 }
521}
522
523impl<I: PartialEq> PartialEq for Component<I>
524where
525 Property<I>: PartialEq,
526{
527 fn eq(&self, other: &Self) -> bool {
528 self.reference == other.reference
529 && self.position == other.position
530 && self.rotation == other.rotation
531 && self.flip == other.flip
532 && self.property == other.property
533 && self.embedding == other.embedding
534 }
535}
536
537impl<I> PartialEq for Line<I>
538where
539 Property<I>: PartialEq,
540{
541 fn eq(&self, other: &Self) -> bool {
542 self.layer == other.layer
543 && self.start == other.start
544 && self.end == other.end
545 && self.property == other.property
546 }
547}
548
549impl<I> PartialEq for Polygon<I>
550where
551 Property<I>: PartialEq,
552{
553 fn eq(&self, other: &Self) -> bool {
554 self.layer == other.layer && self.points == other.points && self.property == other.property
555 }
556}
557
558impl<I> PartialEq for Rectangle<I>
559where
560 Property<I>: PartialEq,
561{
562 fn eq(&self, other: &Self) -> bool {
563 self.layer == other.layer
564 && self.start == other.start
565 && self.end == other.end
566 && self.property == other.property
567 }
568}
569
570impl<I: PartialEq> PartialEq for Text<I>
571where
572 Property<I>: PartialEq,
573{
574 fn eq(&self, other: &Self) -> bool {
575 self.text == other.text
576 && self.position == other.position
577 && self.rotation == other.rotation
578 && self.flip == other.flip
579 && self.size == other.size
580 && self.property == other.property
581 }
582}
583
584impl<I> PartialEq for Wire<I>
585where
586 Property<I>: PartialEq,
587{
588 fn eq(&self, other: &Self) -> bool {
589 self.start == other.start && self.end == other.end && self.property == other.property
590 }
591}
592
593impl<I: PartialEq> PartialEq for Embedding<I>
594where
595 Property<I>: PartialEq,
596{
597 fn eq(&self, other: &Self) -> bool {
598 self.0 == other.0
599 }
600}
601
602impl<O> Default for Objects<O> {
603 fn default() -> Self {
604 Self(Vec::default())
605 }
606}
607
608impl<O: fmt::Display> fmt::Display for Objects<O> {
609 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
610 self.iter().enumerate().try_for_each(
611 |(i, o)| {
612 if i == 0 { o.fmt(f) } else { write!(f, "\n{o}") }
613 },
614 )
615 }
616}
617
618impl fmt::Display for Coordinates {
619 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
620 self.iter().enumerate().try_for_each(
621 |(i, c)| {
622 if i == 0 { c.fmt(f) } else { write!(f, " {c}") }
623 },
624 )
625 }
626}
627
628impl TryFrom<f64> for FiniteDouble {
629 type Error = &'static str;
630
631 fn try_from(value: f64) -> Result<Self, Self::Error> {
632 if value.is_finite() {
633 Ok(Self(value))
634 } else {
635 Err("value is not finite")
636 }
637 }
638}
639
640impl Eq for FiniteDouble {}
641
642impl TryFrom<(f64, f64)> for Vec2 {
643 type Error = <FiniteDouble as TryFrom<f64>>::Error;
644
645 fn try_from(value: (f64, f64)) -> Result<Self, Self::Error> {
646 let (x, y) = value;
647 let x = x.try_into()?;
648 let y = y.try_into()?;
649 Ok(Self { x, y })
650 }
651}
652
653impl<T> From<Vec<(T, T)>> for Coordinates
654where
655 Vec2: From<(T, T)>,
656{
657 fn from(value: Vec<(T, T)>) -> Self {
658 Self(value.into_iter().map(Vec2::from).collect())
659 }
660}
661
662impl FromIterator<Vec2> for Coordinates {
663 fn from_iter<T: IntoIterator<Item = Vec2>>(iter: T) -> Self {
664 Self(iter.into_iter().collect())
665 }
666}
667
668impl TryFrom<Vec<(f64, f64)>> for Coordinates {
669 type Error = <Vec2 as TryFrom<(f64, f64)>>::Error;
670
671 fn try_from(value: Vec<(f64, f64)>) -> Result<Self, Self::Error> {
672 value.into_iter().map(Vec2::try_from).collect()
673 }
674}
675
676impl From<Rotation> for u8 {
677 fn from(value: Rotation) -> Self {
678 match value {
679 Rotation::Zero => 0,
680 Rotation::One => 1,
681 Rotation::Two => 2,
682 Rotation::Three => 3,
683 }
684 }
685}
686
687impl From<bool> for Flip {
688 fn from(value: bool) -> Self {
689 if value {
690 Flip::Flipped
691 } else {
692 Flip::Unflipped
693 }
694 }
695}
696
697impl From<Flip> for bool {
698 fn from(value: Flip) -> Self {
699 match value {
700 Flip::Unflipped => false,
701 Flip::Flipped => true,
702 }
703 }
704}