Skip to main content

canic_host/response_parse/
mod.rs

1#[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}