119 lines
3.6 KiB
Go
119 lines
3.6 KiB
Go
package tape
|
|
|
|
import "io"
|
|
import "math"
|
|
import "bufio"
|
|
|
|
// Encodable is any type that can write itself to an encoder.
|
|
type Encodable interface {
|
|
// Encode sends data to encoder. It returns the amount of bytes written,
|
|
// and an error if the write stopped early.
|
|
Encode(encoder *Encoder) (n int, err error)
|
|
}
|
|
|
|
// Encoder encodes data to an io.Writer.
|
|
type Encoder struct {
|
|
bufio.Writer
|
|
}
|
|
|
|
// NewEncoder creates a new encoder that writes to writer.
|
|
func NewEncoder(writer io.Writer) *Encoder {
|
|
encoder := &Encoder { }
|
|
encoder.Reset(writer)
|
|
return encoder
|
|
}
|
|
|
|
// WriteInt8 encodes an 8-bit signed integer to the output writer.
|
|
func (this *Encoder) WriteInt8(value int8) (n int, err error) {
|
|
return this.WriteUint8(uint8(value))
|
|
}
|
|
|
|
// WriteUint8 encodes an 8-bit unsigned integer to the output writer.
|
|
func (this *Encoder) WriteUint8(value uint8) (n int, err error) {
|
|
return this.Write([]byte { byte(value) })
|
|
}
|
|
|
|
// WriteInt16 encodes an 16-bit signed integer to the output writer.
|
|
func (this *Encoder) WriteInt16(value int16) (n int, err error) {
|
|
return this.WriteUint16(uint16(value))
|
|
}
|
|
|
|
// WriteUint16 encodes an 16-bit unsigned integer to the output writer.
|
|
func (this *Encoder) WriteUint16(value uint16) (n int, err error) {
|
|
return this.Write([]byte {
|
|
byte(value >> 8),
|
|
byte(value),
|
|
})
|
|
}
|
|
|
|
// WriteInt32 encodes an 32-bit signed integer to the output writer.
|
|
func (this *Encoder) WriteInt32(value int32) (n int, err error) {
|
|
return this.WriteUint32(uint32(value))
|
|
}
|
|
|
|
// WriteUint32 encodes an 32-bit unsigned integer to the output writer.
|
|
func (this *Encoder) WriteUint32(value uint32) (n int, err error) {
|
|
return this.Write([]byte {
|
|
byte(value >> 24),
|
|
byte(value >> 16),
|
|
byte(value >> 8),
|
|
byte(value),
|
|
})
|
|
}
|
|
|
|
// WriteInt64 encodes an 64-bit signed integer to the output writer.
|
|
func (this *Encoder) WriteInt64(value int64) (n int, err error) {
|
|
return this.WriteUint64(uint64(value))
|
|
}
|
|
|
|
// WriteUint64 encodes an 64-bit unsigned integer to the output writer.
|
|
func (this *Encoder) WriteUint64(value uint64) (n int, err error) {
|
|
return this.Write([]byte {
|
|
byte(value >> 56),
|
|
byte(value >> 48),
|
|
byte(value >> 40),
|
|
byte(value >> 32),
|
|
byte(value >> 24),
|
|
byte(value >> 16),
|
|
byte(value >> 8),
|
|
byte(value),
|
|
})
|
|
}
|
|
|
|
// WriteIntN encodes an N-byte signed integer to the output writer.
|
|
func (this *Encoder) WriteIntN(value int64, bytes int) (n int, err error) {
|
|
return this.WriteUintN(uint64(value), bytes)
|
|
}
|
|
|
|
// for Write/ReadUintN, increase buffers if go somehow gets support for over 64
|
|
// bit integers. we could also make an expanding int type in goutil to use here,
|
|
// or maybe there is one in the stdlib. keep the int64 versions as well though
|
|
// because its ergonomic.
|
|
|
|
// WriteUintN encodes an N-byte unsigned integer to the output writer.
|
|
func (this *Encoder) WriteUintN(value uint64, bytes int) (n int, err error) {
|
|
// TODO: don't make multiple write calls (without allocating)
|
|
buffer := [1]byte { }
|
|
for bytesLeft := bytes; bytesLeft > 0; bytesLeft -- {
|
|
buffer[0] = byte(value) >> ((bytesLeft - 1) * 8)
|
|
nn, err := this.Write(buffer[:])
|
|
n += nn; if err != nil { return n, err }
|
|
}
|
|
return n, nil
|
|
}
|
|
|
|
// WriteFloat32 encodes a 32-bit floating point value to the output writer.
|
|
func (this *Encoder) WriteFloat32(value float32) (n int, err error) {
|
|
return this.WriteUint32(math.Float32bits(value))
|
|
}
|
|
|
|
// WriteFloat64 encodes a 64-bit floating point value to the output writer.
|
|
func (this *Encoder) WriteFloat64(value float64) (n int, err error) {
|
|
return this.WriteUint64(math.Float64bits(value))
|
|
}
|
|
|
|
// WriteTag encodes a [Tag] to the output writer.
|
|
func (this *Encoder) WriteTag(value Tag) (n int, err error) {
|
|
return this.WriteUint8(uint8(value))
|
|
}
|