Skip to main content

altium_format/ops/
output.rs

1// SPDX-License-Identifier: GPL-3.0-only
2// SPDX-FileCopyrightText: 2026 Alexander Kiselev <alex@akiselev.com>
3//
4//! Output data structures for ops functions.
5//!
6//! This module defines structured data types returned by ops functions,
7//! allowing separation of business logic from presentation.
8
9use serde::{Deserialize, Serialize};
10use std::collections::HashMap;
11
12// ═══════════════════════════════════════════════════════════════════════════
13// INTLIB OUTPUT TYPES
14// ═══════════════════════════════════════════════════════════════════════════
15
16#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct IntLibOverview {
18    pub path: String,
19    pub version: u32,
20    pub component_count: usize,
21    pub schematic_symbol_count: usize,
22    pub pcb_footprint_count: usize,
23    pub parameter_set_count: usize,
24    pub footprint_usage: Vec<(String, usize)>, // (footprint_name, count)
25    pub component_list: Vec<ComponentCrossRef>,
26    // Full details (only populated when --full is requested)
27    #[serde(skip_serializing_if = "Option::is_none")]
28    pub symbols: Option<Vec<SymbolSummary>>,
29    #[serde(skip_serializing_if = "Option::is_none")]
30    pub footprints: Option<Vec<FootprintSummary>>,
31    #[serde(skip_serializing_if = "Option::is_none")]
32    pub parameters: Option<Vec<ComponentParameters>>,
33}
34
35#[derive(Debug, Clone, Serialize, Deserialize)]
36pub struct ComponentCrossRef {
37    pub name: String,
38    pub description: String,
39    pub footprint: String,
40}
41
42#[derive(Debug, Clone, Serialize, Deserialize)]
43pub struct IntLibInfo {
44    pub path: String,
45    pub version: u32,
46    pub cross_ref_count: usize,
47    pub schematic_symbol_count: usize,
48    pub pcb_footprint_count: usize,
49    pub parameter_set_count: usize,
50}
51
52#[derive(Debug, Clone, Serialize, Deserialize)]
53pub struct IntLibComponentDetail {
54    pub name: String,
55    pub description: String,
56    pub footprint: String,
57    pub schlib_path: String,
58    pub pcblib_path: String,
59    pub symbol_info: Option<SymbolInfo>,
60    pub footprint_info: Option<FootprintInfo>,
61    pub parameters: Option<HashMap<String, String>>,
62}
63
64#[derive(Debug, Clone, Serialize, Deserialize)]
65pub struct SymbolInfo {
66    pub pin_count: usize,
67    pub primitive_count: usize,
68}
69
70#[derive(Debug, Clone, Serialize, Deserialize)]
71pub struct FootprintInfo {
72    pub pad_count: usize,
73    pub primitive_count: usize,
74}
75
76#[derive(Debug, Clone, Serialize, Deserialize)]
77pub struct IntLibSearchResults {
78    pub query: String,
79    pub total_matches: usize,
80    pub results: Vec<ComponentCrossRef>,
81}
82
83#[derive(Debug, Clone, Serialize, Deserialize)]
84pub struct IntLibComponentList {
85    pub components: Vec<ComponentCrossRef>,
86}
87
88#[derive(Debug, Clone, Serialize, Deserialize)]
89pub struct IntLibSymbolList {
90    pub symbols: Vec<SymbolSummary>,
91}
92
93#[derive(Debug, Clone, Serialize, Deserialize)]
94pub struct SymbolSummary {
95    pub name: String,
96    pub description: String,
97    pub pin_count: usize,
98}
99
100#[derive(Debug, Clone, Serialize, Deserialize)]
101pub struct IntLibFootprintList {
102    pub footprints: Vec<FootprintSummary>,
103}
104
105#[derive(Debug, Clone, Serialize, Deserialize)]
106pub struct FootprintSummary {
107    pub name: String,
108    pub description: String,
109    pub pad_count: usize,
110}
111
112#[derive(Debug, Clone, Serialize, Deserialize)]
113pub struct IntLibParameterList {
114    pub parameters: Vec<ComponentParameters>,
115}
116
117#[derive(Debug, Clone, Serialize, Deserialize)]
118pub struct ComponentParameters {
119    pub component_name: String,
120    pub params: HashMap<String, String>,
121}
122
123// ═══════════════════════════════════════════════════════════════════════════
124// SCHLIB OUTPUT TYPES
125// ═══════════════════════════════════════════════════════════════════════════
126
127#[derive(Debug, Clone, Serialize, Deserialize)]
128pub struct SchLibOverview {
129    pub path: String,
130    pub total_components: usize,
131    pub components_by_category: Vec<(String, Vec<ComponentSummary>)>,
132    pub pin_statistics: PinStatistics,
133    pub multi_part_components: Vec<ComponentSummary>,
134    pub largest_components: Vec<ComponentSummary>,
135    // Full details (only populated when --full is requested)
136    #[serde(skip_serializing_if = "Option::is_none")]
137    pub component_details: Option<Vec<SchLibComponentDetail>>,
138}
139
140#[derive(Debug, Clone, Serialize, Deserialize)]
141pub struct ComponentSummary {
142    pub name: String,
143    pub description: String,
144    pub pin_count: usize,
145    pub part_count: i32,
146}
147
148#[derive(Debug, Clone, Serialize, Deserialize)]
149pub struct PinStatistics {
150    pub total_pins: usize,
151    pub pin_types: Vec<(String, usize)>, // (type_name, count)
152}
153
154#[derive(Debug, Clone, Serialize, Deserialize)]
155pub struct SchLibComponentList {
156    pub path: String,
157    pub total_components: usize,
158    pub components: Vec<ComponentSummary>,
159}
160
161#[derive(Debug, Clone, Serialize, Deserialize)]
162pub struct SchLibSearchResults {
163    pub query: String,
164    pub total_matches: usize,
165    pub results: Vec<ComponentSummary>,
166}
167
168#[derive(Debug, Clone, Serialize, Deserialize)]
169pub struct SchLibInfo {
170    pub path: String,
171    pub component_count: usize,
172    pub total_primitives: usize,
173    pub primitive_types: Vec<(String, usize)>, // (type_name, count)
174    pub multi_part_count: usize,
175}
176
177#[derive(Debug, Clone, Serialize, Deserialize)]
178pub struct SchLibComponentDetail {
179    pub name: String,
180    pub description: String,
181    pub part_count: i32,
182    pub display_mode_count: i32,
183    pub pin_count: usize,
184    pub total_primitives: usize,
185    pub pins: Vec<PinDetail>,
186    pub primitive_counts: Option<Vec<(String, usize)>>,
187}
188
189#[derive(Debug, Clone, Serialize, Deserialize)]
190pub struct PinDetail {
191    pub designator: String,
192    pub name: String,
193    pub electrical_type: String,
194    pub description: String,
195}
196
197#[derive(Debug, Clone, Serialize, Deserialize)]
198pub struct SchLibPinList {
199    pub path: String,
200    pub total_pins: usize,
201    pub pins: Vec<PinWithComponent>,
202    pub pins_by_type: Option<Vec<(String, Vec<PinWithComponent>)>>,
203}
204
205#[derive(Debug, Clone, Serialize, Deserialize)]
206pub struct PinWithComponent {
207    pub component_name: String,
208    pub designator: String,
209    pub name: String,
210    pub electrical_type: String,
211}
212
213#[derive(Debug, Clone, Serialize, Deserialize)]
214pub struct SchLibPrimitiveList {
215    pub component_name: String,
216    pub total_primitives: usize,
217    pub primitives: Vec<PrimitiveInfo>,
218}
219
220#[derive(Debug, Clone, Serialize, Deserialize)]
221#[serde(tag = "type")]
222pub enum PrimitiveInfo {
223    Pin {
224        designator: String,
225        name: String,
226        electrical_type: String,
227        x: String,
228        y: String,
229    },
230    Rectangle {
231        x1: String,
232        y1: String,
233        x2: String,
234        y2: String,
235    },
236    Line {
237        x1: String,
238        y1: String,
239        x2: String,
240        y2: String,
241    },
242    Arc {
243        center_x: String,
244        center_y: String,
245        radius: String,
246        start_angle: f64,
247        end_angle: f64,
248    },
249    Polygon {
250        vertex_count: usize,
251    },
252    Polyline {
253        vertex_count: usize,
254    },
255    Label {
256        text: String,
257        x: String,
258        y: String,
259    },
260    Other {
261        primitive_type: String,
262    },
263}
264
265// ═══════════════════════════════════════════════════════════════════════════
266// PRJPCB OUTPUT TYPES
267// ═══════════════════════════════════════════════════════════════════════════
268
269#[derive(Debug, Clone, Serialize, Deserialize)]
270pub struct PrjPcbOverview {
271    pub path: String,
272    pub name: String,
273    pub version: String,
274    pub hierarchy_mode: String,
275    pub document_summary: DocumentSummary,
276    pub parameters: HashMap<String, String>,
277    pub component_summary: Option<ComponentSummaryStats>,
278}
279
280#[derive(Debug, Clone, Serialize, Deserialize)]
281pub struct DocumentSummary {
282    pub total_documents: usize,
283    pub schematics: Vec<DocumentInfo>,
284    pub pcb_documents: Vec<DocumentInfo>,
285    pub libraries: Vec<DocumentInfo>,
286    pub other: Vec<DocumentInfo>,
287}
288
289#[derive(Debug, Clone, Serialize, Deserialize)]
290pub struct DocumentInfo {
291    pub path: String,
292    pub doc_type: String,
293    pub exists: bool,
294}
295
296#[derive(Debug, Clone, Serialize, Deserialize)]
297pub struct ComponentSummaryStats {
298    pub total_components: usize,
299    pub by_prefix: Vec<(String, String, usize)>, // (prefix, display_name, count)
300}
301
302#[derive(Debug, Clone, Serialize, Deserialize)]
303pub struct PrjPcbInfo {
304    pub path: String,
305    pub name: String,
306    pub version: String,
307    pub hierarchy_mode: String,
308    pub output_path: String,
309    pub annotation_start: i32,
310    pub document_counts: Vec<(String, usize)>, // (type, count)
311    pub parameter_count: usize,
312    pub erc_matrix_rows: usize,
313}
314
315#[derive(Debug, Clone, Serialize, Deserialize)]
316pub struct PrjPcbDocumentList {
317    pub path: String,
318    pub filter: Option<String>,
319    pub total_documents: usize,
320    pub documents: Vec<DocumentDetailInfo>,
321}
322
323#[derive(Debug, Clone, Serialize, Deserialize)]
324pub struct DocumentDetailInfo {
325    pub path: String,
326    pub doc_type: String,
327    pub exists: bool,
328    pub annotation_enabled: bool,
329    pub library_update: bool,
330}
331
332#[derive(Debug, Clone, Serialize, Deserialize)]
333pub struct PrjPcbNetlist {
334    pub path: String,
335    pub total_nets: usize,
336    pub nets: Vec<NetInfo>,
337}
338
339#[derive(Debug, Clone, Serialize, Deserialize)]
340pub struct NetInfo {
341    pub name: String,
342    pub pins: Vec<NetPinConnection>,
343}
344
345#[derive(Debug, Clone, Serialize, Deserialize)]
346pub struct NetPinConnection {
347    pub component: String,
348    pub pin: String,
349}
350
351#[derive(Debug, Clone, Serialize, Deserialize)]
352pub struct PrjPcbComponentList {
353    pub path: String,
354    pub total_components: usize,
355    pub components: Vec<SchematicComponentInfo>,
356}
357
358#[derive(Debug, Clone, Serialize, Deserialize)]
359pub struct SchematicComponentInfo {
360    pub designator: String,
361    pub lib_reference: String,
362    pub description: String,
363    pub footprint: String,
364    pub value: String,
365    pub sheet: String,
366    pub parameters: HashMap<String, String>,
367}
368
369#[derive(Debug, Clone, Serialize, Deserialize)]
370pub struct PrjPcbBom {
371    pub path: String,
372    pub total_components: usize,
373    pub unique_parts: Option<usize>,
374    pub items: BomItems,
375}
376
377#[derive(Debug, Clone, Serialize, Deserialize)]
378#[serde(untagged)]
379pub enum BomItems {
380    Grouped(Vec<BomGroupItem>),
381    Individual(Vec<SchematicComponentInfo>),
382}
383
384#[derive(Debug, Clone, Serialize, Deserialize)]
385pub struct BomGroupItem {
386    pub lib_reference: String,
387    pub quantity: usize,
388    pub designators: Vec<String>,
389}
390
391#[derive(Debug, Clone, Serialize, Deserialize)]
392pub struct PrjPcbSchPcbDiff {
393    pub path: String,
394    pub pcb_document: String,
395    pub schematic_components: usize,
396    pub pcb_components: usize,
397    pub only_in_schematic: Vec<String>,
398    pub only_in_pcb: Vec<String>,
399    pub schematic_nets: usize,
400    pub pcb_nets: usize,
401    pub nets_only_in_schematic: Vec<String>,
402    pub nets_only_in_pcb: Vec<String>,
403}
404
405#[derive(Debug, Clone, Serialize, Deserialize)]
406pub struct PrjPcbValidation {
407    pub path: String,
408    pub errors: Vec<String>,
409    pub warnings: Vec<String>,
410}
411
412// ═══════════════════════════════════════════════════════════════════════════
413// PCBLIB OUTPUT TYPES
414// ═══════════════════════════════════════════════════════════════════════════
415
416#[derive(Debug, Clone, Serialize, Deserialize)]
417pub struct PcbLibOverview {
418    pub path: String,
419    pub total_footprints: usize,
420    pub unique_id: String,
421    pub footprints_by_category: Vec<(String, Vec<FootprintSummaryExt>)>,
422    pub pad_statistics: PadStatistics,
423    pub hole_sizes: Vec<(String, usize)>, // (size, count)
424    pub largest_footprints: Vec<FootprintSummaryExt>,
425}
426
427#[derive(Debug, Clone, Serialize, Deserialize)]
428pub struct FootprintSummaryExt {
429    pub name: String,
430    pub description: String,
431    pub pad_count: usize,
432}
433
434#[derive(Debug, Clone, Serialize, Deserialize)]
435pub struct PadStatistics {
436    pub total_pads: usize,
437    pub smd_pads: usize,
438    pub th_pads: usize,
439    pub pad_shapes: Vec<(String, usize)>, // (shape_name, count)
440}
441
442#[derive(Debug, Clone, Serialize, Deserialize)]
443pub struct PcbLibFootprintList {
444    pub path: String,
445    pub total_footprints: usize,
446    pub footprints: Vec<FootprintSummaryExt>,
447}
448
449#[derive(Debug, Clone, Serialize, Deserialize)]
450pub struct PcbLibSearchResults {
451    pub query: String,
452    pub total_matches: usize,
453    pub results: Vec<FootprintSummaryExt>,
454}
455
456#[derive(Debug, Clone, Serialize, Deserialize)]
457pub struct PcbLibInfo {
458    pub path: String,
459    pub footprint_count: usize,
460    pub unique_id: String,
461    pub total_primitives: usize,
462    pub primitive_types: Vec<(String, usize)>, // (type_name, count)
463}
464
465#[derive(Debug, Clone, Serialize, Deserialize)]
466pub struct PcbLibFootprintDetail {
467    pub pattern: String,
468    pub description: String,
469    pub height: String,
470    pub pad_count: usize,
471    pub total_primitives: usize,
472    pub bounding_box: BoundingBox,
473    pub pads: Vec<PadDetail>,
474    pub primitive_counts: Option<Vec<(String, usize)>>,
475}
476
477#[derive(Debug, Clone, Serialize, Deserialize)]
478pub struct BoundingBox {
479    pub width: String,
480    pub height: String,
481}
482
483#[derive(Debug, Clone, Serialize, Deserialize)]
484pub struct PadDetail {
485    pub designator: String,
486    pub shape: String,
487    pub size: String,
488    pub hole: Option<String>,
489    pub layer: String,
490}
491
492#[derive(Debug, Clone, Serialize, Deserialize)]
493pub struct PcbLibPadList {
494    pub path: String,
495    pub total_pads: usize,
496    pub pads: Vec<PadWithFootprint>,
497    pub pads_by_shape: Option<Vec<(String, Vec<PadWithFootprint>)>>,
498}
499
500#[derive(Debug, Clone, Serialize, Deserialize)]
501pub struct PadWithFootprint {
502    pub footprint_name: String,
503    pub designator: String,
504    pub size: String,
505    pub hole: Option<String>,
506    pub shape: String,
507}
508
509#[derive(Debug, Clone, Serialize, Deserialize)]
510pub struct PcbLibPrimitiveList {
511    pub footprint_name: String,
512    pub total_primitives: usize,
513    pub primitives: Vec<PrimitiveDetail>,
514}
515
516#[derive(Debug, Clone, Serialize, Deserialize)]
517#[serde(tag = "type")]
518pub enum PrimitiveDetail {
519    Pad {
520        designator: String,
521        shape: String,
522        size: String,
523        hole: Option<String>,
524    },
525    Track {
526        start_x: String,
527        start_y: String,
528        end_x: String,
529        end_y: String,
530        width: String,
531    },
532    Arc {
533        center_x: String,
534        center_y: String,
535        radius: String,
536        start_angle: f64,
537        end_angle: f64,
538    },
539    Text {
540        text: String,
541        x: String,
542        y: String,
543    },
544    Fill {
545        x1: String,
546        y1: String,
547        x2: String,
548        y2: String,
549    },
550    Region {
551        vertex_count: usize,
552        layer: String,
553    },
554    ComponentBody {
555        vertex_count: usize,
556        height: String,
557    },
558    Other {
559        primitive_type: String,
560    },
561}
562
563#[derive(Debug, Clone, Serialize, Deserialize)]
564pub struct PcbLibHoleAnalysis {
565    pub path: String,
566    pub hole_sizes: Vec<HoleSizeInfo>,
567}
568
569#[derive(Debug, Clone, Serialize, Deserialize)]
570pub struct HoleSizeInfo {
571    pub size: String,
572    pub count: usize,
573    pub example_footprints: Vec<String>,
574}
575
576#[derive(Debug, Clone, Serialize, Deserialize)]
577pub struct PcbLibJson {
578    pub file: String,
579    pub footprint_count: usize,
580    pub unique_id: String,
581    pub footprints: Vec<FootprintJsonData>,
582}
583
584#[derive(Debug, Clone, Serialize, Deserialize)]
585pub struct FootprintJsonData {
586    pub name: String,
587    #[serde(skip_serializing_if = "String::is_empty")]
588    pub description: String,
589    pub pad_count: usize,
590    pub primitive_count: usize,
591    #[serde(skip_serializing_if = "Option::is_none")]
592    pub pads: Option<Vec<PadJsonData>>,
593}
594
595#[derive(Debug, Clone, Serialize, Deserialize)]
596pub struct PadJsonData {
597    pub designator: String,
598    pub shape: String,
599    pub size_x: String,
600    pub size_y: String,
601    #[serde(skip_serializing_if = "Option::is_none")]
602    pub hole_size: Option<String>,
603    pub layer: String,
604}
605
606// Measurement output types for cmd_measure
607#[derive(Debug, Clone, Serialize, Deserialize)]
608pub struct MeasurementValue {
609    pub mm: f64,
610    pub mils: f64,
611}
612
613#[derive(Debug, Clone, Serialize, Deserialize)]
614pub struct PcbLibMeasurementReport {
615    pub name: String,
616    pub dimensions: DimensionsData,
617    pub pads: Vec<PadInfoData>,
618    pub pitch: Vec<PitchData>,
619    pub min_pad_clearance: Option<ClearanceData>,
620    pub silkscreen_clearance: Option<ClearanceData>,
621    pub row_span: Option<MeasurementValue>,
622}
623
624#[derive(Debug, Clone, Serialize, Deserialize)]
625pub struct DimensionsData {
626    pub width: MeasurementValue,
627    pub height: MeasurementValue,
628    pub min_x: MeasurementValue,
629    pub max_x: MeasurementValue,
630    pub min_y: MeasurementValue,
631    pub max_y: MeasurementValue,
632}
633
634#[derive(Debug, Clone, Serialize, Deserialize)]
635pub struct PadInfoData {
636    pub designator: String,
637    pub x: MeasurementValue,
638    pub y: MeasurementValue,
639    pub width: MeasurementValue,
640    pub height: MeasurementValue,
641    pub hole: Option<MeasurementValue>,
642    pub shape: String,
643}
644
645#[derive(Debug, Clone, Serialize, Deserialize)]
646pub struct PitchData {
647    pub pitch: MeasurementValue,
648    pub direction: String,
649    pub count: usize,
650    pub pad_pairs: Vec<(String, String, MeasurementValue)>,
651}
652
653#[derive(Debug, Clone, Serialize, Deserialize)]
654pub struct ClearanceData {
655    pub feature1: String,
656    pub feature2: String,
657    pub clearance: MeasurementValue,
658    pub location: String,
659}
660
661#[derive(Debug, Clone, Serialize, Deserialize)]
662pub struct PadDistanceData {
663    pub pad1: String,
664    pub pad2: String,
665    pub center_to_center: MeasurementValue,
666    pub edge_to_edge: MeasurementValue,
667}
668
669#[derive(Debug, Clone, Serialize, Deserialize)]
670pub struct PadClearances {
671    pub pad_to_pad: Option<ClearanceData>,
672    pub pad_to_silkscreen: Option<ClearanceData>,
673}
674
675// ═══════════════════════════════════════════════════════════════════════════
676// PCBDOC OUTPUT TYPES
677// ═══════════════════════════════════════════════════════════════════════════
678
679#[derive(Debug, Clone, Serialize, Deserialize)]
680pub struct PcbDocOverview {
681    pub path: String,
682    pub summary: PcbDocSummary,
683    pub rules_by_category: Vec<(String, Vec<RuleSummary>)>, // (category, rules)
684    pub components_preview: Vec<ComponentPreview>,
685    pub nets_preview: Vec<String>,
686}
687
688#[derive(Debug, Clone, Serialize, Deserialize)]
689pub struct PcbDocSummary {
690    pub components: usize,
691    pub nets: usize,
692    pub rules: usize,
693    pub primitives: usize,
694    pub tracks: usize,
695    pub vias: usize,
696}
697
698#[derive(Debug, Clone, Serialize, Deserialize)]
699pub struct RuleSummary {
700    pub name: String,
701    pub priority: i32,
702    pub enabled: bool,
703}
704
705#[derive(Debug, Clone, Serialize, Deserialize)]
706pub struct ComponentPreview {
707    pub designator: String,
708    pub pattern: String,
709    pub comment: String,
710}
711
712#[derive(Debug, Clone, Serialize, Deserialize)]
713pub struct PcbDocInfo {
714    pub path: String,
715    pub component_count: usize,
716    pub net_count: usize,
717    pub rule_count: usize,
718    pub primitive_count: usize,
719    pub track_count: usize,
720    pub via_count: usize,
721}
722
723#[derive(Debug, Clone, Serialize, Deserialize)]
724pub struct PcbDocRuleList {
725    pub path: String,
726    pub filter: Option<String>,
727    pub total_rules: usize,
728    pub rules: Vec<RuleInfo>,
729}
730
731#[derive(Debug, Clone, Serialize, Deserialize)]
732pub struct RuleInfo {
733    pub name: String,
734    pub kind: String,
735    pub enabled: bool,
736    pub priority: i32,
737    pub scope1_expression: String,
738    pub scope2_expression: String,
739    pub comment: String,
740    pub parameters: Option<HashMap<String, String>>,
741}
742
743#[derive(Debug, Clone, Serialize, Deserialize)]
744pub struct PcbDocRuleDetail {
745    pub name: String,
746    pub kind: String,
747    pub enabled: bool,
748    pub priority: i32,
749    pub scope1_expression: String,
750    pub scope2_expression: String,
751    pub comment: String,
752    pub parameters: HashMap<String, String>,
753}
754
755#[derive(Debug, Clone, Serialize, Deserialize)]
756pub struct PcbDocJson {
757    pub file: String,
758    pub summary: PcbDocSummary,
759    pub rules: Option<Vec<RuleInfo>>,
760    pub components: Option<Vec<PcbComponentInfo>>,
761    pub nets: Option<Vec<String>>,
762    pub layers: Option<Vec<LayerInfo>>,
763}
764
765#[derive(Debug, Clone, Serialize, Deserialize)]
766pub struct PcbComponentInfo {
767    pub designator: String,
768    pub pattern: String,
769    pub comment: String,
770    pub x: Option<String>,
771    pub y: Option<String>,
772    pub rotation: f64,
773    pub layer: String,
774    pub locked: bool,
775}
776
777#[derive(Debug, Clone, Serialize, Deserialize)]
778pub struct PcbDocComponentList {
779    pub path: String,
780    pub total_components: usize,
781    pub layer_filter: Option<String>,
782    pub components: Vec<PcbComponentInfo>,
783}
784
785#[derive(Debug, Clone, Serialize, Deserialize)]
786pub struct PcbDocComponentDetail {
787    pub designator: String,
788    pub pattern: String,
789    pub comment: String,
790    pub source_designator: String,
791    pub source_footprint: String,
792    pub x: Option<String>,
793    pub y: Option<String>,
794    pub rotation: f64,
795    pub layer: String,
796    pub locked: bool,
797    pub pad_count: usize,
798    pub unique_id: String,
799}
800
801#[derive(Debug, Clone, Serialize, Deserialize)]
802pub struct PcbDocOutline {
803    pub vertex_count: usize,
804    pub width_mm: f64,
805    pub height_mm: f64,
806    pub vertices: Vec<OutlineVertex>,
807}
808
809#[derive(Debug, Clone, Serialize, Deserialize)]
810pub struct OutlineVertex {
811    pub x_mm: f64,
812    pub y_mm: f64,
813    pub kind: String, // "line" or "arc"
814    #[serde(skip_serializing_if = "Option::is_none")]
815    pub center_x_mm: Option<f64>,
816    #[serde(skip_serializing_if = "Option::is_none")]
817    pub center_y_mm: Option<f64>,
818    #[serde(skip_serializing_if = "Option::is_none")]
819    pub radius_mm: Option<f64>,
820}
821
822#[derive(Debug, Clone, Serialize, Deserialize)]
823pub struct PcbDocSettings {
824    pub display_unit: String,
825    pub snap_grid: String,
826    pub visible_grid: String,
827    pub component_grid: String,
828    pub track_grid: Option<String>,
829    pub via_grid: Option<String>,
830    pub track_width: Option<String>,
831    pub origin_x: String,
832    pub origin_y: String,
833}
834
835#[derive(Debug, Clone, Serialize, Deserialize)]
836pub struct PcbDocLayers {
837    pub path: String,
838    pub total_layers: usize,
839    pub show_all: bool,
840    pub layers: Vec<LayerInfo>,
841}
842
843#[derive(Debug, Clone, Serialize, Deserialize)]
844pub struct LayerInfo {
845    pub id: u8,
846    pub name: String,
847    pub layer_type: String,
848    pub used: bool,
849    pub enabled: bool,
850    pub copper_thickness: Option<String>,
851    pub dielectric_constant: Option<f64>,
852    pub dielectric_thickness: Option<String>,
853}
854
855#[derive(Debug, Clone, Serialize, Deserialize)]
856pub struct PcbDocKeepouts {
857    pub path: String,
858    pub total_keepouts: usize,
859    pub layer_filter: Option<String>,
860    pub keepouts: Vec<KeepoutInfo>,
861}
862
863#[derive(Debug, Clone, Serialize, Deserialize)]
864pub struct KeepoutInfo {
865    pub index: usize,
866    pub layer: String,
867    pub x1: String,
868    pub y1: String,
869    pub x2: String,
870    pub y2: String,
871    pub kind: String, // "region", "track", "via", etc.
872}
873
874#[derive(Debug, Clone, Serialize, Deserialize)]
875pub struct PcbDocCutouts {
876    pub path: String,
877    pub total_cutouts: usize,
878    pub cutouts: Vec<CutoutInfo>,
879}
880
881#[derive(Debug, Clone, Serialize, Deserialize)]
882pub struct CutoutInfo {
883    pub index: usize,
884    pub vertex_count: usize,
885    pub bounds: BoundsInfo,
886}
887
888#[derive(Debug, Clone, Serialize, Deserialize)]
889pub struct BoundsInfo {
890    pub x1: String,
891    pub y1: String,
892    pub x2: String,
893    pub y2: String,
894}
895
896#[derive(Debug, Clone, Serialize, Deserialize)]
897pub struct PcbDocPolygons {
898    pub path: String,
899    pub total_polygons: usize,
900    pub layer_filter: Option<String>,
901    pub net_filter: Option<String>,
902    pub polygons: Vec<PolygonSummary>,
903}
904
905#[derive(Debug, Clone, Serialize, Deserialize)]
906pub struct PolygonSummary {
907    pub index: usize,
908    pub layer: String,
909    pub net: String,
910    pub vertex_count: usize,
911    pub pour_over: bool,
912    pub remove_dead: bool,
913    pub hatch_style: String,
914}
915
916#[derive(Debug, Clone, Serialize, Deserialize)]
917pub struct PcbDocPolygonDetail {
918    pub index: usize,
919    pub layer: String,
920    pub net: String,
921    pub vertex_count: usize,
922    pub pour_over: bool,
923    pub remove_dead: bool,
924    pub hatch_style: String,
925    pub vertices: Vec<PolygonVertexInfo>,
926}
927
928#[derive(Debug, Clone, Serialize, Deserialize)]
929pub struct PolygonVertexInfo {
930    pub x: String,
931    pub y: String,
932    pub kind: String, // "line" or "arc"
933}
934
935#[derive(Debug, Clone, Serialize, Deserialize)]
936pub struct PcbDocTracks {
937    pub path: String,
938    pub total_tracks: usize,
939    pub layer_filter: Option<String>,
940    pub tracks: Vec<TrackInfo>,
941}
942
943#[derive(Debug, Clone, Serialize, Deserialize)]
944pub struct TrackInfo {
945    pub index: usize,
946    pub layer: String,
947    pub start_x: String,
948    pub start_y: String,
949    pub end_x: String,
950    pub end_y: String,
951    pub width: String,
952    pub net: String,
953}
954
955#[derive(Debug, Clone, Serialize, Deserialize)]
956pub struct PcbDocVias {
957    pub path: String,
958    pub total_vias: usize,
959    pub vias: Vec<ViaInfo>,
960}
961
962#[derive(Debug, Clone, Serialize, Deserialize)]
963pub struct ViaInfo {
964    pub index: usize,
965    pub x: String,
966    pub y: String,
967    pub diameter: String,
968    pub hole_size: String,
969    pub from_layer: String,
970    pub to_layer: String,
971    pub net: String,
972}
973
974#[derive(Debug, Clone, Serialize, Deserialize)]
975pub struct PcbDocArcs {
976    pub path: String,
977    pub total_arcs: usize,
978    pub layer_filter: Option<String>,
979    pub arcs: Vec<ArcInfo>,
980}
981
982#[derive(Debug, Clone, Serialize, Deserialize)]
983pub struct ArcInfo {
984    pub index: usize,
985    pub layer: String,
986    pub center_x: String,
987    pub center_y: String,
988    pub radius: String,
989    pub start_angle: f64,
990    pub end_angle: f64,
991    pub width: String,
992    pub net: String,
993}
994
995#[derive(Debug, Clone, Serialize, Deserialize)]
996pub struct PcbDocFills {
997    pub path: String,
998    pub total_fills: usize,
999    pub layer_filter: Option<String>,
1000    pub fills: Vec<FillInfo>,
1001}
1002
1003#[derive(Debug, Clone, Serialize, Deserialize)]
1004pub struct FillInfo {
1005    pub index: usize,
1006    pub layer: String,
1007    pub x1: String,
1008    pub y1: String,
1009    pub x2: String,
1010    pub y2: String,
1011    pub rotation: f64,
1012    pub net: String,
1013}
1014
1015#[derive(Debug, Clone, Serialize, Deserialize)]
1016pub struct PcbDocTexts {
1017    pub path: String,
1018    pub total_texts: usize,
1019    pub layer_filter: Option<String>,
1020    pub texts: Vec<TextInfo>,
1021}
1022
1023#[derive(Debug, Clone, Serialize, Deserialize)]
1024pub struct TextInfo {
1025    pub index: usize,
1026    pub text: String,
1027    pub layer: String,
1028    pub x: String,
1029    pub y: String,
1030    pub height: String,
1031    pub rotation: f64,
1032}
1033
1034#[derive(Debug, Clone, Serialize, Deserialize)]
1035pub struct PcbDocRegions {
1036    pub path: String,
1037    pub total_regions: usize,
1038    pub layer_filter: Option<String>,
1039    pub regions: Vec<RegionInfo>,
1040}
1041
1042#[derive(Debug, Clone, Serialize, Deserialize)]
1043pub struct RegionInfo {
1044    pub index: usize,
1045    pub layer: String,
1046    pub vertex_count: usize,
1047    pub is_keepout: bool,
1048    pub net: String,
1049}
1050
1051#[derive(Debug, Clone, Serialize, Deserialize)]
1052pub struct PcbDocNets {
1053    pub path: String,
1054    pub total_nets: usize,
1055    pub nets: Vec<String>,
1056}
1057
1058// ═══════════════════════════════════════════════════════════════════════════
1059// SCHDOC OUTPUT TYPES
1060// ═══════════════════════════════════════════════════════════════════════════
1061
1062#[derive(Debug, Clone, Serialize, Deserialize)]
1063pub struct SchDocOverview {
1064    pub path: String,
1065    pub sheet_size: String,
1066    pub components_by_category: Vec<(String, Vec<SchDocComponentRef>)>,
1067    pub power_architecture: PowerArchitecture,
1068    pub interfaces: Option<InterfaceSummary>,
1069    pub key_signals: KeySignals,
1070    pub quick_stats: SchDocQuickStats,
1071}
1072
1073#[derive(Debug, Clone, Serialize, Deserialize)]
1074pub struct SchDocComponentRef {
1075    pub designator: String,
1076    pub lib_reference: String,
1077    pub description: String,
1078}
1079
1080#[derive(Debug, Clone, Serialize, Deserialize)]
1081pub struct PowerArchitecture {
1082    pub power_rails: Vec<(String, usize)>, // (net_name, connection_count)
1083    pub ground_nets: Vec<(String, usize)>,
1084}
1085
1086#[derive(Debug, Clone, Serialize, Deserialize)]
1087pub struct InterfaceSummary {
1088    pub inputs: Vec<String>,
1089    pub outputs: Vec<String>,
1090    pub bidirectional: Vec<String>,
1091    pub unspecified: Vec<String>,
1092}
1093
1094#[derive(Debug, Clone, Serialize, Deserialize)]
1095pub struct KeySignals {
1096    pub total_unique_nets: usize,
1097    pub data_buses: Vec<String>,
1098    pub address_buses: Vec<String>,
1099    pub control_signals: Vec<String>,
1100}
1101
1102#[derive(Debug, Clone, Serialize, Deserialize)]
1103pub struct SchDocQuickStats {
1104    pub components: usize,
1105    pub wires: usize,
1106    pub junctions: usize,
1107    pub net_labels: usize,
1108    pub ports: usize,
1109    pub power_symbols: usize,
1110}
1111
1112#[derive(Debug, Clone, Serialize, Deserialize)]
1113pub struct SchDocBom {
1114    pub path: String,
1115    pub total_components: usize,
1116    pub unique_parts: usize,
1117    pub items: Vec<BomItem>,
1118}
1119
1120#[derive(Debug, Clone, Serialize, Deserialize)]
1121pub struct BomItem {
1122    pub lib_reference: String,
1123    pub quantity: usize,
1124    pub designators: Vec<String>,
1125    pub description: String,
1126}
1127
1128#[derive(Debug, Clone, Serialize, Deserialize)]
1129pub struct SchDocNetlist {
1130    pub path: String,
1131    pub filter: Option<String>,
1132    pub min_connections: usize,
1133    pub total_nets: usize,
1134    pub nets: Vec<NetConnection>,
1135}
1136
1137#[derive(Debug, Clone, Serialize, Deserialize)]
1138pub struct NetConnection {
1139    pub net_name: String,
1140    pub connections: Vec<String>, // "Component.Pin (name)" format
1141}
1142
1143#[derive(Debug, Clone, Serialize, Deserialize)]
1144pub struct SchDocPowerMap {
1145    pub path: String,
1146    pub power_rails: Vec<PowerRail>,
1147    pub ground_nets: Vec<GroundNet>,
1148    pub powered_components: Vec<PoweredComponent>,
1149}
1150
1151#[derive(Debug, Clone, Serialize, Deserialize)]
1152pub struct PowerRail {
1153    pub net_name: String,
1154    pub symbol_count: usize,
1155    pub consumers: Vec<String>,
1156}
1157
1158#[derive(Debug, Clone, Serialize, Deserialize)]
1159pub struct GroundNet {
1160    pub net_name: String,
1161    pub symbol_count: usize,
1162}
1163
1164#[derive(Debug, Clone, Serialize, Deserialize)]
1165pub struct PoweredComponent {
1166    pub designator: String,
1167    pub lib_reference: String,
1168    pub power_pin_count: usize,
1169}
1170
1171#[derive(Debug, Clone, Serialize, Deserialize)]
1172pub struct SchDocBlocks {
1173    pub path: String,
1174    pub blocks: Vec<BlockInfo>,
1175    pub show_all: bool,
1176}
1177
1178#[derive(Debug, Clone, Serialize, Deserialize)]
1179pub struct BlockInfo {
1180    pub designator: String,
1181    pub lib_reference: String,
1182    pub description: String,
1183    pub category: String,
1184    pub power_pins: Vec<String>,
1185    pub input_pins: Vec<String>,
1186    pub output_pins: Vec<String>,
1187    pub bidir_pins: Vec<String>,
1188}
1189
1190#[derive(Debug, Clone, Serialize, Deserialize)]
1191pub struct SchDocProjectAnalysis {
1192    pub sheet_count: usize,
1193    pub sheets: Vec<SheetInfo>,
1194    pub inter_sheet_connections: Vec<InterSheetConnection>,
1195}
1196
1197#[derive(Debug, Clone, Serialize, Deserialize)]
1198pub struct SheetInfo {
1199    pub name: String,
1200    pub component_count: usize,
1201    pub port_count: usize,
1202    pub net_count: usize,
1203    pub ports: Vec<(String, String)>, // (name, io_type)
1204    pub power_nets: Vec<String>,
1205}
1206
1207#[derive(Debug, Clone, Serialize, Deserialize)]
1208pub struct InterSheetConnection {
1209    pub port_name: String,
1210    pub connected_sheets: Vec<(String, String)>, // (sheet_name, io_type)
1211}
1212
1213#[derive(Debug, Clone, Serialize, Deserialize)]
1214pub struct SchDocSignalFlow {
1215    pub path: String,
1216    pub signal: String,
1217    pub trace_found: bool,
1218    pub trace: Option<SignalTrace>,
1219}
1220
1221#[derive(Debug, Clone, Serialize, Deserialize)]
1222pub struct SignalTrace {
1223    pub source: String,
1224    pub path: Vec<String>,
1225    pub destinations: Vec<String>,
1226}
1227
1228#[derive(Debug, Clone, Serialize, Deserialize)]
1229pub struct SchDocInfo {
1230    pub path: String,
1231    pub sheet_info: Option<SheetInfoDetails>,
1232    pub primitive_summary: PrimitiveSummary,
1233    pub unique_nets: Vec<String>,
1234    pub power_nets: Vec<String>,
1235}
1236
1237#[derive(Debug, Clone, Serialize, Deserialize)]
1238pub struct SheetInfoDetails {
1239    pub size: String,
1240    pub size_style: i32,
1241    pub custom_dimensions: Option<(String, String)>,
1242    pub fonts_defined: i32,
1243}
1244
1245#[derive(Debug, Clone, Serialize, Deserialize)]
1246pub struct PrimitiveSummary {
1247    pub total_primitives: usize,
1248    pub components: usize,
1249    pub wires: usize,
1250    pub net_labels: usize,
1251    pub ports: usize,
1252    pub power_objects: usize,
1253    pub junctions: usize,
1254    pub pins: usize,
1255}
1256
1257#[derive(Debug, Clone, Serialize, Deserialize)]
1258pub struct SchDocStats {
1259    pub path: String,
1260    pub total_primitives: usize,
1261    pub record_types: Vec<(String, usize)>, // (type_name, count)
1262}
1263
1264#[derive(Debug, Clone, Serialize, Deserialize)]
1265pub struct SchDocComponentList {
1266    pub path: String,
1267    pub total_components: usize,
1268    pub components: Vec<SchDocComponentInfo>,
1269}
1270
1271#[derive(Debug, Clone, Serialize, Deserialize)]
1272pub struct SchDocComponentInfo {
1273    pub designator: String,
1274    pub lib_reference: String,
1275    pub description: String,
1276    pub location: String,
1277    pub parts: i32,
1278    pub child_count: Option<usize>,
1279}
1280
1281#[derive(Debug, Clone, Serialize, Deserialize)]
1282pub struct SchDocComponentDetail {
1283    pub designator: String,
1284    pub lib_reference: String,
1285    pub description: String,
1286    pub location: String,
1287    pub parts: i32,
1288    pub display_modes: i32,
1289    pub current_part: i32,
1290    pub unique_id: String,
1291    pub child_primitive_count: usize,
1292    pub pins: Vec<SchDocPinInfo>,
1293    pub parameters: Vec<SchDocParameter>,
1294    pub designators: Vec<SchDocDesignator>,
1295    pub graphic_primitive_count: Option<usize>,
1296}
1297
1298#[derive(Debug, Clone, Serialize, Deserialize)]
1299pub struct SchDocPinInfo {
1300    pub designator: String,
1301    pub name: String,
1302    pub electrical_type: String,
1303    pub hidden: bool,
1304}
1305
1306#[derive(Debug, Clone, Serialize, Deserialize)]
1307pub struct SchDocParameter {
1308    pub name: String,
1309    pub value: String,
1310}
1311
1312#[derive(Debug, Clone, Serialize, Deserialize)]
1313pub struct SchDocDesignator {
1314    pub name: String,
1315    pub value: String,
1316}
1317
1318#[derive(Debug, Clone, Serialize, Deserialize)]
1319pub struct SchDocWireList {
1320    pub path: String,
1321    pub total_wires: usize,
1322    pub wires: Vec<WireInfo>,
1323}
1324
1325#[derive(Debug, Clone, Serialize, Deserialize)]
1326pub struct WireInfo {
1327    pub index: usize,
1328    pub start: String,
1329    pub end_or_segments: String,
1330}
1331
1332#[derive(Debug, Clone, Serialize, Deserialize)]
1333pub struct SchDocNetLabelList {
1334    pub path: String,
1335    pub total_net_labels: usize,
1336    pub group_by_name: bool,
1337    pub grouped: Option<Vec<(String, usize)>>, // (net_name, count)
1338    pub individual: Option<Vec<NetLabelInfo>>,
1339}
1340
1341#[derive(Debug, Clone, Serialize, Deserialize)]
1342pub struct NetLabelInfo {
1343    pub net_name: String,
1344    pub location: String,
1345}
1346
1347#[derive(Debug, Clone, Serialize, Deserialize)]
1348pub struct SchDocPortList {
1349    pub path: String,
1350    pub total_ports: usize,
1351    pub ports: Vec<PortInfo>,
1352}
1353
1354#[derive(Debug, Clone, Serialize, Deserialize)]
1355pub struct PortInfo {
1356    pub name: String,
1357    pub io_type: String,
1358    pub location: String,
1359}
1360
1361#[derive(Debug, Clone, Serialize, Deserialize)]
1362pub struct SchDocPowerList {
1363    pub path: String,
1364    pub total_power_objects: usize,
1365    pub group_by_net: bool,
1366    pub grouped: Option<Vec<(String, usize)>>, // (net_name, count)
1367    pub individual: Option<Vec<PowerObjectInfo>>,
1368}
1369
1370#[derive(Debug, Clone, Serialize, Deserialize)]
1371pub struct PowerObjectInfo {
1372    pub net: String,
1373    pub style: String,
1374    pub location: String,
1375}
1376
1377#[derive(Debug, Clone, Serialize, Deserialize)]
1378pub struct SchDocPinList {
1379    pub path: String,
1380    pub total_pins: usize,
1381    pub filter: Option<String>,
1382    pub pins: Vec<SchDocPinDetail>,
1383}
1384
1385#[derive(Debug, Clone, Serialize, Deserialize)]
1386pub struct SchDocPinDetail {
1387    pub component: String,
1388    pub designator: String,
1389    pub name: String,
1390    pub electrical_type: String,
1391    pub location: String,
1392}
1393
1394#[derive(Debug, Clone, Serialize, Deserialize)]
1395pub struct SchDocHierarchy {
1396    pub path: String,
1397    pub hierarchy: Vec<HierarchyNode>,
1398}
1399
1400#[derive(Debug, Clone, Serialize, Deserialize)]
1401pub struct HierarchyNode {
1402    pub node_type: String, // "sheet", "component", etc.
1403    pub unique_id: String,
1404    pub description: String,
1405    pub children: Vec<HierarchyNode>,
1406}
1407
1408#[derive(Debug, Clone, Serialize, Deserialize)]
1409pub struct SchDocSearchResults {
1410    pub path: String,
1411    pub query: String,
1412    pub total_matches: usize,
1413    pub results: Vec<SearchMatch>,
1414}
1415
1416#[derive(Debug, Clone, Serialize, Deserialize)]
1417pub struct SearchMatch {
1418    pub designator: String,
1419    pub lib_reference: String,
1420    pub description: String,
1421    pub location: String,
1422}
1423
1424#[derive(Debug, Clone, Serialize, Deserialize)]
1425pub struct SchDocJunctionList {
1426    pub path: String,
1427    pub total_junctions: usize,
1428    pub junctions: Vec<JunctionInfo>,
1429}
1430
1431#[derive(Debug, Clone, Serialize, Deserialize)]
1432pub struct JunctionInfo {
1433    pub location: String,
1434}
1435
1436#[derive(Debug, Clone, Serialize, Deserialize)]
1437pub struct SchDocJson {
1438    pub file: String,
1439    pub sheet: Option<JsonSheetInfo>,
1440    pub summary: JsonDocSummary,
1441    pub components: Option<Vec<JsonComponentInfo>>,
1442    pub nets: Option<Vec<JsonNetInfo>>,
1443    pub ports: Option<Vec<JsonPortInfo>>,
1444    pub power: Option<Vec<JsonPowerInfo>>,
1445}
1446
1447#[derive(Debug, Clone, Serialize, Deserialize)]
1448pub struct JsonSheetInfo {
1449    pub size: String,
1450    pub fonts: i32,
1451}
1452
1453#[derive(Debug, Clone, Serialize, Deserialize)]
1454pub struct JsonDocSummary {
1455    pub total_primitives: usize,
1456    pub components: usize,
1457    pub wires: usize,
1458    pub net_labels: usize,
1459    pub ports: usize,
1460    pub power_objects: usize,
1461    pub junctions: usize,
1462    pub pins: usize,
1463}
1464
1465#[derive(Debug, Clone, Serialize, Deserialize)]
1466pub struct JsonComponentInfo {
1467    pub designator: String,
1468    pub lib_reference: String,
1469    pub description: String,
1470    pub location: String,
1471    pub pins: Vec<JsonPinInfo>,
1472    pub parameters: Vec<JsonParameterInfo>,
1473}
1474
1475#[derive(Debug, Clone, Serialize, Deserialize)]
1476pub struct JsonPinInfo {
1477    pub designator: String,
1478    pub name: String,
1479    pub electrical: String,
1480    pub hidden: bool,
1481}
1482
1483#[derive(Debug, Clone, Serialize, Deserialize)]
1484pub struct JsonParameterInfo {
1485    pub name: String,
1486    pub value: String,
1487}
1488
1489#[derive(Debug, Clone, Serialize, Deserialize)]
1490pub struct JsonNetInfo {
1491    pub name: String,
1492    pub location: String,
1493}
1494
1495#[derive(Debug, Clone, Serialize, Deserialize)]
1496pub struct JsonPortInfo {
1497    pub name: String,
1498    pub io_type: String,
1499    pub location: String,
1500}
1501
1502#[derive(Debug, Clone, Serialize, Deserialize)]
1503pub struct JsonPowerInfo {
1504    pub net: String,
1505    pub style: String,
1506    pub location: String,
1507}
1508
1509#[derive(Debug, Clone, Serialize, Deserialize)]
1510pub struct SchDocValidationResult {
1511    pub path: String,
1512    pub is_valid: bool,
1513    pub errors: Vec<ValidationError>,
1514}
1515
1516#[derive(Debug, Clone, Serialize, Deserialize)]
1517pub struct ValidationError {
1518    pub kind: String,
1519    pub message: String,
1520    pub location: Option<(f64, f64)>, // (x, y) in mils
1521    pub components: Vec<String>,
1522}
1523
1524#[derive(Debug, Clone, Serialize, Deserialize)]
1525pub struct SchDocNetlistAnalysis {
1526    pub path: String,
1527    pub total_nets: usize,
1528    pub nets: Vec<NetDetail>,
1529}
1530
1531#[derive(Debug, Clone, Serialize, Deserialize)]
1532pub struct NetDetail {
1533    pub name: String,
1534    pub connection_count: usize,
1535    pub connections: Vec<String>,
1536}
1537
1538#[derive(Debug, Clone, Serialize, Deserialize)]
1539pub struct SchDocUnconnectedPins {
1540    pub path: String,
1541    pub total_unconnected: usize,
1542    pub pins: Vec<UnconnectedPin>,
1543}
1544
1545#[derive(Debug, Clone, Serialize, Deserialize)]
1546pub struct UnconnectedPin {
1547    pub component: String,
1548    pub pin: String,
1549    pub x: f64,
1550    pub y: f64,
1551}
1552
1553#[derive(Debug, Clone, Serialize, Deserialize)]
1554pub struct SchDocMissingJunctions {
1555    pub path: String,
1556    pub total_missing: usize,
1557    pub locations: Vec<(f64, f64)>, // (x, y) in mils
1558}
1559
1560#[derive(Debug, Clone, Serialize, Deserialize)]
1561pub struct SchDocLibrarySearchResults {
1562    pub library: String,
1563    pub pattern: String,
1564    pub total_matches: usize,
1565    pub matches: Vec<LibraryComponentMatch>,
1566}
1567
1568#[derive(Debug, Clone, Serialize, Deserialize)]
1569pub struct LibraryComponentMatch {
1570    pub name: String,
1571    pub description: String,
1572    pub pins: usize,
1573}
1574
1575#[derive(Debug, Clone, Serialize, Deserialize)]
1576pub struct SchDocLibraryList {
1577    pub library: String,
1578    pub total_components: usize,
1579    pub components: Vec<LibraryComponentInfo>,
1580}
1581
1582#[derive(Debug, Clone, Serialize, Deserialize)]
1583pub struct LibraryComponentInfo {
1584    pub name: String,
1585    pub description: String,
1586    pub pins: usize,
1587    pub primitives: Option<usize>,
1588}