canic_host/response_parse/
mod.rs1#[cfg(test)]
2mod tests;
3
4#[must_use]
5pub fn find_field<'a>(value: &'a serde_json::Value, field: &str) -> Option<&'a serde_json::Value> {
6 match value {
7 serde_json::Value::Object(map) => map
8 .get(field)
9 .or_else(|| map.values().find_map(|value| find_field(value, field))),
10 serde_json::Value::Array(values) => {
11 values.iter().find_map(|value| find_field(value, field))
12 }
13 _ => None,
14 }
15}
16
17#[must_use]
18pub(crate) fn find_string_field(value: &serde_json::Value, field: &str) -> Option<String> {
19 match value {
20 serde_json::Value::Object(map) => map
21 .get(field)
22 .and_then(|value| value.as_str().map(ToString::to_string))
23 .or_else(|| {
24 map.values()
25 .find_map(|value| find_string_field(value, field))
26 }),
27 serde_json::Value::Array(values) => values
28 .iter()
29 .find_map(|value| find_string_field(value, field)),
30 _ => None,
31 }
32}
33
34#[must_use]
35pub(crate) fn parse_cycle_balance_response(output: &str) -> Option<u128> {
36 serde_json::from_str::<serde_json::Value>(output)
37 .ok()
38 .and_then(|value| find_field(&value, "Ok").and_then(parse_json_u128))
39}
40
41#[must_use]
42pub fn parse_json_u64(value: &serde_json::Value) -> Option<u64> {
43 value
44 .as_u64()
45 .or_else(|| value.as_str().and_then(parse_u64_digits))
46}
47
48#[must_use]
49pub fn parse_json_u128(value: &serde_json::Value) -> Option<u128> {
50 value
51 .as_u64()
52 .map(u128::from)
53 .or_else(|| value.as_str().and_then(parse_u128_digits))
54}
55
56#[must_use]
57pub fn parse_u64_digits(text: &str) -> Option<u64> {
58 number_digits(text).parse().ok()
59}
60
61#[must_use]
62pub fn parse_u128_digits(text: &str) -> Option<u128> {
63 number_digits(text).parse().ok()
64}
65
66fn number_digits(text: &str) -> String {
67 text.chars()
68 .skip_while(|ch| !ch.is_ascii_digit())
69 .take_while(|ch| ch.is_ascii_digit() || *ch == '_' || *ch == ',')
70 .filter(char::is_ascii_digit)
71 .collect()
72}