mardi 5 février 2019

How to get the address of a struct attribute through reflect in GO

I'm working on a code to deserialize streams of bytes into objects and I'm stuck on getting the pointer of the attribute of a struct.

Basically how the code works is as follows: it gets the pointer to a struct, then depending on the type it serializes it, ex. if it's an integer it takes the next 4 bytes. The tricky case is if it's a struct because I have to recursively run Deserialize on all of its attributes and I don't know how to get the address of its attributes to pass them to Deserialize.

func Deserialize(objPtr interface{}, b []byte) (bytesRead int) {
    // it should be the address of the object

    val := reflect.ValueOf(objPtr).Elem()
    valPtr := reflect.ValueOf(objPtr)

    // check if either the object or *object is Serializable
    _, isSerializable := (val.Interface()).(Serializable)
    _, bo := (valPtr.Interface()).(Serializable)
    isSerializable = isSerializable || bo

    // specific type serialization
    if isSerializable{
        return objPtr.(Serializable).Deserializebyte(b)
    }

    switch val.Kind() {
    case reflect.Uint32, reflect.Int, reflect.Int32:
        res := reflect.ValueOf(binary.LittleEndian.Uint32(b[:4]))
        valPtr.Set(res)
        return 4
    case reflect.Uint64, reflect.Int64:
        res := reflect.ValueOf(binary.LittleEndian.Uint32(b[:8]))
        valPtr.Set(res)
        return 8
    case reflect.Struct:
        n_bytes := 0
        for i := 0; i < val.NumField(); i++ {

            // stuck in here
            valPtr.Elem()

            // I don't think the next line works
            last_n_bytes := Deserialize(&(valPtr.Elem().Field(i).Interface()), b)
            n_bytes += last_n_bytes
            b = b[last_n_bytes:]
        }
        //valPtr.Set(res)
        return n_bytes
    default:
        panic("this panic is for debug, every case should be handled above")
        res := val.Bytes()
        valPtr.Set(res)
        return len(val.Bytes())
    }
    return 0
}





Aucun commentaire:

Enregistrer un commentaire