scratch

package
v0.0.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 28, 2021 License: MIT Imports: 1 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Reader

type Reader struct {
	// contains filtered or unexported fields
}

Reader provides zero-copy read methods and other helpful utilities commonly desired in parsers around either an io.Reader or a plain byte slice.

Read methods with 'n' in the name take a size parameter for how much to read. Read methods with a number in the name read that fixed number of bytes. Read methods with 'b' in the name accept a byte slice parameter which will be used for output, allowing you to control memory reuse. Read methods with 'z' in the name will attempt to return zero-copy access to buffers controlled by the Reader -- be careful when using these 'z' methods; it is not recommended to expose the zero-copy slices these methods yield, because the reader itself may also reuse them, and so the likelihood of spooky-action-at-a-distance bugs is high.

While this Reader does some buffering, it's not much (and primarily oriented around reuse of scratch buffers rather than intentionly large batch readaheads); it may still be advisable to use a buffered reader to avoid small reads if reading streamingly from external IO like disk or network.

func (*Reader) Init

func (z *Reader) Init(r io.Reader)

Init makes this Reader ready to consume the given io.Reader. If this Reader has been used before, all state is zeroed out cleanly.

As a convenience, if the io.Reader looks like it can return all the bytes at once (e.g., it has a `Bytes() []byte` method -- as bytes.Buffer does, for example), then Init will access that and use InitSlice, which should lead to better performance.

func (*Reader) InitReader

func (z *Reader) InitReader(r io.Reader)

InitReader makes this Reader ready to consume the given io.Reader. If this Reader has been used before, all state is zeroed out cleanly.

Unlike Init, this initializer will not attempt to autodetect any interface which may provide direct access to underlying byte slices; it will always work in stream mode.

func (*Reader) InitSlice

func (z *Reader) InitSlice(bs []byte)

InitSlice makes this Reader ready to consume the given byte slice. If this Reader has been used before, all state is zeroed out cleanly.

InitSlice is functionally equivalent to wrapping the byte slice in a reader and using Init, but will result in a Reader that generally operates somewhat faster and is able to deliver more zero-copy behaviors. (When we know we're working with a byte slice that's already entirely in memory, we never have to worry about read alignment, etc.)

func (*Reader) NumRead

func (z *Reader) NumRead() int64

func (*Reader) Readb

func (z *Reader) Readb(bs []byte) (n int, err error)

Readb reads up to `len(b)` bytes into the given slice, starting at its beginning, overwriting all values, and disregarding any extra capacity. If the there is less than `len(b)` bytes to be read, a partial read will be returned: some of the slice will be modified, n will be less than the slice length, and err will be ErrUnexpectedEOF. (If you're intentionally providing a larger slice than may be necessary in order to get a batch read, you will want to check for and discard ErrUnexpectedEOF!) If no error is returned, n will always be the length of the slice.

Readb will never return a zero-copy subslice of an existing buffer; use one of the 'Read*z*' methods for that.

func (*Reader) Readn

func (z *Reader) Readn(n int) (bs []byte, err error)

Readn reads up to n bytes into a new byte slice. If there is less than n bytes to be read, a shorter slice will be returned, and err will be ErrUnexpectedEOF. If zero-copy views into existing buffers are acceptable (e.g. you know you won't later mutate, reference or expose this memory again), prefer `Readnzc`. If you already have an existing slice of sufficient size to reuse, prefer `Readb`. Requesting a zero length read will return `zeroByteSlice`, a len-zero cap-zero slice.

Readn will never return a zero-copy subslice of an existing buffer; use one of the 'Read*z*' methods for that. (Readn is purely a convenience method; you can always use Readb to equivalent effect.)

func (*Reader) Readn1

func (z *Reader) Readn1() (byte, error)

Readn1 reads a single byte.

func (*Reader) Readnzc

func (z *Reader) Readnzc(n int) (bs []byte, err error)

Readnzc read up to n bytes into a byte slice which may be shared and must not be reused after any additional calls to this reader. Readnzc will use the implementation scratch buffer if possible, (i.e. n < scratchByteArrayLen), or may return a view of the []byte being decoded from if the read is larger. If there is less than n bytes to be read, a shorter slice will be returned, and err will be ErrUnexpectedEOF. Requesting a zero length read will return `zeroByteSlice`, a len-zero cap-zero slice. If you know your read may be longer than scratchByteArrayLen and you already have an existing slice of sufficient size to reuse, prefer `Readb`.

func (*Reader) ResetNumRead

func (z *Reader) ResetNumRead()

func (*Reader) StopTrack

func (z *Reader) StopTrack() []byte

StopTrack returns the byte slice accumulated since Track was called, and drops the marker.

Calling StopTrack when Track is not in effect will result in panic.

The slice returned by StopTrack may be reused if Track is called again in the future; the caller should copy the contents to a new byte slice before the next call to Track they intend to either make this data available for a long time or to mutate it.

func (*Reader) Track

func (z *Reader) Track()

Track causes the Reader to place a marker and accumulate all bytes into a single contiguous slice up until StopTrack is called; StopTrack will return a reference to this slice. Thus, StopTrack will yield bytes which have already also been seen via other read method calls.

This can be useful when parsing logic requires scanning ahead to look for the end of an unknown-length segment of data, for example.

Calling Track twice without an intervening StopTrack will result in panic.

func (*Reader) Unreadn1

func (z *Reader) Unreadn1()

Unreadn1 "unreads" a single byte which was previously read by Readn1. The result is that subsequent reads will include that byte, and applying the Track method will also cause the track result to include that byte.

Unreadn1 can only be used when the previous call was Readn1, and may panic otherwise.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL