cyfs-util 0.6.8

Rust cyfs-util package
Documentation
use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult};
use std::str::FromStr;
use std::convert::TryFrom;


pub struct TomlHelper;
impl TomlHelper {
    pub fn decode_from_string<T>(v: &toml::Value) -> BuckyResult<T>
    where
        T: FromStr,
        <T as FromStr>::Err: std::fmt::Display,
    {
        if !v.is_str() {
            let msg = format!("invalid toml field, except string: {}", v);
            warn!("{}", msg);

            return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg));
        }

        let v = T::from_str(v.as_str().unwrap()).map_err(|e| {
            let msg = format!(
                "parse toml string error: value={}, {}",
                v.as_str().unwrap(),
                e
            );
            warn!("{}", msg);

            BuckyError::new(BuckyErrorCode::InvalidFormat, msg)
        })?;

        Ok(v)
    }

    pub fn decode_from_boolean(v: &toml::Value) -> BuckyResult<bool> {
        let v = v.as_bool().ok_or_else(|| {
            let msg = format!("invalid toml field, except bool: {}", v);
            warn!("{}", msg);

            BuckyError::new(BuckyErrorCode::InvalidFormat, msg)
        })?;

        Ok(v)
    }

    pub fn decode_string_field<T>(obj: &toml::value::Table, key: &str) -> BuckyResult<T>
    where
        T: FromStr,
        <T as FromStr>::Err: std::fmt::Display,
    {
        let v = obj.get(key).ok_or_else(|| {
            let msg = format!("field not found: {}", key);
            warn!("{}", msg);

            BuckyError::new(BuckyErrorCode::NotFound, msg)
        })?;

        Self::decode_from_string(v)
    }

    pub fn decode_option_string_field<T>(
        obj: &toml::value::Table,
        key: &str,
    ) -> BuckyResult<Option<T>>
    where
        T: FromStr,
        <T as FromStr>::Err: std::fmt::Display,
    {
        match obj.get(key) {
            Some(v) => {
                let obj = Self::decode_from_string(v)?;
                Ok(Some(obj))
            }
            None => Ok(None),
        }
    }

    pub fn decode_to_int<T>(v: &toml::Value) -> BuckyResult<T>
    where
        T: FromStr + TryFrom<u64> + TryFrom<i64>,
        <T as FromStr>::Err: std::fmt::Display,
        <T as TryFrom<u64>>::Error: std::fmt::Display,
        <T as TryFrom<i64>>::Error: std::fmt::Display,
    {
        if v.is_str() {
            let v = T::from_str(v.as_str().unwrap()).map_err(|e| {
                let msg = format!(
                    "parse toml string to int error: value={}, {}",
                    v.as_str().unwrap(),
                    e
                );
                warn!("{}", msg);
                BuckyError::new(BuckyErrorCode::InvalidFormat, msg)
            })?;

            Ok(v)
        } else if v.is_integer() {
            if v.is_integer() {
                let v = T::try_from(v.as_integer().unwrap()).map_err(|e| {
                    let msg = format!(
                        "parse toml integer to int error: value={}, {}",
                        v.as_integer().unwrap(),
                        e
                    );
                    warn!("{}", msg);
                    BuckyError::new(BuckyErrorCode::InvalidFormat, msg)
                })?;
                Ok(v)
            } else {
                let msg = format!(
                    "parse toml integer to int error: value={}",
                    v.as_integer().unwrap(),
                );
                warn!("{}", msg);
                Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg))
            }
        } else {
            let msg = format!("invalid toml field, except string or integer: {}", v);
            warn!("{}", msg);

            Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg))
        }
    }


    pub fn extract_sub_node(mut root: toml::Value, path: &str) -> BuckyResult<toml::Value> {
        let parts: Vec<&str> = path.split('.').collect();

        for part in parts {
            root = Self::extract_node(root, part)?;
        }

        Ok(root)
    }

    pub fn extract_node(root: toml::Value, name: &str) -> BuckyResult<toml::Value> {
        match root {
            toml::Value::Table(mut cfg) => match cfg.remove(name) {
                Some(v) => Ok(v),
                None => {
                    let msg = format!("sub node not found! name={}", name);
                    error!("{}", msg);
                    Err(BuckyError::new(BuckyErrorCode::NotFound, msg))
                }
            }

            _ => {
                let msg = format!(
                    "node is not table! config={}", toml::to_string(&root).unwrap()
                );
                error!("{}", msg);
                Err(BuckyError::from((BuckyErrorCode::InvalidFormat, msg)))
            }
        }
    }
}