consolidate
This commit is contained in:
@@ -4,7 +4,6 @@ package dynamodb
|
||||
|
||||
import "core:encoding/json"
|
||||
import "core:fmt"
|
||||
import "core:mem"
|
||||
import "core:slice"
|
||||
import "core:strings"
|
||||
|
||||
@@ -20,7 +19,7 @@ parse_item :: proc(json_bytes: []byte) -> (Item, bool) {
|
||||
return {}, false
|
||||
}
|
||||
defer json.destroy_value(data)
|
||||
|
||||
|
||||
return parse_item_from_value(data)
|
||||
}
|
||||
|
||||
@@ -31,12 +30,12 @@ parse_item_from_value :: proc(value: json.Value) -> (Item, bool) {
|
||||
if !ok {
|
||||
return {}, false
|
||||
}
|
||||
|
||||
|
||||
item := make(Item)
|
||||
|
||||
|
||||
for key, val in obj {
|
||||
attr_name := strings.clone(key)
|
||||
|
||||
|
||||
attr_value, attr_ok := parse_attribute_value(val)
|
||||
if !attr_ok {
|
||||
// Cleanup on error
|
||||
@@ -49,10 +48,10 @@ parse_item_from_value :: proc(value: json.Value) -> (Item, bool) {
|
||||
delete(attr_name)
|
||||
return {}, false
|
||||
}
|
||||
|
||||
|
||||
item[attr_name] = attr_value
|
||||
}
|
||||
|
||||
|
||||
return item, true
|
||||
}
|
||||
|
||||
@@ -63,12 +62,12 @@ parse_attribute_value :: proc(value: json.Value) -> (Attribute_Value, bool) {
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
|
||||
// DynamoDB attribute must have exactly one key (the type indicator)
|
||||
if len(obj) != 1 {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
|
||||
// Get the single key-value pair
|
||||
for type_name, type_value in obj {
|
||||
// String
|
||||
@@ -79,7 +78,7 @@ parse_attribute_value :: proc(value: json.Value) -> (Attribute_Value, bool) {
|
||||
}
|
||||
return String(strings.clone(string(str))), true
|
||||
}
|
||||
|
||||
|
||||
// Number (stored as string)
|
||||
if type_name == "N" {
|
||||
str, str_ok := type_value.(json.String)
|
||||
@@ -88,7 +87,7 @@ parse_attribute_value :: proc(value: json.Value) -> (Attribute_Value, bool) {
|
||||
}
|
||||
return Number(strings.clone(string(str))), true
|
||||
}
|
||||
|
||||
|
||||
// Binary (base64 string)
|
||||
if type_name == "B" {
|
||||
str, str_ok := type_value.(json.String)
|
||||
@@ -97,7 +96,7 @@ parse_attribute_value :: proc(value: json.Value) -> (Attribute_Value, bool) {
|
||||
}
|
||||
return Binary(strings.clone(string(str))), true
|
||||
}
|
||||
|
||||
|
||||
// Boolean
|
||||
if type_name == "BOOL" {
|
||||
b, b_ok := type_value.(json.Boolean)
|
||||
@@ -106,7 +105,7 @@ parse_attribute_value :: proc(value: json.Value) -> (Attribute_Value, bool) {
|
||||
}
|
||||
return Bool(b), true
|
||||
}
|
||||
|
||||
|
||||
// Null
|
||||
if type_name == "NULL" {
|
||||
b, b_ok := type_value.(json.Boolean)
|
||||
@@ -115,16 +114,16 @@ parse_attribute_value :: proc(value: json.Value) -> (Attribute_Value, bool) {
|
||||
}
|
||||
return Null(b), true
|
||||
}
|
||||
|
||||
|
||||
// String Set
|
||||
if type_name == "SS" {
|
||||
arr, arr_ok := type_value.(json.Array)
|
||||
if !arr_ok {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
|
||||
strings_arr := make([]string, len(arr))
|
||||
|
||||
|
||||
for item, i in arr {
|
||||
str, str_ok := item.(json.String)
|
||||
if !str_ok {
|
||||
@@ -137,19 +136,19 @@ parse_attribute_value :: proc(value: json.Value) -> (Attribute_Value, bool) {
|
||||
}
|
||||
strings_arr[i] = strings.clone(string(str))
|
||||
}
|
||||
|
||||
|
||||
return String_Set(strings_arr), true
|
||||
}
|
||||
|
||||
|
||||
// Number Set
|
||||
if type_name == "NS" {
|
||||
arr, arr_ok := type_value.(json.Array)
|
||||
if !arr_ok {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
|
||||
numbers_arr := make([]string, len(arr))
|
||||
|
||||
|
||||
for item, i in arr {
|
||||
str, str_ok := item.(json.String)
|
||||
if !str_ok {
|
||||
@@ -162,19 +161,19 @@ parse_attribute_value :: proc(value: json.Value) -> (Attribute_Value, bool) {
|
||||
}
|
||||
numbers_arr[i] = strings.clone(string(str))
|
||||
}
|
||||
|
||||
|
||||
return Number_Set(numbers_arr), true
|
||||
}
|
||||
|
||||
|
||||
// Binary Set
|
||||
if type_name == "BS" {
|
||||
arr, arr_ok := type_value.(json.Array)
|
||||
if !arr_ok {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
|
||||
binaries_arr := make([]string, len(arr))
|
||||
|
||||
|
||||
for item, i in arr {
|
||||
str, str_ok := item.(json.String)
|
||||
if !str_ok {
|
||||
@@ -187,19 +186,19 @@ parse_attribute_value :: proc(value: json.Value) -> (Attribute_Value, bool) {
|
||||
}
|
||||
binaries_arr[i] = strings.clone(string(str))
|
||||
}
|
||||
|
||||
|
||||
return Binary_Set(binaries_arr), true
|
||||
}
|
||||
|
||||
|
||||
// List
|
||||
if type_name == "L" {
|
||||
arr, arr_ok := type_value.(json.Array)
|
||||
if !arr_ok {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
|
||||
list := make([]Attribute_Value, len(arr))
|
||||
|
||||
|
||||
for item, i in arr {
|
||||
val, val_ok := parse_attribute_value(item)
|
||||
if !val_ok {
|
||||
@@ -213,22 +212,22 @@ parse_attribute_value :: proc(value: json.Value) -> (Attribute_Value, bool) {
|
||||
}
|
||||
list[i] = val
|
||||
}
|
||||
|
||||
|
||||
return List(list), true
|
||||
}
|
||||
|
||||
|
||||
// Map
|
||||
if type_name == "M" {
|
||||
map_obj, map_ok := type_value.(json.Object)
|
||||
if !map_ok {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
|
||||
attr_map := make(map[string]Attribute_Value)
|
||||
|
||||
|
||||
for map_key, map_val in map_obj {
|
||||
key := strings.clone(map_key)
|
||||
|
||||
|
||||
val, val_ok := parse_attribute_value(map_val)
|
||||
if !val_ok {
|
||||
// Cleanup on error
|
||||
@@ -241,14 +240,14 @@ parse_attribute_value :: proc(value: json.Value) -> (Attribute_Value, bool) {
|
||||
delete(attr_map)
|
||||
return nil, false
|
||||
}
|
||||
|
||||
|
||||
attr_map[key] = val
|
||||
}
|
||||
|
||||
|
||||
return Map(attr_map), true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
@@ -261,9 +260,9 @@ parse_attribute_value :: proc(value: json.Value) -> (Attribute_Value, bool) {
|
||||
serialize_item :: proc(item: Item) -> string {
|
||||
builder := strings.builder_make()
|
||||
defer strings.builder_destroy(&builder)
|
||||
|
||||
|
||||
serialize_item_to_builder(&builder, item)
|
||||
|
||||
|
||||
return strings.clone(strings.to_string(builder))
|
||||
}
|
||||
|
||||
@@ -272,16 +271,16 @@ serialize_item_to_builder :: proc(b: ^strings.Builder, item: Item) {
|
||||
// Collect and sort keys for deterministic output
|
||||
keys := make([dynamic]string, context.temp_allocator)
|
||||
defer delete(keys)
|
||||
|
||||
|
||||
for key in item {
|
||||
append(&keys, key)
|
||||
}
|
||||
|
||||
|
||||
// Sort keys alphabetically
|
||||
slice.sort_by(keys[:], proc(a, b: string) -> bool {
|
||||
return a < b
|
||||
})
|
||||
|
||||
|
||||
strings.write_string(b, "{")
|
||||
for key, i in keys {
|
||||
if i > 0 {
|
||||
@@ -299,19 +298,19 @@ serialize_attribute_value :: proc(b: ^strings.Builder, attr: Attribute_Value) {
|
||||
switch v in attr {
|
||||
case String:
|
||||
fmt.sbprintf(b, `{"S":"%s"}`, string(v))
|
||||
|
||||
|
||||
case Number:
|
||||
fmt.sbprintf(b, `{"N":"%s"}`, string(v))
|
||||
|
||||
|
||||
case Binary:
|
||||
fmt.sbprintf(b, `{"B":"%s"}`, string(v))
|
||||
|
||||
|
||||
case Bool:
|
||||
fmt.sbprintf(b, `{"BOOL":%v}`, bool(v))
|
||||
|
||||
|
||||
case Null:
|
||||
strings.write_string(b, `{"NULL":true}`)
|
||||
|
||||
|
||||
case String_Set:
|
||||
strings.write_string(b, `{"SS":[`)
|
||||
for s, i in v {
|
||||
@@ -321,7 +320,7 @@ serialize_attribute_value :: proc(b: ^strings.Builder, attr: Attribute_Value) {
|
||||
fmt.sbprintf(b, `"%s"`, s)
|
||||
}
|
||||
strings.write_string(b, "]}")
|
||||
|
||||
|
||||
case Number_Set:
|
||||
strings.write_string(b, `{"NS":[`)
|
||||
for n, i in v {
|
||||
@@ -331,7 +330,7 @@ serialize_attribute_value :: proc(b: ^strings.Builder, attr: Attribute_Value) {
|
||||
fmt.sbprintf(b, `"%s"`, n)
|
||||
}
|
||||
strings.write_string(b, "]}")
|
||||
|
||||
|
||||
case Binary_Set:
|
||||
strings.write_string(b, `{"BS":[`)
|
||||
for bin, i in v {
|
||||
@@ -341,7 +340,7 @@ serialize_attribute_value :: proc(b: ^strings.Builder, attr: Attribute_Value) {
|
||||
fmt.sbprintf(b, `"%s"`, bin)
|
||||
}
|
||||
strings.write_string(b, "]}")
|
||||
|
||||
|
||||
case List:
|
||||
strings.write_string(b, `{"L":[`)
|
||||
for item, i in v {
|
||||
@@ -351,20 +350,20 @@ serialize_attribute_value :: proc(b: ^strings.Builder, attr: Attribute_Value) {
|
||||
serialize_attribute_value(b, item)
|
||||
}
|
||||
strings.write_string(b, "]}")
|
||||
|
||||
|
||||
case Map:
|
||||
strings.write_string(b, `{"M":{`)
|
||||
|
||||
|
||||
// Collect and sort keys for deterministic output
|
||||
keys := make([dynamic]string, context.temp_allocator)
|
||||
for key in v {
|
||||
append(&keys, key)
|
||||
}
|
||||
|
||||
|
||||
slice.sort_by(keys[:], proc(a, b: string) -> bool {
|
||||
return a < b
|
||||
})
|
||||
|
||||
|
||||
for key, i in keys {
|
||||
if i > 0 {
|
||||
strings.write_string(b, ",")
|
||||
@@ -373,7 +372,7 @@ serialize_attribute_value :: proc(b: ^strings.Builder, attr: Attribute_Value) {
|
||||
value := v[key]
|
||||
serialize_attribute_value(b, value)
|
||||
}
|
||||
|
||||
|
||||
strings.write_string(b, "}}")
|
||||
}
|
||||
}
|
||||
@@ -389,22 +388,22 @@ parse_table_name :: proc(request_body: []byte) -> (string, bool) {
|
||||
return "", false
|
||||
}
|
||||
defer json.destroy_value(data)
|
||||
|
||||
|
||||
root, ok := data.(json.Object)
|
||||
if !ok {
|
||||
return "", false
|
||||
}
|
||||
|
||||
|
||||
table_name_val, found := root["TableName"]
|
||||
if !found {
|
||||
return "", false
|
||||
}
|
||||
|
||||
|
||||
table_name_str, str_ok := table_name_val.(json.String)
|
||||
if !str_ok {
|
||||
return "", false
|
||||
}
|
||||
|
||||
|
||||
return string(table_name_str), true
|
||||
}
|
||||
|
||||
@@ -416,17 +415,17 @@ parse_item_from_request :: proc(request_body: []byte) -> (Item, bool) {
|
||||
return {}, false
|
||||
}
|
||||
defer json.destroy_value(data)
|
||||
|
||||
|
||||
root, ok := data.(json.Object)
|
||||
if !ok {
|
||||
return {}, false
|
||||
}
|
||||
|
||||
|
||||
item_val, found := root["Item"]
|
||||
if !found {
|
||||
return {}, false
|
||||
}
|
||||
|
||||
|
||||
return parse_item_from_value(item_val)
|
||||
}
|
||||
|
||||
@@ -438,17 +437,17 @@ parse_key_from_request :: proc(request_body: []byte) -> (Item, bool) {
|
||||
return {}, false
|
||||
}
|
||||
defer json.destroy_value(data)
|
||||
|
||||
|
||||
root, ok := data.(json.Object)
|
||||
if !ok {
|
||||
return {}, false
|
||||
}
|
||||
|
||||
|
||||
key_val, found := root["Key"]
|
||||
if !found {
|
||||
return {}, false
|
||||
}
|
||||
|
||||
|
||||
return parse_item_from_value(key_val)
|
||||
}
|
||||
|
||||
@@ -464,17 +463,17 @@ parse_limit :: proc(request_body: []byte) -> int {
|
||||
return 0
|
||||
}
|
||||
defer json.destroy_value(data)
|
||||
|
||||
|
||||
root, ok := data.(json.Object)
|
||||
if !ok {
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
limit_val, found := root["Limit"]
|
||||
if !found {
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
// JSON numbers can be either Integer or Float
|
||||
#partial switch v in limit_val {
|
||||
case json.Integer:
|
||||
@@ -482,7 +481,7 @@ parse_limit :: proc(request_body: []byte) -> int {
|
||||
case json.Float:
|
||||
return int(v)
|
||||
}
|
||||
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -494,24 +493,24 @@ parse_exclusive_start_key :: proc(request_body: []byte) -> Maybe([]byte) {
|
||||
return nil
|
||||
}
|
||||
defer json.destroy_value(data)
|
||||
|
||||
|
||||
root, ok := data.(json.Object)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
key_val, found := root["ExclusiveStartKey"]
|
||||
if !found {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
// Parse as Item first
|
||||
key_item, item_ok := parse_item_from_value(key_val)
|
||||
if !item_ok {
|
||||
return nil
|
||||
}
|
||||
defer item_destroy(&key_item)
|
||||
|
||||
|
||||
// Convert to binary key bytes (this will be done by the storage layer)
|
||||
// For now, just return nil - the storage layer will handle the conversion
|
||||
return nil
|
||||
@@ -521,6 +520,6 @@ parse_exclusive_start_key :: proc(request_body: []byte) -> Maybe([]byte) {
|
||||
serialize_last_evaluated_key :: proc(key: Key) -> string {
|
||||
item := key_to_item(key, {}) // Empty key_schema since we don't need validation here
|
||||
defer item_destroy(&item)
|
||||
|
||||
|
||||
return serialize_item(item)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user