graphddb_runtime/
entity.rs1use serde_json::Value as Json;
10
11use crate::templates::{each_placeholder_pub, json_to_template_string};
12
13fn lookup<'a>(item: &'a [(String, Json)], name: &str) -> Option<&'a Json> {
15 item.iter().find(|(k, _)| k == name).map(|(_, v)| v)
16}
17
18fn fill(template: &str, item: &[(String, Json)]) -> String {
21 let mut out = String::new();
22 let bytes = template.as_bytes();
23 let mut i = 0;
24 while i < bytes.len() {
25 if bytes[i] == b'{' {
26 if let Some(close) = template[i + 1..].find('}') {
27 let name = &template[i + 1..i + 1 + close];
28 if !name.is_empty() && !name.contains('{') {
29 let v = lookup(item, name)
30 .map(json_to_template_string)
31 .unwrap_or_default();
32 out.push_str(&v);
33 i += 1 + close + 1;
34 continue;
35 }
36 }
37 }
38 out.push(bytes[i] as char);
39 i += 1;
40 }
41 out
42}
43
44fn fillable(template: &str, item: &[(String, Json)]) -> bool {
46 each_placeholder_pub(template)
47 .iter()
48 .all(|name| lookup(item, name).is_some())
49}
50
51pub fn add_key_attributes(manifest: &Json, entity_name: &str, item: &mut Vec<(String, Json)>) {
55 let entity = manifest
56 .get("entities")
57 .and_then(Json::as_object)
58 .and_then(|e| e.get(entity_name));
59 let entity = match entity {
60 Some(e) => e,
61 None => return,
62 };
63 if let Some(key) = entity.get("key").filter(|k| !k.is_null()) {
64 let pk_tmpl = key.get("pkTemplate").and_then(Json::as_str).unwrap_or("");
65 let pk = fill(pk_tmpl, item);
66 set(item, "PK", Json::String(pk));
67 if let Some(sk_tmpl) = key.get("skTemplate").and_then(Json::as_str) {
68 let sk = fill(sk_tmpl, item);
69 set(item, "SK", Json::String(sk));
70 }
71 }
72 if let Some(gsis) = entity.get("gsis").and_then(Json::as_array) {
73 for gsi in gsis {
74 let index = gsi.get("indexName").and_then(Json::as_str).unwrap_or("");
75 if let Some(pk_tmpl) = gsi.get("pkTemplate").and_then(Json::as_str) {
76 if fillable(pk_tmpl, item) {
77 set(
78 item,
79 &format!("{index}PK"),
80 Json::String(fill(pk_tmpl, item)),
81 );
82 }
83 }
84 if let Some(sk_tmpl) = gsi.get("skTemplate").and_then(Json::as_str) {
85 if fillable(sk_tmpl, item) {
86 set(
87 item,
88 &format!("{index}SK"),
89 Json::String(fill(sk_tmpl, item)),
90 );
91 }
92 }
93 }
94 }
95}
96
97fn set(item: &mut Vec<(String, Json)>, key: &str, value: Json) {
98 if let Some(slot) = item.iter_mut().find(|(k, _)| k == key) {
99 slot.1 = value;
100 } else {
101 item.push((key.to_string(), value));
102 }
103}