// 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 }
// ExtractAddWorkUnitItem converts an arbitrary object (which really // should be a cborpc.PythonTuple or a list) into an AddWorkUnitItem. func ExtractAddWorkUnitItem(obj interface{}) (result AddWorkUnitItem, err error) { var ( decoder *mapstructure.Decoder haveMetadata bool havePriority bool kvpList []interface{} kvpMap map[string]interface{} str string bstr []byte ok bool ) // If we got handed a string (or a byte string) turn it into // a work unit with no data if str, ok = obj.(string); ok { result.Key = str result.Data = make(map[string]interface{}) return } if bstr, ok = obj.([]byte); ok { result.Key = string(bstr) 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["metadata"] = kvpList[2] haveMetadata = true } if len(kvpList) >= 4 && kvpList[3] != nil { kvpMap["priority"] = kvpList[3] havePriority = true } // Now we can invoke mapstructure config := mapstructure.DecoderConfig{ DecodeHook: cborrpc.DecodeBytesAsString, Result: &result, } decoder, err = mapstructure.NewDecoder(&config) if err == nil { err = decoder.Decode(kvpMap) } if err == nil && haveMetadata && !havePriority { // See if the caller passed metadata["priority"] // instead of an explicit priority field. if priority, ok := result.Metadata["priority"]; ok { if result.Priority, ok = priority.(float64); !ok { err = ErrBadPriority } } } return }