1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
use yaml_rust::Yaml;
use crate::utils::parse_pairs;
use yaml_rust::yaml::{Hash, Array};
use std::f64;
use arc_convert_lib::{ indent};

pub trait ToArc {
    fn to_arc(&self) -> String;
}

impl ToArc for Yaml {
    fn to_arc(&self) -> String {
        match self {
            Yaml::Real(r) => {
                if r.to_lowercase().contains('e') {
                    match r.parse::<f64>() {
                        Ok(o) => {
                            format!("{}", o)
                        }
                        Err(_) => {
                            String::from("null")
                        }
                    }
                } else if r.to_lowercase().contains("n") {
                    match r.to_lowercase().as_str() {
                        ".inf" | "+.inf" | "inf" => format!("{:#X}f64", f64::INFINITY.to_bits()),
                        "-inf" | "-.inf" => format!("{:#X}f64", f64::NEG_INFINITY.to_bits()),
                        ".nan" | "nan" => format!("{:#X}f64", f64::NAN.to_bits()),
                        _ => {
                            String::from("null")
                        }
                    }
                } else if r.starts_with('.') {
                    format!("0{}", r)
                } else if r.ends_with('.') {
                    format!("{}0", r)
                } else {
                    format!("{}", r)
                }
            }
            Yaml::Integer(i) => {
                format!("{}", i)
            }
            Yaml::String(s) => {
                format!("{:?}", s)
            }
            Yaml::Boolean(b) => {
                format!("{}", b)
            }
            Yaml::Array(a) => {
                a.to_arc()
            }
            Yaml::Hash(h) => {
                h.to_arc()
            }
            Yaml::Alias(a) => {
                println!("{:#?}", a);
                unreachable!()
            }
            Yaml::Null => {
                String::from("null")
            }
            Yaml::BadValue => {
                String::from("null")
            }
        }
    }
}

impl ToArc for Hash {
    fn to_arc(&self) -> String {
        let kv = parse_pairs(self);
        if kv.len() == 1 {
            format!("{{{}}}", kv[0])
        } else {
            format!("{{\n{}}}", indent(&kv.join("\n"), "    "))
        }
    }
}

impl ToArc for Array {
    fn to_arc(&self) -> String {
        let mut max = 0;
        let mut len = 0;
        let mut v = vec![];
        for a in self {
            let s = a.to_arc();
            let l = s.lines().count();
            if l > max {
                max = l
            }
            len += s.len();//for fast
            v.push(s)
        }
        if len < 128 && max <= 1 {
            format!("[{}]", v.join(", "))
        } else {
            format!("[\n{}]", indent(&v.join("\n"), "    "))
        }
    }
}