github.com/la5nta/wl2k-go@v0.11.8/transport/ax25/agwpe/frame.go (about)

     1  package agwpe
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"fmt"
     7  	"io"
     8  )
     9  
    10  type callsign [10]byte
    11  
    12  func callsignFromString(s string) callsign { var c callsign; copy(c[:], s); return c }
    13  
    14  func (c callsign) String() string { return strFromBytes(c[:]) }
    15  
    16  func strFromBytes(b []byte) string {
    17  	idx := bytes.IndexByte(b[:], 0x00)
    18  	if idx < 0 {
    19  		return string(b)
    20  	}
    21  	return string(b[:idx])
    22  }
    23  
    24  // header represents the fixed-size AGWPE header
    25  type header struct {
    26  	Port     uint8    // AGWPE Port
    27  	_        [3]byte  // Reserved
    28  	DataKind kind     // The frame code
    29  	_        byte     // Reserved
    30  	PID      uint8    // Frame PID
    31  	_        byte     // Reserved
    32  	From     callsign // From callsign
    33  	To       callsign // To callsign
    34  	DataLen  uint32   // Data length
    35  	_        uint32   // Reserved (User)
    36  }
    37  
    38  func (h *header) ReadFrom(r io.Reader) (int64, error) {
    39  	return int64(binary.Size(h)), binary.Read(r, binary.LittleEndian, h)
    40  }
    41  
    42  func (h header) WriteTo(w io.Writer) (int64, error) {
    43  	return int64(binary.Size(h)), binary.Write(w, binary.LittleEndian, h)
    44  }
    45  
    46  // frame represents the variable-size AGWPE frame
    47  type frame struct {
    48  	header
    49  	Data []byte
    50  }
    51  
    52  func (f frame) String() string {
    53  	return fmt.Sprintf("Port: %d. Kind: %c. From: %v. To: %v, Data: %q", f.Port, f.DataKind, f.From, f.To, f.Data)
    54  }
    55  
    56  func (f frame) WriteTo(w io.Writer) (int64, error) {
    57  	f.DataLen = uint32(len(f.Data))
    58  	n, err := f.header.WriteTo(w)
    59  	if err != nil {
    60  		return n, err
    61  	}
    62  	m, err := w.Write(f.Data)
    63  	return n + int64(m), err
    64  }
    65  
    66  func (f *frame) ReadFrom(r io.Reader) (int64, error) {
    67  	n, err := f.header.ReadFrom(r)
    68  	if err != nil {
    69  		return n, err
    70  	}
    71  	if cap(f.Data) < int(f.header.DataLen) {
    72  		f.Data = make([]byte, int(f.header.DataLen))
    73  	} else {
    74  		f.Data = f.Data[:f.header.DataLen]
    75  	}
    76  	m, err := r.Read(f.Data)
    77  	switch {
    78  	case err != nil:
    79  		return n + int64(m), err
    80  	case m != len(f.Data):
    81  		return n + int64(m), io.ErrUnexpectedEOF
    82  	}
    83  	return n + int64(m), err
    84  }