// Note: This function has no receiver, which makes it easier to test. // The "json" input parameter should be a parsed JSON object structure, the output of a decoder. func getScanVectorsFromJSON(json interface{}) (map[string]timestamp.Vector, errors.Error) { bucketMap, ok := json.(map[string]interface{}) if !ok { return nil, errors.NewServiceErrorTypeMismatch(SCAN_VECTORS, "map of strings to vectors") } out := make(map[string]timestamp.Vector) for k, v := range bucketMap { // Is it a sparse vector? mapVector, ok := v.(map[string]interface{}) if ok { entries, err := makeSparseVector(mapVector) if err != nil { return nil, err } out[k] = entries continue } // Is it a full vector? arrayVector, ok := v.([]interface{}) if ok { entries, err := makeFullVector(arrayVector) if err != nil { return nil, err } out[k] = entries continue } return nil, errors.NewServiceErrorTypeMismatch(k, "full or sparse vector") } return out, nil }
func makeVectorEntry(index int, args interface{}) (*scanVectorEntry, errors.Error) { data, is_map := args.(map[string]interface{}) if !is_map { return nil, errors.NewServiceErrorTypeMismatch(SCAN_VECTOR, "array or map of { number, string }") } value, has_value := data["value"] if !has_value { return nil, errors.NewServiceErrorTypeMismatch(SCAN_VECTOR, "array or map of { number, string }") } value_val, is_number := value.(float64) if !is_number { return nil, errors.NewServiceErrorTypeMismatch(SCAN_VECTOR, "array or map of { number, string }") } guard, has_guard := data["guard"] if !has_guard { return nil, errors.NewServiceErrorTypeMismatch(SCAN_VECTOR, "array or map of { number, string }") } guard_val, guard_ok := guard.(string) if !guard_ok { return nil, errors.NewServiceErrorTypeMismatch(SCAN_VECTOR, "array or map of { number, string }") } return &scanVectorEntry{ position: uint32(index), value: uint64(value_val), guard: guard_val, }, nil }
func makeFullVector(args []interface{}) (*scanVectorEntries, errors.Error) { if len(args) != SCAN_VECTOR_SIZE { return nil, errors.NewServiceErrorTypeMismatch(SCAN_VECTOR, fmt.Sprintf("array of %d entries", SCAN_VECTOR_SIZE)) } entries := make([]timestamp.Entry, len(args)) for i, arg := range args { array, ok := arg.([]interface{}) if !ok { return nil, errors.NewServiceErrorTypeMismatch("entry of a full scan vector", "array of length 2") } sequenceNum, uuid, err := extractValues(array) if err != nil { return nil, err } entries[i] = &scanVectorEntry{ position: uint32(i), value: sequenceNum, guard: uuid, } } return &scanVectorEntries{ entries: entries, }, nil }
func makeSparseVector(args map[string]interface{}) (*scanVectorEntries, errors.Error) { entries := make([]timestamp.Entry, len(args)) i := 0 for key, arg := range args { index, err := strconv.Atoi(key) if err != nil { return nil, errors.NewServiceErrorBadValue(err, SCAN_VECTOR) } array, ok := arg.([]interface{}) if !ok { return nil, errors.NewServiceErrorTypeMismatch("scan vector entry", "two-element array") } sequenceNum, uuid, error := extractValues(array) if err != nil { return nil, error } entries[i] = &scanVectorEntry{ position: uint32(index), value: sequenceNum, guard: uuid, } i = i + 1 } return &scanVectorEntries{ entries: entries, }, nil }
func (this *jsonArgs) getScanVector() (timestamp.Vector, errors.Error) { var type_ok bool scan_vector_data_field, in_request := this.getField(SCAN_VECTOR) if !in_request { return nil, nil } full_vector_data, type_ok := scan_vector_data_field.([]interface{}) if type_ok { if len(full_vector_data) != SCAN_VECTOR_SIZE { return nil, errors.NewServiceErrorTypeMismatch(SCAN_VECTOR, fmt.Sprintf("array of %d entries", SCAN_VECTOR_SIZE)) } entries := make([]timestamp.Entry, len(full_vector_data)) for index, arg := range full_vector_data { nextEntry, err := makeVectorEntry(index, arg) if err != nil { return nil, err } entries[index] = nextEntry } } sparse_vector_data, type_ok := scan_vector_data_field.(map[string]interface{}) if !type_ok { return nil, errors.NewServiceErrorTypeMismatch(SCAN_VECTOR, "array or map of { number, string }") } entries := make([]timestamp.Entry, len(sparse_vector_data)) i := 0 for key, arg := range sparse_vector_data { index, e := strconv.Atoi(key) if e != nil { return nil, errors.NewServiceErrorBadValue(e, SCAN_VECTOR) } nextEntry, err := makeVectorEntry(index, arg) if err != nil { return nil, err } entries[i] = nextEntry i = i + 1 } return &scanVectorEntries{ entries: entries, }, nil }
// helper function to get a string type argument func (this *jsonArgs) getString(f string, dflt string) (string, errors.Error) { value_field, in_request := this.getField(f) if !in_request { return dflt, nil } value, type_ok := value_field.(string) if !type_ok { return value, errors.NewServiceErrorTypeMismatch(f, "string") } return value, nil }
func (this *jsonArgs) getTristate(f string) (value.Tristate, errors.Error) { value_tristate := value.NONE value_field, in_request := this.getField(f) if !in_request { return value_tristate, nil } b, type_ok := value_field.(bool) if !type_ok { return value_tristate, errors.NewServiceErrorTypeMismatch(f, "boolean") } value_tristate = value.ToTristate(b) return value_tristate, nil }
func (this *jsonArgs) getCredentials() ([]map[string]string, errors.Error) { var creds_data []map[string]string creds_field, in_request := this.getField(CREDS) if !in_request { return creds_data, nil } creds_data, type_ok := creds_field.([]map[string]string) if !type_ok { return creds_data, errors.NewServiceErrorTypeMismatch(CREDS, "array of { user, pass }") } return creds_data, nil }
// Note: This function has no receiver, which makes it easier to test. // The "json" input parameter should be a parsed JSON object structure, the output of a decoder. func getScanVectorFromJSON(json interface{}) (timestamp.Vector, errors.Error) { // Is it a sparse vector? mapVector, ok := json.(map[string]interface{}) if ok { return makeSparseVector(mapVector) } // Is it a full vector? arrayVector, ok := json.([]interface{}) if ok { return makeFullVector(arrayVector) } return nil, errors.NewServiceErrorTypeMismatch(SCAN_VECTOR, "full or sparse vector") }
// makeFullVector is used when the request includes all entries func makeFullVector(args []*restArg) (*scanVectorEntries, errors.Error) { if len(args) != SCAN_VECTOR_SIZE { return nil, errors.NewServiceErrorTypeMismatch(SCAN_VECTOR, fmt.Sprintf("array of %d entries", SCAN_VECTOR_SIZE)) } entries := make([]timestamp.Entry, len(args)) for i, arg := range args { entries[i] = &scanVectorEntry{ position: uint32(i), value: arg.Value, guard: arg.Guard, } } return &scanVectorEntries{ entries: entries, }, nil }
func (this *jsonArgs) getPositionalArgs() (value.Values, errors.Error) { var positionalArgs value.Values args_field, in_request := this.getField(ARGS) if !in_request { return positionalArgs, nil } args, type_ok := args_field.([]interface{}) if !type_ok { return positionalArgs, errors.NewServiceErrorTypeMismatch(ARGS, "array") } positionalArgs = make([]value.Value, len(args)) // Put each element of args into positionalArgs for i, arg := range args { positionalArgs[i] = value.NewValue(arg) } return positionalArgs, nil }