1818package ota
1919
2020import (
21- "bufio"
2221 "encoding/binary"
22+ "fmt"
2323 "hash/crc32"
2424 "io"
2525 "strconv"
2626
2727 "github.com/arduino/arduino-cloud-cli/internal/lzss"
28- "github.com/juju/errors"
2928)
3029
31- // A writer is a buffered, flushable writer.
32- type writer interface {
33- io.Writer
34- Flush () error
35- }
36-
37- // encoder encodes a binary into an .ota file.
38- type encoder struct {
39- // w is the writer that compressed bytes are written to.
40- w writer
30+ // Encoder writes a binary to an output stream in the ota format.
31+ type Encoder struct {
32+ // w is the stream where encoded bytes are written.
33+ w io.Writer
4134
42- // vendorID is the ID of the board vendor
35+ // vendorID is the ID of the board vendor.
4336 vendorID string
4437
45- // is the ID of the board vendor is the ID of the board model
38+ // productID is the ID of the board model.
4639 productID string
4740}
4841
49- // NewWriter creates a new `WriteCloser` for the the given VID/PID.
50- func NewWriter (w io.Writer , vendorID , productID string ) io.WriteCloser {
51- bw , ok := w .(writer )
52- if ! ok {
53- bw = bufio .NewWriter (w )
54- }
55- return & encoder {
56- w : bw ,
42+ // NewEncoder creates a new ota encoder.
43+ func NewEncoder (w io.Writer , vendorID , productID string ) * Encoder {
44+ return & Encoder {
45+ w : w ,
5746 vendorID : vendorID ,
5847 productID : productID ,
5948 }
6049}
6150
62- // Write writes a compressed representation of p to e's underlying writer.
63- func (e * encoder ) Write (binaryData []byte ) (int , error ) {
64- //log.Println("original binaryData is", len(binaryData), "bytes length")
65-
66- // Magic number (VID/PID)
51+ // Encode compresses data using a lzss algorithm, encodes the result
52+ // in ota format and writes it to e's underlying writer.
53+ func (e * Encoder ) Encode (data []byte ) error {
54+ // Compute the magic number (VID/PID)
6755 magicNumber := make ([]byte , 4 )
6856 vid , err := strconv .ParseUint (e .vendorID , 16 , 16 )
6957 if err != nil {
70- return 0 , errors . Annotate ( err , "OTA encoder: failed to parse vendorID" )
58+ return fmt . Errorf ( "cannot parse vendorID: %w" , err )
7159 }
7260 pid , err := strconv .ParseUint (e .productID , 16 , 16 )
7361 if err != nil {
74- return 0 , errors . Annotate ( err , "OTA encoder: failed to parse productID" )
62+ return fmt . Errorf ( "cannot parse productID: %w" , err )
7563 }
7664
7765 binary .LittleEndian .PutUint16 (magicNumber [0 :2 ], uint16 (pid ))
@@ -82,61 +70,43 @@ func (e *encoder) Write(binaryData []byte) (int, error) {
8270 Compression : true ,
8371 }
8472
85- // Compress the compiled binary
86- compressed := lzss .Encode (binaryData )
87-
73+ compressed := lzss .Encode (data )
8874 // Prepend magic number and version field to payload
89- var binDataComplete []byte
90- binDataComplete = append (binDataComplete , magicNumber ... )
91- binDataComplete = append (binDataComplete , version .AsBytes ()... )
92- binDataComplete = append (binDataComplete , compressed ... )
93- //log.Println("binDataComplete is", len(binDataComplete), "bytes length")
75+ var outData []byte
76+ outData = append (outData , magicNumber ... )
77+ outData = append (outData , version .Bytes ()... )
78+ outData = append (outData , compressed ... )
9479
95- headerSize , err : = e .writeHeader (binDataComplete )
80+ err = e .writeHeader (outData )
9681 if err != nil {
97- return headerSize , err
82+ return fmt . Errorf ( "cannot write data header to output stream: %w" , err )
9883 }
9984
100- payloadSize , err : = e .writePayload ( binDataComplete )
85+ _ , err = e .w . Write ( outData )
10186 if err != nil {
102- return payloadSize , err
87+ return fmt . Errorf ( "cannot write encoded data to output stream: %w" , err )
10388 }
10489
105- return headerSize + payloadSize , nil
106- }
107-
108- // Close closes the encoder, flushing any pending output. It does not close or
109- // flush e's underlying writer.
110- func (e * encoder ) Close () error {
111- return e .w .Flush ()
90+ return nil
11291}
11392
114- func (e * encoder ) writeHeader (binDataComplete []byte ) (int , error ) {
115-
93+ func (e * Encoder ) writeHeader (data []byte ) error {
11694 // Write the length of the content
11795 lengthAsBytes := make ([]byte , 4 )
118- binary .LittleEndian .PutUint32 (lengthAsBytes , uint32 (len (binDataComplete )))
119-
120- n , err := e .w .Write (lengthAsBytes )
96+ binary .LittleEndian .PutUint32 (lengthAsBytes , uint32 (len (data )))
97+ _ , err := e .w .Write (lengthAsBytes )
12198 if err != nil {
122- return n , err
99+ return err
123100 }
124101
125- // Calculate the checksum for binDataComplete
126- crc := crc32 .ChecksumIEEE (binDataComplete )
127-
128- // encode the checksum uint32 value as 4 bytes
102+ // Write the checksum uint32 value as 4 bytes
103+ crc := crc32 .ChecksumIEEE (data )
129104 crcAsBytes := make ([]byte , 4 )
130105 binary .LittleEndian .PutUint32 (crcAsBytes , crc )
131-
132- n , err = e .w .Write (crcAsBytes )
106+ _ , err = e .w .Write (crcAsBytes )
133107 if err != nil {
134- return n , err
108+ return err
135109 }
136110
137- return len (lengthAsBytes ) + len (crcAsBytes ), nil
138- }
139-
140- func (e * encoder ) writePayload (data []byte ) (int , error ) {
141- return e .w .Write (data )
111+ return nil
142112}
0 commit comments