build calls cb to decode an object instance from a proto. The output of cb is cached into s so each instance is only built once. i is the proto instances slice (d.content.Instances.Foo) s is a pointer to the decoder instances slice (&d.inst.Foo) p is the object's proto ID outPtr is a pointer to the
(i, s, p, outPtr, cb interface{})
| 1951 | // outPtr is a pointer to the output value |
| 1952 | // cb is a func with the signature: func(InputType, *OutputType) |
| 1953 | func (*decoder) build(i, s, p, outPtr, cb interface{}) { |
| 1954 | sV := reflect.ValueOf(s) |
| 1955 | pV := reflect.ValueOf(p) |
| 1956 | |
| 1957 | outPtrV := reflect.ValueOf(outPtr) |
| 1958 | outV := outPtrV.Elem() |
| 1959 | |
| 1960 | id := int(pV.Interface().(uint64)) |
| 1961 | if id == 0 { |
| 1962 | return // 0 means nil |
| 1963 | } |
| 1964 | |
| 1965 | idx := id - 1 |
| 1966 | |
| 1967 | if existing := sV.Elem().Index(idx); !existing.IsNil() { |
| 1968 | // Already built this object. |
| 1969 | outV.Set(existing) |
| 1970 | return |
| 1971 | } |
| 1972 | |
| 1973 | in := reflect.ValueOf(i).Index(idx) |
| 1974 | out := reflect.New(outPtrV.Type().Elem().Elem()) |
| 1975 | outV.Set(out) |
| 1976 | |
| 1977 | // Store the id into the decoder instances slice before building to handle |
| 1978 | // cyclic dependencies. |
| 1979 | sV.Elem().Index(idx).Set(out) |
| 1980 | |
| 1981 | // Build |
| 1982 | reflect.ValueOf(cb).Call([]reflect.Value{in, out}) |
| 1983 | } |
no test coverage detected