build calls cb to encode an object instance to a proto. The return proto of cb is cached into i so each instance is only built once. i is a pointer to the proto instances slice (&e.instances.Foo) m is a pointer to the encoder instances map (e.maps.Foo) n is the object to encode out is a pointer to
(i, m, n, out interface{}, cb interface{})
| 2162 | // out is a pointer to the output identifier |
| 2163 | // cb is a func with the signature: func() *OutputType |
| 2164 | func (e *encoder) build(i, m, n, out interface{}, cb interface{}) { |
| 2165 | iV := reflect.ValueOf(i) |
| 2166 | mV := reflect.ValueOf(m) |
| 2167 | nV := reflect.ValueOf(n) |
| 2168 | outV := reflect.ValueOf(out) |
| 2169 | cbV := reflect.ValueOf(cb) |
| 2170 | |
| 2171 | if !nV.IsValid() || |
| 2172 | ((nV.Kind() == reflect.Ptr || nV.Kind() == reflect.Interface) && nV.IsNil()) { |
| 2173 | // n is nil. |
| 2174 | // Don't assign to out to keep it at default 0 (representing nil) |
| 2175 | return |
| 2176 | } |
| 2177 | |
| 2178 | if existing := mV.MapIndex(nV); existing.IsValid() { |
| 2179 | // Already built this object. |
| 2180 | outV.Elem().Set(existing) |
| 2181 | return |
| 2182 | } |
| 2183 | |
| 2184 | idx := iV.Elem().Len() |
| 2185 | |
| 2186 | // The ID is the index + 1. And ID of 0 represents a nil. |
| 2187 | idV := reflect.ValueOf(uint64(idx + 1)) |
| 2188 | outV.Elem().Set(idV) |
| 2189 | mV.SetMapIndex(nV, idV) |
| 2190 | |
| 2191 | // Grow the slice to hold the new entry. We do this before the call to cb |
| 2192 | // as this might call build() again, reordering the elements of the i slice. |
| 2193 | iV.Elem().Set(reflect.Append(iV.Elem(), reflect.Zero(iV.Type().Elem().Elem()))) |
| 2194 | |
| 2195 | // Build |
| 2196 | pV := cbV.Call([]reflect.Value{})[0] |
| 2197 | |
| 2198 | // Assign the output proto value to the content instances for the given id. |
| 2199 | iV.Elem().Index(idx).Set(pV) |
| 2200 | |
| 2201 | checkMessageEncodes(pV.Interface()) |
| 2202 | } |
| 2203 | |
| 2204 | // Help debug `proto: bapi.Content: illegal tag 0 (wire type 0)` errors |
| 2205 | func checkMessageEncodes(v interface{}) { |
no test coverage detected