예제 #1
0
// lockKeys unmarshals an arbitrary object into a list of lists of
// objects, flattening tuples into lists, or fails.
func lockKeys(obj interface{}) ([][]interface{}, bool) {
	list, ok := cborrpc.Detuplify(obj)
	if !ok {
		return nil, ok
	}
	list2 := make([][]interface{}, len(list))
	for i, item := range list {
		item2, ok := cborrpc.Detuplify(item)
		if !ok {
			return nil, ok
		}
		list2[i] = item2
	}
	return list2, ok
}
예제 #2
0
// ExtractAddWorkUnitItem converts an arbitrary object (which really
// should be a cborpc.PythonTuple or a list) into an AddWorkUnitItem.
func ExtractAddWorkUnitItem(obj interface{}, now time.Time) (result AddWorkUnitItem, err error) {
	var (
		decoder *mapstructure.Decoder
		kvpList []interface{}
		kvpMap  map[string]interface{}
		ok      bool
	)
	// If we got handed a string (or a byte string) turn it into
	// a work unit with no data
	if result.Key, ok = cborrpc.Destringify(obj); ok {
		result.Data = make(map[string]interface{})
		return
	}

	// Otherwise obj must be a tuple (or a list)
	if kvpList, ok = cborrpc.Detuplify(obj); !ok {
		err = ErrWorkUnitNotList
		return
	}
	// Turn that list into a string-keyed map
	if len(kvpList) < 2 {
		err = ErrWorkUnitTooShort
		return
	}
	kvpMap = make(map[string]interface{})
	kvpMap["key"] = kvpList[0]
	kvpMap["data"] = kvpList[1]
	if len(kvpList) >= 3 && kvpList[2] != nil {
		kvpMap["meta"] = kvpList[2]
	}

	// Now we can invoke mapstructure, on this modified struct
	var partial struct {
		Key  string
		Data map[string]interface{}
		Meta AddWorkUnitMeta
	}
	config := mapstructure.DecoderConfig{
		DecodeHook: cborrpc.DecodeBytesAsString,
		Result:     &partial,
	}
	decoder, err = mapstructure.NewDecoder(&config)
	if err == nil {
		err = decoder.Decode(kvpMap)
	}

	// If that worked, copy data over to a real result
	if err == nil {
		result.Key = partial.Key
		result.Data = partial.Data
		result.Meta = partial.Meta.ToMeta(now)
	}

	// If a priority value was given in the list, that overrides
	// what got extracted
	if err == nil && len(kvpList) >= 4 && kvpList[3] != nil {
		if result.Meta.Priority, ok = kvpList[3].(float64); !ok {
			err = ErrBadPriority
		}
	}

	return
}