vdl/vom: Add vom.RawBytes.VDLRead, and some bugfixes.

The idea behind vom.RawBytes.VDLRead is straightforward, but
there's a catch in the implementation; in order to work (easily),
we need to ensure that dec.StartValue hasn't been called.  I've
restructured the reflect_reader.go code to make this happen.

One bugfix is in vdl.Value.VDLRead.  It wasn't quite handling
type compatibility checks correctly, in both the nil and the
non-nil cases.  More importantly, I've added logic to allow
invalid values (where the type hasn't been set yet) to be read
and filled.  This is useful given the general reflect_reader.go
strategy of creating zero values and calling VDLRead.

Another bugfix is in TypeToReflect, to add handling for the
ErrorType case.  The basic idea is that if we're decoding from
error(nil) to any(nil), we should end up with any(error(nil)).
Adding the logic to TypeToReflect makes the existing convert.go
logic do the right thing, but it's hard to update the test to
reflect this.  Instead I've added typeToReflectFixed, which adds
the ErrorType case, and I've left TypeToReflect as-is.  We'll
flip over after we remove the existing convert logic.

Change-Id: I11b7db2ebbe2593c0da53156f70781bd4c963404
diff --git a/vdl/reflect_reader.go b/vdl/reflect_reader.go
index b1fe7b7..8260e6b 100644
--- a/vdl/reflect_reader.go
+++ b/vdl/reflect_reader.go
@@ -11,10 +11,11 @@
 )
 
 var (
-	errMustReflect          = errors.New("vdl: value must be handled via reflection")
-	errNilValue             = errors.New("vdl: nil value is invalid")
-	errReflectCantSet       = errors.New("vdl: reflect.Value cannot be set")
-	errReadAnyInterfaceOnly = errors.New("vdl: read into any only supported for interfaces")
+	errReadMustReflect       = errors.New("vdl: read must be handled via reflection")
+	errReadIntoNilValue      = errors.New("vdl: read into nil value")
+	errReadReflectCantSet    = errors.New("vdl: read into unsettable reflect.Value")
+	errReadAnyAlreadyStarted = errors.New("vdl: read into any after StartValue called")
+	errReadAnyInterfaceOnly  = errors.New("vdl: read into any only supported for interfaces")
 )
 
 // Read uses dec to decode a value into v, calling VDLRead methods and fast
@@ -22,7 +23,7 @@
 // basically an all-purpose VDLRead implementation.
 func Read(dec Decoder, v interface{}) error {
 	if v == nil {
-		return errNilValue
+		return errReadIntoNilValue
 	}
 	rv := reflect.ValueOf(v)
 	if rv.Kind() == reflect.Ptr && !rv.IsNil() {
@@ -32,7 +33,7 @@
 		//
 		// TODO(toddw): If reflection is too slow, add the nil pointer check to all
 		// VDLRead methods, as well as other readNonReflect cases below.
-		if err := readNonReflect(dec, false, v); err != errMustReflect {
+		if err := readNonReflect(dec, false, v); err != errReadMustReflect {
 			return err
 		}
 	}
@@ -75,21 +76,21 @@
 		}
 		return dec.FinishValue()
 	}
