in marshal.go [2492:2624]
func unmarshalUDT(info TypeInfo, data []byte, value interface{}) error {
switch v := value.(type) {
case Unmarshaler:
return v.UnmarshalCQL(info, data)
case UDTUnmarshaler:
udt := info.(UDTTypeInfo)
for id, e := range udt.Elements {
if len(data) == 0 {
return nil
}
if len(data) < 4 {
return unmarshalErrorf("can not unmarshal %s: field [%d]%s: unexpected eof", info, id, e.Name)
}
var p []byte
p, data = readBytes(data)
if err := v.UnmarshalUDT(e.Name, e.Type, p); err != nil {
return err
}
}
return nil
case *map[string]interface{}:
udt := info.(UDTTypeInfo)
rv := reflect.ValueOf(value)
if rv.Kind() != reflect.Ptr {
return unmarshalErrorf("can not unmarshal into non-pointer %T", value)
}
rv = rv.Elem()
t := rv.Type()
if t.Kind() != reflect.Map {
return unmarshalErrorf("can not unmarshal %s into %T. Accepted types: Unmarshaler, UDTUnmarshaler, *map[string]interface{}, struct.", info, value)
} else if data == nil {
rv.Set(reflect.Zero(t))
return nil
}
rv.Set(reflect.MakeMap(t))
m := *v
for id, e := range udt.Elements {
if len(data) == 0 {
return nil
}
if len(data) < 4 {
return unmarshalErrorf("can not unmarshal %s: field [%d]%s: unexpected eof", info, id, e.Name)
}
valType, err := goType(e.Type)
if err != nil {
return unmarshalErrorf("can not unmarshal %s: %v", info, err)
}
val := reflect.New(valType)
var p []byte
p, data = readBytes(data)
if err := Unmarshal(e.Type, p, val.Interface()); err != nil {
return err
}
m[e.Name] = val.Elem().Interface()
}
return nil
}
rv := reflect.ValueOf(value)
if rv.Kind() != reflect.Ptr {
return unmarshalErrorf("can not unmarshal into non-pointer %T", value)
}
k := rv.Elem()
if k.Kind() != reflect.Struct || !k.IsValid() {
return unmarshalErrorf("cannot unmarshal %s into %T. Accepted types: Unmarshaler, UDTUnmarshaler, *map[string]interface{}, *struct.", info, value)
}
if len(data) == 0 {
if k.CanSet() {
k.Set(reflect.Zero(k.Type()))
}
return nil
}
t := k.Type()
fields := make(map[string]reflect.Value, t.NumField())
for i := 0; i < t.NumField(); i++ {
sf := t.Field(i)
if tag := sf.Tag.Get("cql"); tag != "" {
fields[tag] = k.Field(i)
}
}
udt := info.(UDTTypeInfo)
for id, e := range udt.Elements {
if len(data) == 0 {
return nil
}
if len(data) < 4 {
// UDT def does not match the column value
return unmarshalErrorf("can not unmarshal %s: field [%d]%s: unexpected eof", info, id, e.Name)
}
var p []byte
p, data = readBytes(data)
f, ok := fields[e.Name]
if !ok {
f = k.FieldByName(e.Name)
if f == emptyValue {
// skip fields which exist in the UDT but not in
// the struct passed in
continue
}
}
if !f.IsValid() || !f.CanAddr() {
return unmarshalErrorf("cannot unmarshal %s into %T: field %v is not valid", info, value, e.Name)
}
fk := f.Addr().Interface()
if err := Unmarshal(e.Type, p, fk); err != nil {
return err
}
}
return nil
}