byteio/README.md

58 lines
1.7 KiB
Markdown

# src.lwithers.me.uk/go/byteio
[![GoDoc](https://godoc.org/src.lwithers.me.uk/go/byteio?status.svg)](https://godoc.org/src.lwithers.me.uk/go/byteio)
This package provides two interfaces, `Reader` and `Writer`, which capture the
most common byte-oriented methods for I/O, namely `Read([]byte)`, `ReadByte()`
and `ReadRune()` (plus the equivalent writing methods). This is useful because
sometimes you simply want to perform byte-oriented I/O without knowing whether
you have an underlying `bytes.Buffer` or `bufio.Reader` etc.
Furthermore, as a convenience, there are functions which automatically wrap
any `io.Reader` or `io.Writer` with a bufio equivalent if necessary. These
allow for simple byte-oriented I/O operations on arbitrary reader / writer
interfaces with minimal boilerplate.
Example of a method using the `byteio.Reader` interface:
```
func ReadUint16LE(r byteio.Reader) (uint16, error) {
var n uint16
if x, err := r.ReadByte(); err != nil {
return 0, err
} else {
n = uint16(x)
}
if x, err := r.ReadByte(); err != nil {
return 0, err
} else {
n |= uint16(x) << 8
}
return n, nil
}
```
Example of something calling this function:
```
var r io.Reader
// …
br := byteio.NewReader(r)
n, err := ReadUint16LE(br)
```
Example of using the writer interface:
```
var w io.Writer
// …
bw := byteio.NewWriter(w)
defer byteio.FlushIfNecessary(bw)
err := WriteUint16LE(bw, 0x5432)
```
The `byteio.FlushIfNecessary` method determines whether its argument has a
`Flush()` method or not, and if it does, calls it. This allows the caller to
write non-conditional code, not having to check whether `bw` is a `bufio.Writer`
(which needs a flush) or a `bytes.Buffer` (which does not), etc.