fakecloud_dynamodb/service/helpers/
schemas.rs1use super::*;
4
5pub(crate) fn parse_key_schema(val: &Value) -> Result<Vec<KeySchemaElement>, AwsServiceError> {
6 let arr = val.as_array().ok_or_else(|| {
7 AwsServiceError::aws_error(
8 StatusCode::BAD_REQUEST,
9 "ValidationException",
10 "KeySchema is required",
11 )
12 })?;
13 Ok(arr
14 .iter()
15 .map(|elem| KeySchemaElement {
16 attribute_name: elem["AttributeName"]
17 .as_str()
18 .unwrap_or_default()
19 .to_string(),
20 key_type: elem["KeyType"].as_str().unwrap_or("HASH").to_string(),
21 })
22 .collect())
23}
24
25pub(crate) fn parse_attribute_definitions(
26 val: &Value,
27) -> Result<Vec<AttributeDefinition>, AwsServiceError> {
28 let arr = val.as_array().ok_or_else(|| {
29 AwsServiceError::aws_error(
30 StatusCode::BAD_REQUEST,
31 "ValidationException",
32 "AttributeDefinitions is required",
33 )
34 })?;
35 Ok(arr
36 .iter()
37 .map(|elem| AttributeDefinition {
38 attribute_name: elem["AttributeName"]
39 .as_str()
40 .unwrap_or_default()
41 .to_string(),
42 attribute_type: elem["AttributeType"].as_str().unwrap_or("S").to_string(),
43 })
44 .collect())
45}
46
47pub(crate) fn parse_provisioned_throughput(
48 val: &Value,
49) -> Result<ProvisionedThroughput, AwsServiceError> {
50 Ok(ProvisionedThroughput {
51 read_capacity_units: val["ReadCapacityUnits"].as_i64().unwrap_or(5),
52 write_capacity_units: val["WriteCapacityUnits"].as_i64().unwrap_or(5),
53 })
54}
55
56pub fn parse_gsi(val: &Value, billing_mode: &str) -> Vec<GlobalSecondaryIndex> {
57 let Some(arr) = val.as_array() else {
58 return Vec::new();
59 };
60 arr.iter()
61 .filter_map(|g| {
62 Some(GlobalSecondaryIndex {
63 index_name: g["IndexName"].as_str()?.to_string(),
64 key_schema: parse_key_schema(&g["KeySchema"]).ok()?,
65 projection: parse_projection(&g["Projection"]),
66 provisioned_throughput: Some(parse_gsi_throughput(
67 &g["ProvisionedThroughput"],
68 billing_mode,
69 )),
70 on_demand_throughput: parse_on_demand_throughput(&g["OnDemandThroughput"]),
71 })
72 })
73 .collect()
74}
75
76pub fn parse_gsi_throughput(val: &Value, billing_mode: &str) -> ProvisionedThroughput {
83 if billing_mode == "PAY_PER_REQUEST" {
84 return ProvisionedThroughput {
85 read_capacity_units: 0,
86 write_capacity_units: 0,
87 };
88 }
89 ProvisionedThroughput {
90 read_capacity_units: val["ReadCapacityUnits"].as_i64().unwrap_or(5),
91 write_capacity_units: val["WriteCapacityUnits"].as_i64().unwrap_or(5),
92 }
93}
94
95pub fn parse_lsi(val: &Value) -> Vec<LocalSecondaryIndex> {
96 let Some(arr) = val.as_array() else {
97 return Vec::new();
98 };
99 arr.iter()
100 .filter_map(|l| {
101 Some(LocalSecondaryIndex {
102 index_name: l["IndexName"].as_str()?.to_string(),
103 key_schema: parse_key_schema(&l["KeySchema"]).ok()?,
104 projection: parse_projection(&l["Projection"]),
105 })
106 })
107 .collect()
108}
109
110pub fn parse_tags(val: &Value) -> BTreeMap<String, String> {
111 let mut tags = BTreeMap::new();
112 if let Some(arr) = val.as_array() {
113 for tag in arr {
114 if let (Some(k), Some(v)) = (tag["Key"].as_str(), tag["Value"].as_str()) {
115 tags.insert(k.to_string(), v.to_string());
116 }
117 }
118 }
119 tags
120}
121
122pub(crate) fn parse_expression_attribute_names(body: &Value) -> HashMap<String, String> {
123 let mut names = HashMap::new();
124 if let Some(obj) = body["ExpressionAttributeNames"].as_object() {
125 for (k, v) in obj {
126 if let Some(s) = v.as_str() {
127 names.insert(k.clone(), s.to_string());
128 }
129 }
130 }
131 names
132}
133
134pub(crate) fn parse_expression_attribute_values(body: &Value) -> HashMap<String, Value> {
135 let mut values = HashMap::new();
136 if let Some(obj) = body["ExpressionAttributeValues"].as_object() {
137 for (k, v) in obj {
138 values.insert(k.clone(), v.clone());
139 }
140 }
141 values
142}