blob: a620e4ac53d83aeeb16d2f7214cdbf20dfe94ee6 [file] [log] [blame]
// Copyright (C) 2014 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package binary
import (
"io"
"math"
)
// Decoder provides methods for decoding values to an io.Reader.
type Decoder struct {
reader io.Reader
tmp [8]byte
objects map[uint16]interface{}
}
// NewDecoder creates a Decoder that reads from the provided io.Reader.
func NewDecoder(reader io.Reader) *Decoder {
return &Decoder{reader: reader, objects: map[uint16]interface{}{}}
}
// Read implements the io.Reader interface, delegating to the underlying reader.
func (d *Decoder) Read(p []byte) (int, error) {
return d.reader.Read(p)
}
// TypeID decodes and returns a type id from the Decoder's io.Reader.
func (d *Decoder) TypeID() (TypeID, error) {
var id TypeID
_, err := io.ReadFull(d.reader, id[:])
return id, err
}
// Bool decodes and returns a boolean value from the Decoder's io.Reader.
func (d *Decoder) Bool() (bool, error) {
b := d.tmp[:1]
_, err := io.ReadFull(d.reader, b[:1])
return b[0] != 0, err
}
// Int8 decodes and returns a signed, 8 bit integer value from the Decoder's io.Reader.
func (d *Decoder) Int8() (int8, error) {
i, err := d.Uint8()
return int8(i), err
}
// Uint8 decodes and returns an unsigned, 8 bit integer value from the Decoder's io.Reader.
func (d *Decoder) Uint8() (uint8, error) {
b := d.tmp[:1]
_, err := io.ReadFull(d.reader, b[:1])
return b[0], err
}
// Int16 decodes and returns a signed, 16 bit integer value from the Decoder's io.Reader.
func (d *Decoder) Int16() (int16, error) {
i, err := d.Uint16()
return int16(i), err
}
// Uint16 decodes and returns an unsigned, 16 bit integer value from the Decoder's io.Reader.
func (d *Decoder) Uint16() (uint16, error) {
b := d.tmp[:2]
_, err := io.ReadFull(d.reader, b)
return uint16(b[0]) | uint16(b[1])<<8, err
}
// Int32 decodes and returns a signed, 32 bit integer value from the Decoder's io.Reader.
func (d *Decoder) Int32() (int32, error) {
i, err := d.Uint32()
return int32(i), err
}
// Uint32 decodes and returns an unsigned, 32 bit integer value from the Decoder's io.Reader.
func (d *Decoder) Uint32() (uint32, error) {
b := d.tmp[:4]
_, err := io.ReadFull(d.reader, b[:])
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24, err
}
// Float32 decodes and returns a 32 bit floating-point value from the Decoder's io.Reader.
func (d *Decoder) Float32() (float32, error) {
i, err := d.Uint32()
return math.Float32frombits(i), err
}
// Int64 decodes and returns a signed, 64 bit integer value from the Decoder's io.Reader.
func (d *Decoder) Int64() (int64, error) {
i, err := d.Uint64()
return int64(i), err
}
// Uint64 decodes and returns an unsigned, 64 bit integer value from the Decoder's io.Reader.
func (d *Decoder) Uint64() (uint64, error) {
b := d.tmp[:8]
_, err := io.ReadFull(d.reader, b[:])
return uint64(b[0]) |
uint64(b[1])<<8 |
uint64(b[2])<<16 |
uint64(b[3])<<24 |
uint64(b[4])<<32 |
uint64(b[5])<<40 |
uint64(b[6])<<48 |
uint64(b[7])<<56, err
}
// Float64 decodes and returns a 64 bit floating-point value from the Decoder's io.Reader.
func (d *Decoder) Float64() (float64, error) {
i, err := d.Uint64()
return math.Float64frombits(i), err
}
// String decodes and returns a string (pascal-style) from the Decoder's io.Reader.
func (d *Decoder) String() (string, error) {
c, err := d.Uint32()
if err != nil {
return "", err
}
if c > 0 {
s := make([]byte, c)
_, err := io.ReadFull(d.reader, s)
return string(s), err
} else {
return "", nil
}
}
// String decodes and returns a string (c-style) from the Decoder's io.Reader.
func (d *Decoder) CString() (string, error) {
s := []byte{}
for {
c, err := d.Uint8()
if err != nil {
return "", err
}
if c == 0 {
break
}
s = append(s, c)
}
return string(s), nil
}
// Data decodes and returns a sequence of bytes from the Decoder's io.Reader.
func (d *Decoder) Data() ([]byte, error) {
c, err := d.Uint32()
if err != nil {
return nil, err
}
buf := make([]byte, c)
_, err = io.ReadFull(d.reader, buf)
return buf, err
}
// Object decodes and returns an Object from the Decoder's io.Reader. Object instances that were
// encoded multiple times will be decoded and returned as a shared, single instance.
// The type id in the stream must have been previously registered with binary.Register.
func (d *Decoder) Object() (interface{}, error) {
key, err := d.Uint16()
if err != nil {
return nil, err
}
if key == objectNil {
return nil, nil
}
if obj, alreadyDecoded := d.objects[key]; alreadyDecoded {
return obj, nil
}
id, err := d.TypeID()
if err != nil {
return nil, err
}
obj, err := MakeObject(id)
if err != nil {
return nil, err
}
if err = obj.Decode(d); err != nil {
return nil, err
}
d.objects[key] = obj
return obj, nil
}