diff options
author | Máximo Cuadros <mcuadros@gmail.com> | 2015-10-23 12:05:02 +0200 |
---|---|---|
committer | Máximo Cuadros <mcuadros@gmail.com> | 2015-10-23 12:05:02 +0200 |
commit | 214e1dca024fb6da5ed65564d2de734df5dc2127 (patch) | |
tree | 0c2805a0676006690a8053ae8ccee388ccfc83fe /formats/pktline/decoder.go | |
parent | 70923099e61fa33f0bc5256d2f938fa44c4df10e (diff) | |
download | go-git-214e1dca024fb6da5ed65564d2de734df5dc2127.tar.gz |
format/pktline: review and improving coverage
Diffstat (limited to 'formats/pktline/decoder.go')
-rw-r--r-- | formats/pktline/decoder.go | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/formats/pktline/decoder.go b/formats/pktline/decoder.go new file mode 100644 index 0000000..a078475 --- /dev/null +++ b/formats/pktline/decoder.go @@ -0,0 +1,106 @@ +package pktline + +import ( + "errors" + "io" + "strconv" +) + +var ( + ErrUnderflow = errors.New("unexpected string length (underflow)") + ErrInvalidHeader = errors.New("invalid header") + ErrInvalidLen = errors.New("invalid length") +) + +// Decoder implements a pkt-line format decoder +type Decoder struct { + r io.Reader +} + +// NewDecoder returns a new Decoder +func NewDecoder(r io.Reader) *Decoder { + return &Decoder{r} +} + +// ReadLine reads and return one pkt-line line from the reader +func (d *Decoder) ReadLine() (string, error) { + return d.readLine() +} + +func (d *Decoder) readLine() (string, error) { + raw := make([]byte, HeaderLength) + if _, err := d.r.Read(raw); err != nil { + return "", err + } + + header, err := strconv.ParseInt(string(raw), 16, 16) + if err != nil { + return "", ErrInvalidHeader + } + + if header == 0 { + return "", nil + } + + exp := int(header - HeaderLength) + if exp < 0 { + return "", ErrInvalidLen + } + + line := make([]byte, exp) + if read, err := d.r.Read(line); err != nil { + return "", err + } else if read != exp { + return "", ErrUnderflow + } + + return string(line), nil +} + +// ReadBlock reads and return multiple pkt-line lines, it stops at the end +// of the reader or if a flush-pkt is reached +func (d *Decoder) ReadBlock() ([]string, error) { + var o []string + + for { + line, err := d.readLine() + if err == io.EOF { + return o, nil + } + + if err != nil { + return o, err + } + + if err == nil && line == "" { + return o, nil + } + + o = append(o, line) + } +} + +// ReadAll read and returns all the lines +func (d *Decoder) ReadAll() ([]string, error) { + result, err := d.ReadBlock() + if err != nil { + return result, err + } + + for { + lines, err := d.ReadBlock() + if err == io.EOF { + return result, nil + } + + if err != nil { + return result, err + } + + if err == nil && len(lines) == 0 { + return result, nil + } + + result = append(result, lines...) + } +} |