-	return errMustReflect
+	return errReadMustReflect
 }
 
 // ReadReflect is like Read, but takes a reflect.Value argument.  Use Read if
 // performance is important and you have an interface{} handy.
 func ReadReflect(dec Decoder, rv reflect.Value) error {
 	if !rv.IsValid() {
-		return errNilValue
+		return errReadIntoNilValue
 	}
 	if !rv.CanSet() && rv.Kind() == reflect.Ptr && !rv.IsNil() {
 		// Dereference the pointer a single time to make rv settable.
 		rv = rv.Elem()
 	}
 	if !rv.CanSet() {
-		return errReflectCantSet
+		return errReadReflectCantSet
 	}
 	tt, err := TypeFromReflect(rv.Type())
 	if err != nil {
@@ -114,6 +115,12 @@
 }
 
 func readNonNative(dec Decoder, calledStart bool, rv reflect.Value, tt *Type) error {
+	// Any is handled first, since any(nil) is handled differently from ?T(nil)
+	// contained in an any value, so this factoring makes things simpler.
+	if tt == AnyType {
+		return readAny(dec, calledStart, rv)
+	}
+	// Now we can start the decoder value, if we haven't already.
 	if !calledStart {
 		if err := dec.StartValue(); err != nil {
 			return err
@@ -122,28 +129,24 @@
 			return err
 		}
 	}
-	switch {
-	case tt == AnyType:
-		// Any is handled first, to treat any(nil) differently from ?T(nil).
-		return readAny(dec, rv)
-	case dec.IsNil():
-		// Nil decoded values are handled next, to special-case the pointer
-		// handling; we don't create pointers all the way down to the actual value.
-		return readNil(dec, rv, tt)
+	// Nil decoded values are handled next, to special-case the pointer handling;
+	// we don't create pointers all the way down to the actual value.
+	if dec.IsNil() {
+		return readFromNil(dec, rv, tt)
 	}
 	// Now we know that the decoded value isn't nil.  Walk pointers and check for
 	// faster non-reflect support.
 	rv = readWalkPointers(rv)
-	if err := readNonReflect(dec, true, rv.Addr().Interface()); err != errMustReflect {
+	if err := readNonReflect(dec, true, rv.Addr().Interface()); err != errReadMustReflect {
 		return err
 	}
 	// Special-case the error interface, and fill it in with the native error
-	// representation verror.E.  Nil errors are handled above in readNil.
+	// representation verror.E.  Nil errors are handled above in readFromNil.
 	if rv.Type() == rtError {
 		return readNonNilError(dec, rv)
 	}
-	// Handle the non-nil value.
-	if err := readNonNil(dec, rv, tt.NonOptional()); err != nil {
+	// Handle the non-nil decoded value.
+	if err := readNonNilValue(dec, rv, tt.NonOptional()); err != nil {
 		return err
 	}
 	return dec.FinishValue()
@@ -165,11 +168,22 @@
 	return rv
 }
 
-func readAny(dec Decoder, rv reflect.Value) error {
+func readAny(dec Decoder, calledStart bool, rv reflect.Value) error {
+	if calledStart {
+		// The existing code ensures that calledStart is always false here, since
+		// readReflect(dec, true, ...) is only called below in this function, which
+		// never calls it with another any type.  If we did, we'd have a vdl
+		// any(any), which isn't allowed.  This error tries to prevent future
+		// changes that will break this requirement.
+		//
+		// Also note that the implementation of vom.RawBytes.VDLRead requires that
+		// StartValue has not been called yet.
+		return errReadAnyAlreadyStarted
+	}
 	// Walk pointers and check for faster non-reflect support, which handles
 	// vdl.Value and vom.RawBytes, and any other special-cases.
 	rv = readWalkPointers(rv)
-	if err := readNonReflect(dec, true, rv.Addr().Interface()); err != errMustReflect {
+	if err := readNonReflect(dec, true, rv.Addr().Interface()); err != errReadMustReflect {
 		return err
 	}
 	// The only case left is to handle interfaces.  We allow decoding into
@@ -177,6 +191,9 @@
 	if rv.Kind() != reflect.Interface {
 		return errReadAnyInterfaceOnly
 	}
+	if err := dec.StartValue(); err != nil {
+		return err
+	}
 	// Handle decoding any(nil) by setting the interface to nil.  Note that the
 	// only case where dec.Type() is AnyType is when the value is any(nil).
 	if dec.Type() == AnyType {
@@ -185,7 +202,10 @@
 	}
 	// Lookup the reflect type based on the decoder type, and create a new value
 	// to decode into.
-	rtDecode := TypeToReflect(dec.Type())
+	//
+	// TODO(toddw): Replace typeToReflectFixed with TypeToReflect, after we've
+	// fixed it to treat the error type correctly.
+	rtDecode := typeToReflectFixed(dec.Type())
 	switch {
 	case rtDecode == nil:
 		return fmt.Errorf("vdl: %v not registered, call vdl.Register, or use vdl.Value or vom.RawBytes instead", dec.Type())
@@ -209,11 +229,12 @@
 	return nil
 }
 
-func readNil(dec Decoder, rv reflect.Value, tt *Type) error {
+func readFromNil(dec Decoder, rv reflect.Value, tt *Type) error {
 	if tt.Kind() != Optional {
-		return fmt.Errorf("can't decode nil into non-optional %v", tt)
+		return fmt.Errorf("vdl: can't decode nil into non-optional %v", tt)
 	}
-	// Note that rv is always a pointer, since tt is optional.
+	// Note that since tt is optional, we know that rv is always a pointer, or the
+	// special-case error interface.
 	rv.Set(reflect.Zero(rv.Type()))
 	return dec.FinishValue()
 }
@@ -240,7 +261,7 @@
 	return nil
 }
 
-func readNonNil(dec Decoder, rv reflect.Value, tt *Type) error {
+func readNonNilValue(dec Decoder, rv reflect.Value, tt *Type) error {
 	// Handle named and unnamed []byte and [N]byte, where the element type is the
 	// unnamed byte type.  Cases like []MyByte fall through and are handled as
 	// regular lists, since we can't easily convert []MyByte to []byte.
@@ -313,8 +334,8 @@
 		return readUnion(dec, rv, tt)
 	}
 	// Note that Any was already handled via readAny, Optional was handled via
-	// readNil (or stripped off for non-nil values), and TypeObject was handled
-	// via the readNonReflect special-case.
+	// readFromNil (or stripped off for non-nil values), and TypeObject was
+	// handled via the readNonReflect special-case.
 	panic(fmt.Errorf("vdl: unhandled type %v in Read", tt))
 }
 
diff --git a/vdl/register.go b/vdl/register.go
index 366223a..0b1e61b 100644
--- a/vdl/register.go
+++ b/vdl/register.go
@@ -364,6 +364,9 @@
 // named types in our registry, and build the unnamed types that we can via the
 // Go reflect package.  Returns nil for types that can't be manufactured.
 func TypeToReflect(t *Type) reflect.Type {
+	// TODO(toddw): This is broken, since it doesn't handle registered native
+	// error types correctly.  But it's hard to fix with the old convert.go logic,
+	// so we'll wait until we get rid of that code completely.
 	if t.Name() != "" {
 		// Named types cannot be manufactured via Go reflect, so we lookup in our
 		// registry instead.
@@ -415,6 +418,65 @@
 	}
 }
 
+// TODO(toddw): Replace TypeToReflect with typeToReflectFixed after the old
+// conversion logic is removed.
+func typeToReflectFixed(t *Type) reflect.Type {
+	if t == ErrorType {
+		if ni, err := nativeInfoForError(); err == nil {
+			return reflect.PtrTo(ni.NativeType)
+		}
+	}
+	if t.Name() != "" {
+		// Named types cannot be manufactured via Go reflect, so we lookup in our
+		// registry instead.
+		if ri := reflectInfoFromName(t.Name()); ri != nil {
+			if ni := nativeInfoFromWire(ri.Type); ni != nil {
+				return ni.NativeType
+			}
+			return ri.Type
+		}
+		return nil
+	}
+	// We can make some unnamed types via Go reflect.  Return nil otherwise.
+	switch t.Kind() {
+	case Any, Enum, Union:
+		// We can't make unnamed versions of any of these types.
+		return nil
+	case Optional:
+		if elem := typeToReflectFixed(t.Elem()); elem != nil {
+			return reflect.PtrTo(elem)
+		}
+		return nil
+	case Array:
+		if elem := typeToReflectFixed(t.Elem()); elem != nil {
+			return reflect.ArrayOf(t.Len(), elem)
+		}
+		return nil
+	case List:
+		if elem := typeToReflectFixed(t.Elem()); elem != nil {
+			return reflect.SliceOf(elem)
+		}
+		return nil
+	case Set:
+		if key := typeToReflectFixed(t.Key()); key != nil {
+			return reflect.MapOf(key, rtUnnamedEmptyStruct)
+		}
+		return nil
+	case Map:
+		if key, elem := typeToReflectFixed(t.Key()), typeToReflectFixed(t.Elem()); key != nil && elem != nil {
+			return reflect.MapOf(key, elem)
+		}
+		return nil
+	case Struct:
+		if t.NumField() == 0 {
+			return rtUnnamedEmptyStruct
+		}
+		return nil
+	default:
+		return rtFromKind[t.Kind()]
+	}
+}
+
 var rtFromKind = [...]reflect.Type{
 	Bool:       rtBool,
 	Byte:       rtByte,
diff --git a/vdl/value.go b/vdl/value.go
index 3859aa5..49415d5 100644
--- a/vdl/value.go
+++ b/vdl/value.go
@@ -173,7 +173,7 @@
 
 // OptionalValue returns an optional value with elem assigned to x.  Panics if
 // the type of x cannot be made optional.
-func OptionalValue(x *Value) *Value { return &Value{OptionalType(x.t), x} }
+func OptionalValue(x *Value) *Value { return &Value{OptionalType(x.t), CopyValue(x)} }
 
 // BoolValue is a convenience to create a Bool value.
 func BoolValue(x bool) *Value { return ZeroValue(BoolType).AssignBool(x) }
@@ -319,8 +319,8 @@
 	return ok && vrep == nil
 }
 
-// IsValid returns true iff v is valid.  Nil and new(Value) are invalid; most
-// other methods panic if called on an invalid Value.
+// IsValid returns true iff v is valid, where v == nil and v == new(Value) are
+// invalid.  Most other methods panic if called on an invalid Value.
 func (v *Value) IsValid() bool {
 	return v != nil && v.t != nil
 }
diff --git a/vdl/value_reader.go b/vdl/value_reader.go
index 203dcab..e6a98f6 100644
--- a/vdl/value_reader.go
+++ b/vdl/value_reader.go
@@ -8,68 +8,86 @@
 	"fmt"
 )
 
-// VDLRead reads from a decoder into this vdl Value.
+// VDLRead uses dec to decode a value in vv.  If vv isn't valid (i.e. has no
+// type), it will be filled in the exact type of value read from the decoder.
+// Otherwise the type of vv must be compatible with the type of the value read
+// from the decoder.
 func (vv *Value) VDLRead(dec Decoder) error {
-	if vv == nil || vv.t == nil {
-		return fmt.Errorf("cannot decode into nil vdl value")
+	if vv == nil {
+		return errReadIntoNilValue
 	}
 	if err := dec.StartValue(); err != nil {
 		return err
 	}
-	if dec.IsNil() {
-		return vv.readHandleNil(dec)
-	}
-	fillvvAny := vv
-	if vv.Kind() == Any {
-		innerType := dec.Type()
-		if dec.IsOptional() {
-			innerType = OptionalType(innerType)
+	if !vv.IsValid() {
+		// Initialize vv to the zero value of the exact type read from the decoder.
+		// It is as if vv were initialized to that type to begin with.
+		switch {
+		case dec.IsAny():
+			*vv = *ZeroValue(AnyType)
+		case dec.IsOptional():
+			*vv = *ZeroValue(OptionalType(dec.Type()))
+		default:
+			*vv = *ZeroValue(dec.Type())
 		}
-		fillvvAny = ZeroValue(innerType)
 	}
-	fillvv := fillvvAny
-	if fillvvAny.Kind() == Optional {
-		fillvv = ZeroValue(fillvvAny.Type().Elem())
-	}
-
-	if err := fillvv.readFillValue(dec); err != nil {
+	if err := decoderCompatible(dec, vv.Type()); err != nil {
 		return err
 	}
-
-	if fillvvAny.Kind() == Optional {
-		fillvvAny.Assign(OptionalValue(fillvv))
+	// Handle nil decoded values first, to simplify the rest of the cases.
+	if dec.IsNil() {
+		return vv.readFromNil(dec)
 	}
-	if vv.Kind() == Any {
-		vv.Assign(fillvvAny)
+	// Handle non-nil values.  If vv is any or optional we need to treat it
+	// specially, since it needs to be assigned after the value is read.
+	vvFill, makeOptional := vv, false
+	switch {
+	case vv.Kind() == Any:
+		// Fill in a value of the type read from the decoder.
+		vvFill = ZeroValue(dec.Type())
+		makeOptional = dec.IsOptional()
+	case vv.Kind() == Optional:
+		// Fill in a value of our elem type.
+		vvFill = ZeroValue(vv.Type().Elem())
+		makeOptional = true
+	}
+	if err := vvFill.readNonNilValue(dec); err != nil {
+		return err
+	}
+	// Finished reading, handle any and optional cases.
+	if makeOptional {
+		vvFill = OptionalValue(vvFill)
+	}
+	if vv.Kind() == Any || vv.Kind() == Optional {
+		vv.Assign(vvFill)
 	}
 	return dec.FinishValue()
 }
 
-// readHandleNil handles the case that dec.IsNil() is true
-func (vv *Value) readHandleNil(dec Decoder) error {
+func (vv *Value) readFromNil(dec Decoder) error {
+	// We've already checked for compatibility above, so we know that we're
+	// allowed to set the nil value.
 	switch {
-	case dec.IsOptional():
-		// handles optional inside-any and optional on-its-own cases
-		if dec.Type().Kind() != Optional {
-			return fmt.Errorf("invalid optional value returned from decoder of type %v", dec.Type())
-		}
+	case vv.Kind() == Any:
+		// Make sure that any(nil) and ?T(nil) are retained correctly in the any.
 		vv.Assign(ZeroValue(dec.Type()))
-	case dec.IsAny():
+	case vv.Kind() == Optional:
+		// Just set the optional to nil.
 		vv.Assign(nil)
 	default:
-		return fmt.Errorf("invalid non-any, non-optional nil value of type %v", dec.Type())
+		return fmt.Errorf("vdl: can't decode nil into non-any non-optional %v", vv.Type())
 	}
 	return dec.FinishValue()
 }
 
-func (vv *Value) readFillValue(dec Decoder) error {
+func (vv *Value) readNonNilValue(dec Decoder) error {
 	if vv.Type().IsBytes() {
-		fixedLength := -1
+		fixedLen := -1
 		if vv.Kind() == Array {
-			fixedLength = vv.Type().Len()
+			fixedLen = vv.Type().Len()
 		}
 		var val []byte
-		if err := dec.DecodeBytes(fixedLength, &val); err != nil {
+		if err := dec.DecodeBytes(fixedLen, &val); err != nil {
 			return err
 		}
 		vv.AssignBytes(val)
@@ -82,36 +100,42 @@
 			return err
 		}
 		vv.AssignBool(val)
+		return nil
 	case Byte, Uint16, Uint32, Uint64:
 		val, err := dec.DecodeUint(uint(bitlenV(vv.Kind())))
 		if err != nil {
 			return err
 		}
 		vv.AssignUint(val)
+		return nil
 	case Int8, Int16, Int32, Int64:
 		val, err := dec.DecodeInt(uint(bitlenV(vv.Kind())))
 		if err != nil {
 			return err
 		}
 		vv.AssignInt(val)
+		return nil
 	case Float32, Float64:
 		val, err := dec.DecodeFloat(uint(bitlenV(vv.Kind())))
 		if err != nil {
 			return err
 		}
 		vv.AssignFloat(val)
+		return nil
 	case String:
 		val, err := dec.DecodeString()
 		if err != nil {
 			return err
 		}
 		vv.AssignString(val)
+		return nil
 	case TypeObject:
 		val, err := dec.DecodeTypeObject()
 		if err != nil {
 			return err
 		}
 		vv.AssignTypeObject(val)
+		return nil
 	case Enum:
 		val, err := dec.DecodeString()
 		if err != nil {
@@ -122,34 +146,21 @@
 			return fmt.Errorf("vdl: %v invalid enum label %q", vv.Type(), val)
 		}
 		vv.AssignEnumIndex(index)
+		return nil
 	case Array:
-		if err := vv.readArray(dec); err != nil {
-			return err
-		}
+		return vv.readArray(dec)
 	case List:
-		if err := vv.readList(dec); err != nil {
-			return err
-		}
+		return vv.readList(dec)
 	case Set:
-		if err := vv.readSet(dec); err != nil {
-			return err
-		}
+		return vv.readSet(dec)
 	case Map:
-		if err := vv.readMap(dec); err != nil {
-			return err
-		}
+		return vv.readMap(dec)
 	case Struct:
-		if err := vv.readStruct(dec); err != nil {
-			return err
-		}
+		return vv.readStruct(dec)
 	case Union:
-		if err := vv.readUnion(dec); err != nil {
-			return err
-		}
-	default:
-		panic(fmt.Sprintf("unhandled type: %v", vv.Type()))
+		return vv.readUnion(dec)
 	}
-	return nil
+	panic(fmt.Errorf("vdl: unhandled type %v in VDLRead", vv.Type()))
 }
 
 func (vv *Value) readArray(dec Decoder) error {
diff --git a/verror/init.go b/verror/init.go
index 8f5653a..901c489 100644
--- a/verror/init.go
+++ b/verror/init.go
@@ -98,15 +98,15 @@
 }
 
 // VDLRead implements the logic to populate error from dec.
-func VDLRead(dec vdl.Decoder, error *error) error {
+func VDLRead(dec vdl.Decoder, x *error) error {
 	if err := dec.StartValue(); err != nil {
 		return err
 	}
-	if dec.IsOptional() && dec.IsNil() {
-		if !vdl.Compatible(dec.Type(), vdl.ErrorType) {
-			return fmt.Errorf("incompatible types, got %v, want error", dec.Type())
+	if dec.IsNil() {
+		if (dec.StackDepth() == 1 || dec.IsAny()) && !vdl.Compatible(vdl.ErrorType, dec.Type()) {
+			return fmt.Errorf("incompatible error, from %v", dec.Type())
 		}
-		*error = nil
+		*x = nil
 		return dec.FinishValue()
 	}
 	dec.IgnoreNextStartValue()
@@ -118,6 +118,6 @@
 	if err := WireToNative(wire, nativePtr); err != nil {
 		return err
 	}
-	*error = nativePtr
+	*x = nativePtr
 	return nil
 }
diff --git a/vom/.api b/vom/.api
index e2bb47c..f67ad3d 100644
--- a/vom/.api
+++ b/vom/.api
@@ -96,6 +96,7 @@
 pkg vom, method (*RawBytes) MakeVDLTarget() vdl.Target
 pkg vom, method (*RawBytes) String() string
 pkg vom, method (*RawBytes) ToValue(interface{}) error
+pkg vom, method (*RawBytes) VDLRead(vdl.Decoder) error
 pkg vom, method (*TypeDecoder) Start()
 pkg vom, method (*TypeDecoder) Stop()
 pkg vom, method (*XDecoder) Decode(interface{}) error
diff --git a/vom/decoder.go b/vom/decoder.go
index 748bfbd..00f3151 100644
--- a/vom/decoder.go
+++ b/vom/decoder.go
@@ -132,7 +132,7 @@
 	}
 	if hax, ok := target.(hasRvHack); ok {
 		rv := hax.HackGetRv()
-		valLen, err := d.decodeValueByteLen(valType)
+		valLen, err := d.peekValueByteLen(valType)
 		if err != nil {
 			return err
 		}
@@ -161,7 +161,7 @@
 	if err != nil {
 		return err
 	}
-	valLen, err := d.decodeValueByteLen(valType)
+	valLen, err := d.peekValueByteLen(valType)
 	if err != nil {
 		return err
 	}
@@ -190,8 +190,8 @@
 	return tid, d.endMessage()
 }
 
-// decodeValueByteLen returns the byte length of the next value.
-func (d *Decoder) decodeValueByteLen(tt *vdl.Type) (int, error) {
+// peekValueByteLen returns the byte length of the next value.
+func (d *Decoder) peekValueByteLen(tt *vdl.Type) (int, error) {
 	if hasChunkLen(tt) {
 		// Use the explicit message length.
 		return d.buf.lim, nil
diff --git a/vom/raw_bytes.go b/vom/raw_bytes.go
index b835714..9145c84 100644
--- a/vom/raw_bytes.go
+++ b/vom/raw_bytes.go
@@ -20,6 +20,11 @@
 	Data       []byte
 }
 
+func (RawBytes) __VDLReflect(struct {
+	Type interface{} // ensure vdl.TypeOf(RawBytes{}) returns vdl.AnyType
+}) {
+}
+
 func RawBytesOf(value interface{}) *RawBytes {
 	rb, err := RawBytesFromValue(value)
 	if err != nil {
@@ -108,11 +113,6 @@
 	return len(rb.Data) == 1 && rb.Data[0] == WireCtrlNil
 }
 
-func (RawBytes) __VDLReflect(struct {
-	Type interface{} // ensure vdl.TypeOf(RawBytes{}) returns vdl.AnyType
-}) {
-}
-
 func (rb *RawBytes) Decoder() vdl.Decoder {
 	dec := NewDecoder(bytes.NewReader(rb.Data))
 	dec.buf.version = rb.Version
@@ -134,6 +134,16 @@
 	return xd
 }
 
+func (rb *RawBytes) VDLRead(dec vdl.Decoder) error {
+	// Fastpath: the bytes are already available in the xDecoder.  Note that this
+	// also handles the case where dec is RawBytes.Decoder().
+	if d, ok := dec.(*xDecoder); ok {
+		return d.readRawBytes(rb)
+	}
+	// Slowpath: the bytes are not available, we must encode new bytes.
+	return fmt.Errorf("vom: RawBytes.VDLRead slowpath not implemented")
+}
+
 // vdl.Target that writes to a vom.RawBytes.  This structure is intended to be
 // one-time-use and created via RawBytes.MakeVDLTarget.
 type rbTarget struct {
diff --git a/vom/xdecoder.go b/vom/xdecoder.go
index 3980d48..b302e45 100644
--- a/vom/xdecoder.go
+++ b/vom/xdecoder.go
@@ -27,7 +27,9 @@
 )
 
 var (
-	errEmptyDecoderStack = errors.New("vom: empty decoder stack")
+	errEmptyDecoderStack          = errors.New("vom: empty decoder stack")
+	errReadRawBytesAlreadyStarted = errors.New("vom: read into vom.RawBytes after StartValue called")
+	errReadRawBytesFromNonAny     = errors.New("vom: read into vom.RawBytes only supported on any values")
 )
 
 type XDecoder struct {
@@ -77,6 +79,56 @@
 	return len(d.stack)
 }
 
+// readRawBytes fills in rb with the next value.  It can be called for both
+// top-level and internal values.
+func (d *xDecoder) readRawBytes(rb *RawBytes) error {
+	if d.ignoreNextStartValue {
+		// If the user has already called StartValue on the decoder, it's harder to
+		// capture all the raw bytes, since the optional flag and length hints have
+		// already been decoded.  So we simply disallow this from happening.
+		return errReadRawBytesAlreadyStarted
+	}
+	tt, err := d.dfsNextType()
+	if err != nil {
+		return err
+	}
+	// Handle top-level values.  All types of values are supported, since we can
+	// simply copy the message bytes.
+	if len(d.stack) == 0 {
+		anyLen, err := d.old.peekValueByteLen(tt)
+		if err != nil {
+			return err
+		}
+		if err := d.old.decodeRaw(tt, anyLen, rb); err != nil {
+			return err
+		}
+		return d.old.endMessage()
+	}
+	// Handle internal values.  Only any values are supported at the moment, since
+	// they come with a header that tells us the exact length to read.
+	//
+	// TODO(toddw): Handle other types, either by reading and skipping bytes based
+	// on the type, or by falling back to a decode / re-encode slowpath.
+	if tt.Kind() != vdl.Any {
+		return errReadRawBytesFromNonAny
+	}
+	ttElem, anyLen, err := d.old.readAnyHeader()
+	if err != nil {
+		return err
+	}
+	if ttElem == nil {
+		// This is a nil any value, which has already been read by readAnyHeader.
+		// We simply fill in RawBytes with the single WireCtrlNil byte.
+		rb.Version = d.old.buf.version
+		rb.Type = vdl.AnyType
+		rb.RefTypes = nil
+		rb.AnyLengths = nil
+		rb.Data = []byte{WireCtrlNil}
+		return nil
+	}
+	return d.old.decodeRaw(ttElem, anyLen, rb)
+}
+
 func (d *xDecoder) StartValue() error {
 	//defer func() { fmt.Printf("HACK: StartValue  %+v\n", d.stack) }()
 	if d.ignoreNextStartValue {
@@ -93,11 +145,11 @@
 func (d *xDecoder) setupValue(tt *vdl.Type) error {
 	// Handle any, which may be nil.  We "dereference" non-nil any to the inner
 	// type.  If that happens to be an optional, it's handled below.
-	isAny, anyLen := false, 0
+	isAny := false
 	if tt.Kind() == vdl.Any {
 		isAny = true
 		var err error
-		switch tt, anyLen, err = d.old.readAnyHeader(); {
+		switch tt, _, err = d.old.readAnyHeader(); {
 		case err != nil:
 			return err
 		case tt == nil:
@@ -122,7 +174,6 @@
 			tt = tt.Elem() // non-nil optional
 		}
 	}
-	_ = anyLen // TODO(toddw): Do something about RawBytes.
 	// Initialize LenHint for composite types.
 	entry := decoderStackEntry{
 		Type:       tt,