refactor: extract platform media crates
This commit is contained in:
159
server-rs/crates/platform-hyper3d/src/response/parsing.rs
Normal file
159
server-rs/crates/platform-hyper3d/src/response/parsing.rs
Normal file
@@ -0,0 +1,159 @@
|
||||
use serde_json::Value;
|
||||
|
||||
pub(crate) fn parse_api_error_message(raw_text: &str, fallback_message: &str) -> String {
|
||||
if let Ok(parsed) = serde_json::from_str::<Value>(raw_text) {
|
||||
for key in ["message", "detail", "error"] {
|
||||
if let Some(message) = find_first_string_by_key(&parsed, key)
|
||||
&& !message.trim().is_empty()
|
||||
{
|
||||
return message;
|
||||
}
|
||||
}
|
||||
}
|
||||
raw_text
|
||||
.trim()
|
||||
.chars()
|
||||
.take(240)
|
||||
.collect::<String>()
|
||||
.trim()
|
||||
.to_string()
|
||||
.chars()
|
||||
.next()
|
||||
.map(|_| raw_text.trim().chars().take(240).collect())
|
||||
.unwrap_or_else(|| fallback_message.to_string())
|
||||
}
|
||||
|
||||
pub(crate) fn find_first_array_by_keys<'a>(
|
||||
value: &'a Value,
|
||||
keys: &[&str],
|
||||
) -> Option<&'a Vec<Value>> {
|
||||
match value {
|
||||
Value::Object(object) => {
|
||||
for (key, value) in object {
|
||||
if keys.iter().any(|target| key.eq_ignore_ascii_case(target))
|
||||
&& let Some(array) = value.as_array()
|
||||
{
|
||||
return Some(array);
|
||||
}
|
||||
if let Some(found) = find_first_array_by_keys(value, keys) {
|
||||
return Some(found);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
Value::Array(items) => items
|
||||
.iter()
|
||||
.find_map(|item| find_first_array_by_keys(item, keys)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn find_first_string_by_keys(value: &Value, keys: &[&str]) -> Option<String> {
|
||||
keys.iter()
|
||||
.find_map(|key| find_first_string_by_key(value, key))
|
||||
}
|
||||
|
||||
pub(crate) fn find_first_f64_by_keys(value: &Value, keys: &[&str]) -> Option<f64> {
|
||||
match value {
|
||||
Value::Object(object) => {
|
||||
for (key, value) in object {
|
||||
if keys.iter().any(|target| key.eq_ignore_ascii_case(target))
|
||||
&& let Some(number) = value.as_f64()
|
||||
{
|
||||
return Some(number);
|
||||
}
|
||||
if let Some(found) = find_first_f64_by_keys(value, keys) {
|
||||
return Some(found);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
Value::Array(items) => items
|
||||
.iter()
|
||||
.find_map(|item| find_first_f64_by_keys(item, keys)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn find_first_string_by_key(value: &Value, target_key: &str) -> Option<String> {
|
||||
match value {
|
||||
Value::Object(object) => {
|
||||
for (key, value) in object {
|
||||
if key.eq_ignore_ascii_case(target_key)
|
||||
&& let Some(text) = value.as_str()
|
||||
{
|
||||
return Some(text.trim().to_string());
|
||||
}
|
||||
if let Some(found) = find_first_string_by_key(value, target_key) {
|
||||
return Some(found);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
Value::Array(items) => items
|
||||
.iter()
|
||||
.find_map(|item| find_first_string_by_key(item, target_key)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn find_root_string_by_keys(value: &Value, keys: &[&str]) -> Option<String> {
|
||||
let object = value.as_object()?;
|
||||
for key in keys {
|
||||
if let Some(text) = object
|
||||
.iter()
|
||||
.find(|(candidate, _)| candidate.eq_ignore_ascii_case(key))
|
||||
.and_then(|(_, value)| value.as_str())
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty())
|
||||
{
|
||||
return Some(text.to_string());
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub(crate) fn collect_strings_by_keys(value: &Value, keys: &[&str]) -> Vec<String> {
|
||||
let mut results = Vec::new();
|
||||
collect_strings(value, keys, &mut results);
|
||||
let mut deduped = Vec::new();
|
||||
for result in results {
|
||||
if !deduped.contains(&result) {
|
||||
deduped.push(result);
|
||||
}
|
||||
}
|
||||
deduped
|
||||
}
|
||||
|
||||
fn collect_strings(value: &Value, keys: &[&str], output: &mut Vec<String>) {
|
||||
match value {
|
||||
Value::Object(object) => {
|
||||
for (key, value) in object {
|
||||
if keys.iter().any(|target| key.eq_ignore_ascii_case(target)) {
|
||||
match value {
|
||||
Value::String(text) if !text.trim().is_empty() => {
|
||||
output.push(text.trim().to_string());
|
||||
}
|
||||
Value::Array(items) => {
|
||||
for item in items {
|
||||
if let Some(text) = item.as_str().map(str::trim)
|
||||
&& !text.is_empty()
|
||||
{
|
||||
output.push(text.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
collect_strings(value, keys, output);
|
||||
}
|
||||
}
|
||||
Value::Array(items) => {
|
||||
for item in items {
|
||||
collect_strings(item, keys, output);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user