rs-pixel 0.1.0

A complete, rate-limiting, asynchronous Rust implementation of the Hypixel Public API with extensive SkyBlock support
Documentation
use serde_json::{Map, Value};

pub trait Raw {
    fn raw(&self) -> &Value;
}

pub trait Property {
    fn get_property(&self, full_path: &str) -> Option<&Value>;
    fn get_str_property(&self, full_path: &str) -> Option<&str>;
    fn get_string_property(&self, full_path: &str) -> Option<String>;
    fn get_int_property(&self, full_path: &str) -> Option<i64>;
    fn get_float_property(&self, full_path: &str) -> Option<f64>;
    fn get_array_property(&self, full_path: &str) -> Option<&Vec<Value>>;
    fn get_object_property(&self, full_path: &str) -> Option<&Map<String, Value>>;
}

impl<T> Property for T
where
    T: Raw,
{
    fn get_property(&self, full_path: &str) -> Option<&Value> {
        if full_path.is_empty() {
            return Some(self.raw());
        }

        let paths = full_path.split('.');
        let mut cur_raw = self.raw();

        for path in paths {
            if cur_raw.is_array() {
                if let Ok(idx) = path.parse::<usize>() {
                    match cur_raw.get(idx) {
                        Some(new_raw) => cur_raw = new_raw,
                        None => return None,
                    };
                    continue;
                }
            }

            match cur_raw.get(path) {
                Some(new_raw) => cur_raw = new_raw,
                None => return None,
            }
        }

        Some(cur_raw)
    }

    fn get_str_property(&self, full_path: &str) -> Option<&str> {
        self.get_property(full_path)
            .and_then(serde_json::Value::as_str)
    }

    fn get_string_property(&self, full_path: &str) -> Option<String> {
        self.get_property(full_path)
            .and_then(serde_json::Value::as_str)
            .map(std::string::ToString::to_string)
    }

    fn get_int_property(&self, full_path: &str) -> Option<i64> {
        self.get_property(full_path)
            .and_then(serde_json::Value::as_i64)
            .or_else(|| {
                self.get_property(full_path)
                    .and_then(serde_json::Value::as_f64)
                    .map(|v| v as i64)
            })
    }

    fn get_float_property(&self, full_path: &str) -> Option<f64> {
        self.get_property(full_path)
            .and_then(serde_json::Value::as_f64)
            .or_else(|| {
                self.get_property(full_path)
                    .and_then(serde_json::Value::as_i64)
                    .map(|v| v as f64)
            })
    }

    fn get_array_property(&self, full_path: &str) -> Option<&Vec<Value>> {
        self.get_property(full_path)
            .and_then(serde_json::Value::as_array)
    }

    fn get_object_property(&self, full_path: &str) -> Option<&Map<String, Value>> {
        self.get_property(full_path)
            .and_then(serde_json::Value::as_object)
    }
}

impl Raw for Value {
    fn raw(&self) -> &Value {
        self
    }
}