blob: d1b31a1dc045ba6770e50ed2701fcad535dbd928 [file] [log] [blame]
// Copyright 2016 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package vdl
// Transcode transcodes from the decoder to the encoder.
func Transcode(e Encoder, d Decoder) error {
if err := d.StartValue(AnyType); err != nil {
return err
}
if d.IsNil() {
if err := e.NilValue(d.Type()); err != nil {
return err
}
return d.FinishValue()
}
if d.IsOptional() {
e.SetNextStartValueIsOptional()
}
if err := e.StartValue(d.Type()); err != nil {
return err
}
if err := transcodeNonNilValue(e, d); err != nil {
return err
}
if err := d.FinishValue(); err != nil {
return err
}
return e.FinishValue()
}
func transcodeNonNilValue(e Encoder, d Decoder) error {
if d.Type().IsBytes() {
var b []byte
fixedLen := -1
if d.Type().Kind() == Array {
fixedLen = d.Type().Len()
b = make([]byte, fixedLen)
}
if err := d.DecodeBytes(fixedLen, &b); err != nil {
return err
}
return e.EncodeBytes(b)
}
switch d.Type().Kind() {
case Bool:
val, err := d.DecodeBool()
if err != nil {
return err
}
return e.EncodeBool(val)
case Byte, Uint16, Uint32, Uint64:
val, err := d.DecodeUint(d.Type().Kind().BitLen())
if err != nil {
return err
}
return e.EncodeUint(val)
case Int8, Int16, Int32, Int64:
val, err := d.DecodeInt(d.Type().Kind().BitLen())
if err != nil {
return err
}
return e.EncodeInt(val)
case Float32, Float64:
val, err := d.DecodeFloat(d.Type().Kind().BitLen())
if err != nil {
return err
}
return e.EncodeFloat(val)
case String, Enum:
val, err := d.DecodeString()
if err != nil {
return err
}
return e.EncodeString(val)
case TypeObject:
val, err := d.DecodeTypeObject()
if err != nil {
return err
}
return e.EncodeTypeObject(val)
case List, Array, Set:
return transcodeListOrArrayOrSet(e, d)
case Map:
return transcodeMap(e, d)
case Struct, Union:
return transcodeStructOrUnion(e, d)
}
panic("unhandled kind")
}
func transcodeListOrArrayOrSet(e Encoder, d Decoder) error {
if err := e.SetLenHint(d.LenHint()); err != nil {
return err
}
for {
switch done, err := d.NextEntry(); {
case err != nil:
return err
case done:
return e.NextEntry(true)
default:
if err := e.NextEntry(false); err != nil {
return err
}
if err := Transcode(e, d); err != nil {
return err
}
}
}
}
func transcodeMap(e Encoder, d Decoder) error {
if err := e.SetLenHint(d.LenHint()); err != nil {
return err
}
for {
switch done, err := d.NextEntry(); {
case err != nil:
return err
case done:
return e.NextEntry(true)
default:
if err := e.NextEntry(false); err != nil {
return err
}
if err := Transcode(e, d); err != nil {
return err
}
if err := Transcode(e, d); err != nil {
return err
}
}
}
}
func transcodeStructOrUnion(e Encoder, d Decoder) error {
for {
switch index, err := d.NextField(); {
case err != nil:
return err
case index == -1:
return e.NextField(-1)
default:
if err := e.NextField(index); err != nil {
return err
}
if err := Transcode(e, d); err != nil {
return err
}
}
}
}