Skip to content
Snippets Groups Projects
Verified Commit 33612ba5 authored by Nik | Klampfradler's avatar Nik | Klampfradler
Browse files

[NSS] Refactor more jq program loading code into function

parent 44bde3bb
No related branches found
No related tags found
No related merge requests found
......@@ -151,73 +151,67 @@ fn get_data(conf: &Config, prefix: &str, endpoint: &str, param: String, token: &
.text()?)
}
fn get_jq_prog(conf: &Config, prefix: &str, endpoint: &str, rev: bool) -> Option<String> {
fn get_jq_prog(conf: &Config, prefix: &str, endpoint: &str, multi: bool, rev: bool) -> jq_rs::Result<jq_rs::JqProgram> {
// Generate config key to find jq program under
let prog_key = match rev {
false => full_key(vec![prefix, "maps", endpoint]),
true => full_key(vec![prefix, "maps.rev", endpoint]),
};
match get_optional(&conf, &prog_key) {
Some(v) => Some (v),
// Retrieve jq program code from config
let mut jq_code: String = match get_optional(&conf, &prog_key) {
// We got the value immediately
Some(v) => v,
None => {
if rev {
// Do not fallback to more generic program for reverse mapping
return None;
}
// Try falling back to more generic program
match endpoint.find('.') {
Some(i) => {
debug!("JQ mapping program for {} not found; trying more generic definition", endpoint);
get_jq_prog(conf, prefix, &endpoint[..i], rev)
},
None => None
".".to_string()
} else {
// Try falling back to more generic program
match endpoint.find('.') {
Some(i) => {
debug!("JQ mapping program for {} not found; trying more generic definition", endpoint);
// Call recursively (and return verbatim, as we get a compiled program)
return get_jq_prog(conf, prefix, &endpoint[..i], multi, rev)
}
// Lookup failed ultimately; fallback to jq "identity" (no-op)
None => ".".to_string()
}
}
}
};
// If multi mode is passed, the program will be applied to an array of entries
// We thus wrap it in a call to jq's `map()`
if multi {
jq_code = "map(".to_string() + &jq_code + ")";
}
debug!("Compiling JQ program for endpoint {}: {}", endpoint, jq_code);
jq_rs::compile(&jq_code)
}
pub fn get_data_jq<T: for<'de> Deserialize<'de>, V: Serialize>(conf: &Config, prefix: &str, endpoint: &str, param: V, token: &BasicTokenResponse, multi: bool) -> Result<T, Box<dyn error::Error>> {
let res: Option<String> = get_jq_prog(&conf, prefix, endpoint, false);
let jq_code = match res {
Some(s) => {
debug!("Found jq mapping program for endpoint {}: {}", endpoint, s);
match multi {
true => "map(".to_string() + &s + ")",
false => s
}
},
None => {
debug!("No jq mapping program for endpoint {}; using default (no-op)", endpoint);
".".to_string()
}
};
let mut jq_prog = jq_rs::compile(&jq_code)?;
let res: Option<String> = get_jq_prog(&conf, prefix, endpoint, true);
let jq_code = match res {
Some(s) => {
debug!("Found jq reverse mapping program for endpoint {}: {}", endpoint, s);
s
},
None => {
debug!("No jq reverse mapping program for endpoint {}; using default (no-op)", endpoint);
".".to_string()
}
};
let mut jq_prog_rev = jq_rs::compile(&jq_code)?;
// Get jq mapping programs for forward and reverse mappings
let mut jq_prog_fwd = get_jq_prog(&conf, prefix, endpoint, multi, false)?;
let mut jq_prog_rev = get_jq_prog(&conf, prefix, endpoint, false, true)?;
// Convert and transform the passed param using the reverse JQ mapping program
// 1. Serialize into JSON value (atomic) to be bale to pass into jq
let param_serialized = serde_json::to_string(&param)?;
let param = serde_json::to_string(&param)?;
// 2. Transform using the JQ program loaded above
let param_trans = jq_prog_rev.run(&param_serialized)?.trim().to_string();
let param = jq_prog_rev.run(&param)?.trim().to_string();
// 3. Deserialize into serde_json value so we get numbers as numbers, strings properly unquoted
let param_deserialized: serde_json::Value = serde_json::from_str(&param_trans)?;
let param = match param_deserialized {
let param: serde_json::Value = serde_json::from_str(&param)?;
let param = match param {
serde_json::Value::String(v) => v, // We want strings verbatim without JSON quoting
_ => param_deserialized.to_string() // We want numbers converted to string
_ => param.to_string() // We want numbers converted to string
};
let data_raw = get_data(&conf, prefix, endpoint, param, token)?;
let data_trans = jq_prog.run(&data_raw)?;
// Retrieve data via HTTP and transform using jq forward mapping program
let data = get_data(&conf, prefix, endpoint, param, token)?;
let data = jq_prog_fwd.run(&data)?;
Ok(serde_json::from_str(&data_trans)?)
// Deserialize transformed JSON and return
Ok(serde_json::from_str(&data)?)
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment