github.com/brownsys/tracing-framework-go@v0.0.0-20161210174012-0542a62412fe/other/trace/baggage/baggage.go (about) 1 package baggage 2 3 import ( 4 "fmt" 5 "reflect" 6 "sync" 7 8 "github.com/golang/protobuf/proto" 9 10 lproto "github.com/brownsys/tracing-framework-go/trace/baggage/internal/proto" 11 ) 12 13 // ContextKey should be used as the key for baggage 14 // propagated using a context.Context object (from 15 // the golang.org/x/net/context (pre-go1.7) or context 16 // (go1.7) packages). 17 var ContextKey struct{ private struct{} } 18 19 // ByteNamespaces is a set of named namespaces 20 // in which all values are represented by byte 21 // slices. Since byte slices are not legal map 22 // keys in Go, strings with the same contents 23 // are used instead. These strings are not 24 // necessarily human-readable, and should be 25 // treated simply as byte slices which are stored 26 // temporarily as strings. 27 type ByteNamespaces map[string]ByteBaggage 28 29 // ByteBaggage is a set of named bags 30 // in which all values are represented by byte 31 // slices. Since byte slices are not legal map 32 // keys in Go, strings with the same contents 33 // are used instead. These strings are not 34 // necessarily human-readable, and should be 35 // treated simply as byte slices which are stored 36 // temporarily as strings. 37 type ByteBaggage map[string][][]byte 38 39 type Marshaler interface { 40 MarshalBaggage() ([]byte, error) 41 } 42 43 type Unmarshaler interface { 44 UnmarshalBaggage(b []byte) error 45 } 46 47 func Marshal(v interface{}) ([]byte, error) { 48 if bv, ok := v.(ByteNamespaces); ok { 49 var message lproto.BaggageMessage 50 message.Namespace = make([]*lproto.BaggageMessage_NamespaceData, len(bv)) 51 52 i := -1 53 for k, ns := range bv { 54 i++ 55 var pns lproto.BaggageMessage_NamespaceData 56 pns.Key = []byte(k) 57 pns.Bag = make([]*lproto.BaggageMessage_BagData, len(ns)) 58 j := -1 59 for k, bag := range ns { 60 j++ 61 var pbag lproto.BaggageMessage_BagData 62 pbag.Key = []byte(k) 63 pbag.Value = bag 64 pns.Bag[j] = &pbag 65 } 66 message.Namespace[i] = &pns 67 } 68 69 bytes, err := proto.Marshal(&message) 70 if err != nil { 71 return nil, fmt.Errorf("baggage: Marshal: %v", err) 72 } 73 return bytes, nil 74 } 75 76 rv := reflect.ValueOf(v) 77 typ := rv.Type() 78 79 marshalSettingsCache.RLock() 80 settings, ok := marshalSettingsCache.m[typ] 81 marshalSettingsCache.RUnlock() 82 if !ok { 83 var err error 84 settings, err = makeMarshalSettings(typ) 85 if err != nil { 86 return nil, err 87 } 88 89 marshalSettingsCache.Lock() 90 marshalSettingsCache.m[typ] = settings 91 marshalSettingsCache.Unlock() 92 } 93 94 panic("unimplemented") 95 } 96 97 func Unmarshal(data []byte, v interface{}) error { 98 bv, ok1 := v.(ByteNamespaces) 99 bvp, ok2 := v.(*ByteNamespaces) 100 if ok1 || ok2 { 101 if ok2 { 102 bv = *bvp 103 } 104 105 var message lproto.BaggageMessage 106 107 if err := proto.Unmarshal(data, &message); err != nil { 108 return fmt.Errorf("baggage: Unmarshal: %v", err) 109 } 110 111 for _, ns := range message.GetNamespace() { 112 if ns == nil { 113 panic("internal error") 114 } 115 bags := make(ByteBaggage) 116 for _, bag := range ns.GetBag() { 117 if bag == nil { 118 panic("internal error") 119 } 120 bags[string(bag.GetKey())] = bag.GetValue() 121 } 122 bv[string(ns.GetKey())] = bags 123 } 124 125 return nil 126 } 127 128 rv := reflect.ValueOf(v) 129 typ := rv.Type() 130 131 if typ.Kind() != reflect.Ptr { 132 return fmt.Errorf("baggage: Unmarshal non-pointer %v", typ) 133 } 134 135 rv = rv.Elem() 136 typ = typ.Elem() 137 138 unmarshalSettingsCache.RLock() 139 settings, ok := unmarshalSettingsCache.m[typ] 140 unmarshalSettingsCache.RUnlock() 141 if !ok { 142 var err error 143 settings, err = makeUnmarshalSettings(typ) 144 if err != nil { 145 return err 146 } 147 148 unmarshalSettingsCache.Lock() 149 unmarshalSettingsCache.m[typ] = settings 150 unmarshalSettingsCache.Unlock() 151 } 152 153 var message lproto.BaggageMessage 154 155 if err := proto.Unmarshal(data, &message); err != nil { 156 return fmt.Errorf("baggage: Unmarshal: %v", err) 157 } 158 159 for _, ns := range message.GetNamespace() { 160 if ns == nil { 161 panic("internal error") 162 } 163 164 name := reflect.New(settings.namespaceNameTyp) 165 if settings.namespaceNameTyp == stringTyp { 166 name.Elem().SetString(string(ns.Key)) 167 } else { 168 err := name.Interface().(Unmarshaler).UnmarshalBaggage(ns.Key) 169 if err != nil { 170 return fmt.Errorf("baggage: Unmarshal: namespace key: %v", err) 171 } 172 } 173 name = name.Elem() 174 175 namespace := reflect.MakeMap(settings.namespaceTyp) 176 for _, bag := range ns.GetBag() { 177 if bag == nil { 178 panic("internal error") 179 } 180 181 bk := reflect.New(settings.bagNameTyp) 182 if settings.bagNameTyp == stringTyp { 183 bk.Elem().SetString(string(bag.Key)) 184 } else { 185 err := bk.Interface().(Unmarshaler).UnmarshalBaggage(bag.Key) 186 if err != nil { 187 return fmt.Errorf("baggage: Unmarshal: baggage key: %v", err) 188 } 189 } 190 bk = bk.Elem() 191 192 bv := reflect.MakeSlice(reflect.SliceOf(settings.bagElemTyp), len(bag.Value), len(bag.Value)) 193 for i, v := range bag.Value { 194 elem := bv.Index(i) 195 if settings.bagElemTyp == byteSliceTyp { 196 elem.Set(reflect.ValueOf(v)) 197 } else { 198 err := elem.Addr().Interface().(Unmarshaler).UnmarshalBaggage(v) 199 if err != nil { 200 return fmt.Errorf("baggage: Unmarshal: baggage element: %v", err) 201 } 202 } 203 } 204 205 namespace.SetMapIndex(bk, bv) 206 } 207 208 rv.SetMapIndex(name, namespace) 209 } 210 211 return nil 212 } 213 214 var marshalSettingsCache = struct { 215 m map[reflect.Type]marshalSettings 216 sync.RWMutex 217 }{m: make(map[reflect.Type]marshalSettings)} 218 219 var unmarshalSettingsCache = struct { 220 m map[reflect.Type]unmarshalSettings 221 sync.RWMutex 222 }{m: make(map[reflect.Type]unmarshalSettings)} 223 224 type marshalSettings struct { 225 bagElemTyp reflect.Type 226 bagNameTyp reflect.Type 227 namespaceNameTyp reflect.Type 228 namespaceTyp reflect.Type 229 } 230 231 type unmarshalSettings struct { 232 bagElemTyp reflect.Type 233 bagNameTyp reflect.Type 234 namespaceNameTyp reflect.Type 235 namespaceTyp reflect.Type 236 } 237 238 // type converter struct { 239 // bagElemToByteSlice func(v reflect.Value) []byte 240 // byteSliceToBagElem func(b []byte) reflect.Value 241 // bagNameToByteSlice func(v reflect.Value) []byte 242 // byteSliceToBagName func(b []byte) reflect.Value 243 // namespaceNameToByteSlice func(v reflect.Value) []byte 244 // byteSliceToNamespaceName func(b []byte) reflect.Value 245 // } 246 247 var ( 248 stringTyp = reflect.TypeOf("") 249 byteSliceTyp = reflect.TypeOf([]byte(nil)) 250 251 marshalerTyp = reflect.TypeOf([]Marshaler(nil)).Elem() 252 unmarshalerTyp = reflect.TypeOf([]Unmarshaler(nil)).Elem() 253 ) 254 255 func makeMarshalSettings(t reflect.Type) (marshalSettings, error) { 256 switch { 257 case t.Kind() != reflect.Map: 258 fallthrough 259 case t.Elem().Kind() != reflect.Map: 260 fallthrough 261 case t.Elem().Elem().Kind() != reflect.Slice: 262 return marshalSettings{}, fmt.Errorf("baggage: Marshal: type must be of the form map[T]map[U][]V") 263 } 264 265 var settings marshalSettings 266 267 // namespace name type 268 tt := t.Key() 269 settings.namespaceTyp = t.Elem() 270 settings.namespaceNameTyp = tt 271 switch { 272 case tt == stringTyp: 273 case tt.Implements(marshalerTyp): 274 default: 275 return marshalSettings{}, fmt.Errorf("baggage: Marshal: type %v is not string and does not implement Marshaler", tt) 276 } 277 278 // bage name type 279 tt = t.Elem().Key() 280 settings.bagNameTyp = tt 281 switch { 282 case tt == stringTyp: 283 case tt.Implements(marshalerTyp): 284 default: 285 return marshalSettings{}, fmt.Errorf("baggage: Marshal: type %v is not string and does not implement Marshaler", tt) 286 } 287 288 // bag element type 289 tt = t.Elem().Elem().Elem() 290 settings.bagElemTyp = tt 291 switch { 292 case tt == byteSliceTyp: 293 case tt.Implements(marshalerTyp): 294 default: 295 return marshalSettings{}, fmt.Errorf("baggage: Marshal: type %v is not []byte and does not implement Marshaler", tt) 296 } 297 298 return settings, nil 299 } 300 301 func makeUnmarshalSettings(t reflect.Type) (unmarshalSettings, error) { 302 switch { 303 case t.Kind() != reflect.Map: 304 fallthrough 305 case t.Elem().Kind() != reflect.Map: 306 fallthrough 307 case t.Elem().Elem().Kind() != reflect.Slice: 308 return unmarshalSettings{}, fmt.Errorf("baggage: Unmarshal: type must be of the form map[T]map[U][]V") 309 } 310 311 var settings unmarshalSettings 312 313 // namespace name type 314 tt := t.Key() 315 settings.namespaceTyp = t.Elem() 316 settings.namespaceNameTyp = tt 317 switch { 318 case tt == stringTyp: 319 case reflect.PtrTo(tt).Implements(unmarshalerTyp): 320 default: 321 return unmarshalSettings{}, fmt.Errorf("baggage: Unmarshal: type %v is not string and does not implement Unmarshaler", tt) 322 } 323 324 // bage name type 325 tt = t.Elem().Key() 326 settings.bagNameTyp = tt 327 switch { 328 case tt == stringTyp: 329 case reflect.PtrTo(tt).Implements(unmarshalerTyp): 330 default: 331 return unmarshalSettings{}, fmt.Errorf("baggage: Unmarshal: type %v is not string and does not implement Unmarshaler", tt) 332 } 333 334 // bag element type 335 tt = t.Elem().Elem().Elem() 336 settings.bagElemTyp = tt 337 switch { 338 case tt == byteSliceTyp: 339 case reflect.PtrTo(tt).Implements(unmarshalerTyp): 340 default: 341 return unmarshalSettings{}, fmt.Errorf("baggage: Unmarshal: type %v is not []byte and does not implement Unmarshaler", tt) 342 } 343 344 return settings, nil 345 }