| package vom |
| |
| import ( |
| "errors" |
| "fmt" |
| "io" |
| "os" |
| "reflect" |
| |
| "v.io/v23/vdl" |
| ) |
| |
| var ( |
| errDecodeNil = errors.New("invalid decode into nil interface{}") |
| errDecodeNilRawValue = errors.New("invalid decode into nil *RawValue") |
| ) |
| |
| // Decoder manages the receipt and unmarshaling of typed values from the other |
| // side of a connection. |
| type Decoder struct { |
| dec decoder |
| } |
| |
| type decoder interface { |
| Decode(target vdl.Target) error |
| DecodeRaw(raw *RawValue) error |
| Ignore() error |
| } |
| |
| // This is only used for debugging; add this as the first line of NewDecoder to |
| // dump formatted vom bytes to stdout: |
| // r = teeDump(r) |
| func teeDump(r io.Reader) io.Reader { |
| return io.TeeReader(r, NewDumper(NewDumpWriter(os.Stdout))) |
| } |
| |
| // NewDecoder returns a new Decoder that reads from the given reader. The |
| // Decoder understands all formats generated by the Encoder. |
| func NewDecoder(r io.Reader) (*Decoder, error) { |
| buf, types := newDecbuf(r), newDecoderTypes() |
| magic, err := buf.PeekByte() |
| if err != nil { |
| return nil, fmt.Errorf("error reading magic byte %v", err) |
| } |
| if magic != binaryMagicByte { |
| return nil, fmt.Errorf("bad magic byte, got %x, want %x", magic, binaryMagicByte) |
| } |
| buf.Skip(1) |
| return &Decoder{newBinaryDecoder(buf, types)}, nil |
| } |
| |
| // Decode reads the next value from the reader and stores it in value v. |
| // The type of v need not exactly match the type of the originally encoded |
| // value; decoding succeeds as long as the values are compatible. |
| // |
| // Types that are special-cased, only for v: |
| // *RawValue - Store raw (uninterpreted) bytes in v. |
| // |
| // Types that are special-cased, recursively throughout v: |
| // *vdl.Value - Decode into v. |
| // reflect.Value - Decode into v, which must be settable. |
| // |
| // Decoding into a RawValue captures the value in a raw form, which may be |
| // subsequently passed to an Encoder for transcoding. |
| // |
| // Decode(nil) always returns an error. Use Ignore() to ignore the next value. |
| func (d *Decoder) Decode(v interface{}) error { |
| switch tv := v.(type) { |
| case nil: |
| return errDecodeNil |
| case *RawValue: |
| if tv == nil { |
| return errDecodeNilRawValue |
| } |
| return d.dec.DecodeRaw(tv) |
| } |
| target, err := vdl.ReflectTarget(reflect.ValueOf(v)) |
| if err != nil { |
| return err |
| } |
| return d.dec.Decode(target) |
| } |
| |
| // Ignore ignores the next value from the reader. |
| func (d *Decoder) Ignore() error { |
| return d.dec.Ignore() |
| } |