1package internal
2
3import (
4 "archive/zip"
5 "encoding/xml"
6 "fmt"
7 "io"
8)
9
10func LoadFile(path string) (*Circuit, error) {
11 circuit, err := loadXML(path)
12 if err != nil {
13 return nil, err
14 }
15 cleanupCircuit(circuit)
16 return documentFromXML(circuit), nil
17}
18
19func loadXML(path string) (*xmlCircuit, error) {
20 r, err := zip.OpenReader(path)
21 if err != nil {
22 return nil, fmt.Errorf("failed to open .cddx as a zip archive: %w", err)
23 }
24 defer r.Close()
25
26 const docPath = "circuitdiagram/Document.xml"
27
28 var docFile *zip.File
29 for _, f := range r.File {
30 if f.Name == docPath {
31 docFile = f
32 break
33 }
34 }
35 if docFile == nil {
36 return nil, fmt.Errorf("'%s' not found inside archive — not a valid .cddx file", docPath)
37 }
38
39 rc, err := docFile.Open()
40 if err != nil {
41 return nil, fmt.Errorf("failed to open '%s' inside archive: %w", docPath, err)
42 }
43 defer rc.Close()
44
45 data, err := io.ReadAll(rc)
46 if err != nil {
47 return nil, fmt.Errorf("failed to read '%s': %w", docPath, err)
48 }
49
50 var circuit xmlCircuit
51 if err := xml.Unmarshal(data, &circuit); err != nil {
52 return nil, fmt.Errorf("failed to parse '%s': %w", docPath, err)
53 }
54 return &circuit, nil
55}