package tape import "io" import "math" import "bufio" // Decodable is any type that can decode itself from a decoder. type Decodable interface { // Decode reads data from decoder, replacing the data of the object. It // returns the amount of bytes written, and an error if the write // stopped early. Decode(decoder *Decoder) (n int, err error) } // Decoder decodes data from an [io.Reader]. type Decoder struct { bufio.Reader } // NewDecoder creates a new decoder that reads from reader. func NewDecoder(reader io.Reader) *Decoder { decoder := &Decoder { } decoder.Reader.Reset(reader) return decoder } // ReadFull calls [io.ReadFull] on the reader. func (this *Decoder) ReadFull(buffer []byte) (n int, err error) { return io.ReadFull(this, buffer) } // ReadInt8 decodes an 8-bit signed integer from the input reader. func (this *Decoder) ReadInt8() (value int8, n int, err error) { uncasted, n, err := this.ReadUint8() return int8(uncasted), n, err } // ReadUint8 decodes an 8-bit unsigned integer from the input reader. func (this *Decoder) ReadUint8() (value uint8, n int, err error) { buffer := [1]byte { } n, err = this.ReadFull(buffer[:]) return uint8(buffer[0]), n, err } // ReadInt16 decodes an 16-bit signed integer from the input reader. func (this *Decoder) ReadInt16() (value int16, n int, err error) { uncasted, n, err := this.ReadUint16() return int16(uncasted), n, err } // ReadUint16 decodes an 16-bit unsigned integer from the input reader. func (this *Decoder) ReadUint16() (value uint16, n int, err error) { buffer := [2]byte { } n, err = this.ReadFull(buffer[:]) return uint16(buffer[0]) << 8 | uint16(buffer[1]), n, err } // ReadInt32 decodes an 32-bit signed integer from the input reader. func (this *Decoder) ReadInt32() (value int32, n int, err error) { uncasted, n, err := this.ReadUint32() return int32(uncasted), n, err } // ReadUint32 decodes an 32-bit unsigned integer from the input reader. func (this *Decoder) ReadUint32() (value uint32, n int, err error) { buffer := [4]byte { } n, err = this.ReadFull(buffer[:]) return uint32(buffer[0]) << 24 | uint32(buffer[1]) << 16 | uint32(buffer[2]) << 8 | uint32(buffer[3]), n, err } // ReadInt64 decodes an 64-bit signed integer from the input reader. func (this *Decoder) ReadInt64() (value int64, n int, err error) { uncasted, n, err := this.ReadUint64() return int64(uncasted), n, err } // ReadUint64 decodes an 64-bit unsigned integer from the input reader. func (this *Decoder) ReadUint64() (value uint64, n int, err error) { buffer := [8]byte { } n, err = this.ReadFull(buffer[:]) return uint64(buffer[0]) << 56 | uint64(buffer[1]) << 48 | uint64(buffer[2]) << 40 | uint64(buffer[3]) << 32 | uint64(buffer[4]) << 24 | uint64(buffer[5]) << 16 | uint64(buffer[6]) << 8 | uint64(buffer[7]), n, err } // ReadIntN decodes an N-byte signed integer from the input reader. func (this *Decoder) ReadIntN(bytes int) (value int64, n int, err error) { uncasted, n, err := this.ReadUintN(bytes) return int64(uncasted), n, err } // ReadUintN decodes an N-byte unsigned integer from the input reader. func (this *Decoder) ReadUintN(bytes int) (value uint64, n int, err error) { // TODO: don't make multiple read calls (without allocating) buffer := [1]byte { } for bytesLeft := bytes; bytesLeft > 0; bytesLeft -- { nn, err := this.ReadFull(buffer[:]) n += nn; if err != nil { return 0, n, err } value |= uint64(buffer[0]) << ((bytesLeft - 1) * 8) } // *read* integers too big, but don't return them. if bytes > 8 { value = 0 } return value, n, nil } // ReadFloat16 decodes a 16-bit floating point value from the input reader. func (this *Decoder) ReadFloat16() (value float32, n int, err error) { bits, nn, err := this.ReadUint16() n += nn; if err != nil { return 0, n, err } return math.Float32frombits(f16bitsToF32bits(bits)), n, nil } // ReadFloat32 decldes a 32-bit floating point value from the input reader. func (this *Decoder) ReadFloat32() (value float32, n int, err error) { bits, nn, err := this.ReadUint32() n += nn; if err != nil { return 0, n, err } return math.Float32frombits(bits), n, nil } // ReadFloat64 decldes a 64-bit floating point value from the input reader. func (this *Decoder) ReadFloat64() (value float64, n int, err error) { bits, nn, err := this.ReadUint64() n += nn; if err != nil { return 0, n, err } return math.Float64frombits(bits), n, nil } // ReadTag decodes a [Tag] from the input reader. func (this *Decoder) ReadTag() (value Tag, n int, err error) { uncasted, nn, err := this.ReadUint8() n += nn; if err != nil { return 0, n, err } return Tag(uncasted), n, nil } // f16bitsToF32bits returns uint32 (float32 bits) converted from specified uint16. // Taken from https://github.com/x448/float16/blob/v0.8.4/float16 // // MIT License // // Copyright (c) 2019 Montgomery Edwards⁴⁴⁸ and Faye Amacker // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. func f16bitsToF32bits(in uint16) uint32 { // All 65536 conversions with this were confirmed to be correct // by Montgomery Edwards⁴⁴⁸ (github.com/x448). sign := uint32(in&0x8000) << 16 // sign for 32-bit exp := uint32(in&0x7c00) >> 10 // exponenent for 16-bit coef := uint32(in&0x03ff) << 13 // significand for 32-bit if exp == 0x1f { if coef == 0 { // infinity return sign | 0x7f800000 | coef } // NaN return sign | 0x7fc00000 | coef } if exp == 0 { if coef == 0 { // zero return sign } // normalize subnormal numbers exp++ for coef&0x7f800000 == 0 { coef <<= 1 exp-- } coef &= 0x007fffff } return sign | ((exp + (0x7f - 0xf)) << 23) | coef }