// deconstructDatum converts a datum object to an arbitrary type func deconstructDatum(datum *p.Datum, opts map[string]interface{}) (interface{}, error) { switch datum.GetType() { case p.Datum_R_NULL: return nil, nil case p.Datum_R_JSON: var v interface{} err := json.Unmarshal([]byte(datum.GetRStr()), &v) if err != nil { return nil, err } v, err = recursivelyConvertPseudotype(v, opts) if err != nil { return nil, err } return v, nil case p.Datum_R_BOOL: return datum.GetRBool(), nil case p.Datum_R_NUM: return datum.GetRNum(), nil case p.Datum_R_STR: return datum.GetRStr(), nil case p.Datum_R_ARRAY: items := []interface{}{} for _, d := range datum.GetRArray() { item, err := deconstructDatum(d, opts) if err != nil { return nil, err } items = append(items, item) } return items, nil case p.Datum_R_OBJECT: obj := map[string]interface{}{} for _, assoc := range datum.GetRObject() { key := assoc.GetKey() val, err := deconstructDatum(assoc.GetVal(), opts) if err != nil { return nil, err } obj[string(key)] = val } pobj, err := convertPseudotype(obj, opts) if err != nil { return nil, err } return pobj, nil } return nil, fmt.Errorf("Unknown Datum type %s encountered in response.", datum.GetType().String()) }
// deconstructDatum converts a datum object to an arbitrary type func deconstructDatum(datum *p.Datum, opts map[string]interface{}) (interface{}, error) { switch datum.GetType() { case p.Datum_R_NULL: return nil, nil case p.Datum_R_BOOL: return datum.GetRBool(), nil case p.Datum_R_NUM: return datum.GetRNum(), nil case p.Datum_R_STR: return datum.GetRStr(), nil case p.Datum_R_ARRAY: items := []interface{}{} for _, d := range datum.GetRArray() { item, err := deconstructDatum(d, opts) if err != nil { return nil, err } items = append(items, item) } return items, nil case p.Datum_R_OBJECT: obj := map[interface{}]interface{}{} for _, assoc := range datum.GetRObject() { key := assoc.GetKey() val, err := deconstructDatum(assoc.GetVal(), opts) if err != nil { return nil, err } obj[key] = val } // Handle ReQL pseudo-types if reqlType, ok := obj["$reql_type$"]; ok { if reqlType == "TIME" { // load timeformat, set to native if the option was not set timeFormat := "native" if opt, ok := opts["time_format"]; ok { if sopt, ok := opt.(string); ok { timeFormat = sopt } else { return nil, fmt.Errorf("Invalid time_format run option \"%s\".", opt) } } if timeFormat == "native" { return reqlTimeToNativeTime(obj["epoch_time"].(float64), obj["timezone"].(string)) } else if timeFormat == "raw" { return obj, nil } else { return nil, fmt.Errorf("Unknown time_format run option \"%s\".", reqlType) } } else { return obj, nil } } return obj, nil } return nil, fmt.Errorf("Unknown Datum type %s encountered in response.", datum.GetType().String()) }