| // Copyright 2020 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| package fuzz |
| |
| import ( |
| "encoding/base64" |
| "encoding/json" |
| "fmt" |
| "reflect" |
| ) |
| |
| // TODO(fxbug.dev/47320): Implement shorter, mutable tokens by using a path to a tmpdir |
| |
| // A Handle provides a way to serialize information about an Instance. |
| // A Handle must be immutable for the lifetime of the Instance. |
| type Handle []byte |
| |
| // Serialize returns a printable representation of the Handle |
| func (h Handle) Serialize() string { |
| return base64.StdEncoding.EncodeToString(h) |
| } |
| |
| // PopulateObject will load configuration data from the Handle into the provided object |
| // Field names must be globally unique |
| func (h Handle) PopulateObject(obj interface{}) error { |
| if err := json.Unmarshal(h, obj); err != nil { |
| return fmt.Errorf("error unmarshaling: %s", err) |
| } |
| |
| return nil |
| } |
| |
| // LoadHandleFromString creates a Handle from its string representation as returned by Serialize() |
| func LoadHandleFromString(s string) (Handle, error) { |
| data, err := base64.StdEncoding.DecodeString(s) |
| if err != nil { |
| return nil, fmt.Errorf("Error decoding handle: %s", err) |
| } |
| return data, nil |
| } |
| |
| // NewHandleFromObjects creates a Handle encoding data from the provided objects |
| // All exported fields of the objects will be captured, and merged |
| func NewHandleFromObjects(objs ...interface{}) (Handle, error) { |
| mergedData := make(map[string]interface{}) |
| |
| // Merge the data from the sub-objects |
| for _, obj := range objs { |
| if obj == nil { |
| continue |
| } |
| |
| t := reflect.TypeOf(obj).Elem() |
| v := reflect.ValueOf(obj).Elem() |
| for i := 0; i < t.NumField(); i++ { |
| field := t.Field(i) |
| // Only process exported fields (https://golang.org/pkg/reflect/#StructField) |
| if field.PkgPath == "" { |
| mergedData[field.Name] = v.Field(i).Interface() |
| } |
| } |
| } |
| |
| data, err := json.Marshal(mergedData) |
| if err != nil { |
| return nil, fmt.Errorf("error constructing instance handle: %s", err) |
| } |
| |
| return data, nil |
| } |