#[allow(clippy::wildcard_imports)]
use super::*;
pub(super) fn req_string(args: &Value, key: &str) -> std::result::Result<String, ()> {
let value = args.get(key).ok_or(())?;
value.as_str().map(str::to_string).ok_or(())
}
pub(super) fn opt_string(args: &Value, key: &str) -> std::result::Result<Option<String>, ()> {
let Some(value) = args.get(key) else {
return Ok(None);
};
if value.is_null() {
return Ok(None);
}
value.as_str().map(|s| Some(s.to_string())).ok_or(())
}
pub(super) fn opt_selector(args: &Value, key: &str) -> std::result::Result<Option<String>, ()> {
let Some(value) = args.get(key) else {
return Ok(None);
};
match value {
Value::Null => Ok(None),
Value::String(s) => Ok(Some(s.clone())),
Value::Number(n) => n.as_i64().map(|i| Some(i.to_string())).ok_or(()),
_ => Err(()),
}
}
pub(super) fn reject_retired_links(args: &Value) -> Option<Value> {
if !args.as_object().is_some_and(|o| o.contains_key("links")) {
return None;
}
Some(error_result(
"invalid input: `links` was removed \u{2014} the typed model replaces it. \
create each relationship with `link_issue` (`a`, `b`, `kind`) and remove \
an existing one with `remove_relationship` (`id`). The old argument \
*replaced* the whole set, so replacing it means one `remove_relationship` \
per existing edge plus one `link_issue` per new one"
.to_string(),
))
}
pub(super) fn opt_string_array(
args: &Value,
key: &str,
) -> std::result::Result<Option<Vec<String>>, ()> {
let Some(value) = args.get(key) else {
return Ok(None);
};
if value.is_null() {
return Ok(None);
}
let items = value.as_array().ok_or(())?;
let mut out: Vec<String> = Vec::with_capacity(items.len());
for item in items {
out.push(item.as_str().ok_or(())?.to_string());
}
Ok(Some(out))
}
pub(super) fn opt_bool(args: &Value, key: &str) -> std::result::Result<Option<bool>, ()> {
let Some(value) = args.get(key) else {
return Ok(None);
};
if value.is_null() {
return Ok(None);
}
value.as_bool().map(Some).ok_or(())
}
pub(super) fn selector(args: &Value, key: &str) -> std::result::Result<String, ()> {
let value = args.get(key).ok_or(())?;
match value {
Value::Null => Err(()),
Value::String(s) => Ok(s.clone()),
Value::Number(n) => n.as_i64().map(|i| i.to_string()).ok_or(()),
_ => Err(()),
}
}
pub(super) fn req_u32(args: &Value, key: &str) -> std::result::Result<u32, ()> {
let value = args.get(key).ok_or(())?;
let number = value.as_u64().ok_or(())?;
u32::try_from(number).map_err(|_| ())
}
pub(super) fn opt_u32(args: &Value, key: &str) -> std::result::Result<Option<u32>, ()> {
let Some(value) = args.get(key) else {
return Ok(None);
};
if value.is_null() {
return Ok(None);
}
value
.as_u64()
.and_then(|number| u32::try_from(number).ok())
.map(Some)
.ok_or(())
}
pub(super) fn req_i64(args: &Value, key: &str) -> std::result::Result<i64, ()> {
args.get(key).and_then(Value::as_i64).ok_or(())
}
pub(super) fn opt_i64(args: &Value, key: &str) -> std::result::Result<Option<i64>, ()> {
let Some(value) = args.get(key) else {
return Ok(None);
};
if value.is_null() {
return Ok(None);
}
value.as_i64().map(Some).ok_or(())
}