card_format/
card.rs

1use crate::err::CardErr;
2use serde_derive::*;
3use serde::Serializer as SS;
4use std::collections::BTreeMap;
5use std::fmt::{self, Display};
6use serde::ser::{Serialize, Serializer, SerializeSeq, SerializeMap};
7
8#[derive(Clone, Debug, PartialEq)]
9pub enum CDPathNode {
10    DigLast,
11    Append,
12    AtKey(String),
13}
14#[derive(Debug, PartialEq, Clone)]
15pub enum CData {
16    S(String),
17    N(isize),
18    L(Vec<CData>),
19    M(BTreeMap<String, CData>),
20}
21
22impl serde::Serialize for CData {
23    fn serialize<S:SS>(&self,ser: S) -> Result<<S as SS>::Ok,<S as SS>::Error> {
24        match self {
25            CData::S(s) => ser.serialize_str(s),
26            CData::N(n) => ser.serialize_i64(*n as i64),
27            CData::L(l) => {
28                let mut seq = ser.serialize_seq(Some(l.len()))?;
29                for e in l {
30                    seq.serialize_element(e);
31                }
32                seq.end()
33            }
34            CData::M(m) => {
35                let mut map = ser.serialize_map(Some(m.len()))?;
36                for (k,v) in m {
37                    map.serialize_entry(k,v);
38                }
39                map.end()
40            }
41
42        }
43    }
44}
45
46impl Display for CData {
47    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
48        match self {
49            CData::S(s) => write!(f, r#""{}""#, s),
50            CData::N(n) => write!(f, "{}", n),
51            CData::L(l) => {
52                let mut pre = "[";
53                for item in l {
54                    write!(f, "{}{}", pre, item)?;
55                    pre = ",";
56                }
57                write!(f, "]")
58            }
59            CData::M(m) => {
60                let mut pre = "{";
61                for (k, v) in m {
62                    write!(f, "{}{}:{}", pre, k, v)?;
63                    pre = ",";
64                }
65                write!(f, "{}", "}")
66            }
67        }
68    }
69}
70
71impl CData {
72    pub fn wrap(mut self, w: usize) -> Self {
73        for _ in 0..w {
74            self = CData::L(vec![self]);
75        }
76        self
77    }
78
79    pub fn add_at_path(&mut self, c: CData, path: &[CDPathNode]) -> Result<(), CardErr> {
80        match (self, path.get(0)) {
81            (CData::L(l), Some(CDPathNode::DigLast)) => match l.last_mut() {
82                Some(ls) => return ls.add_at_path(c, &path[1..]),
83                None => l.push(Self::build_from_path(c, &path[1..])),
84            },
85            (CData::L(l), _) => l.push(Self::build_from_path(c, &path[1..])),
86            (CData::M(m), Some(CDPathNode::AtKey(k))) => match m.get_mut(k) {
87                Some(v) => v.add_at_path(c, &path[1..])?,
88                None => {
89                    m.insert(k.clone(), CData::build_from_path(c, &path[1..]));
90                }
91            },
92            (_, _) => return Err(CardErr::S("Could not add child at path")),
93        }
94        Ok(())
95    }
96
97    pub fn build_from_path(c: CData, path: &[CDPathNode]) -> CData {
98        match path.get(0) {
99            Some(CDPathNode::AtKey(k)) => {
100                let mut mp = BTreeMap::new();
101                mp.insert(k.clone(), CData::build_from_path(c, &path[1..]));
102                CData::M(mp)
103            }
104            Some(_) => CData::L(vec![CData::build_from_path(c, &path[1..])]),
105            None => c,
106        }
107    }
108
109    pub fn add_child(&mut self, c: CData, depth: usize) -> Result<(), CardErr> {
110        match self {
111            CData::L(l) => {
112                if depth <= 0 {
113                    l.push(c);
114                    return Ok(());
115                }
116                match l.last_mut() {
117                    None => l.push(c.wrap(depth - 1)),
118                    Some(ls) => {
119                        ls.add_child(c, depth - 1)?;
120                    }
121                }
122            }
123            _ => return Err(CardErr::Unset),
124        }
125        Ok(())
126    }
127
128    pub fn as_list(&self) -> Option<&Vec<CData>> {
129        match self {
130            CData::L(l) => Some(l),
131            _ => None,
132        }
133    }
134}
135
136#[derive(Clone, Debug, Serialize)]
137pub struct Card {
138    pub num: usize,
139    pub name: String,
140    pub data: BTreeMap<String, CData>,
141}
142
143impl Card {
144    pub fn new(name: String, num: usize) -> Card {
145        Card {
146            name,
147            num,
148            data: BTreeMap::new(),
149        }
150    }
151    pub fn build(name: String, num: usize, data: BTreeMap<String, CData>) -> Card {
152        Card { name, num, data }
153    }
154
155    pub fn fill_defaults(&mut self, rmap: &BTreeMap<String, CData>) {
156        for (k, v) in rmap {
157            if self.data.get(k).is_none() {
158                self.data.insert(k.clone(), v.clone());
159            }
160        }
161    }
162    pub fn flatten(mut self)->CData{
163        self.data.insert("name".to_string(), CData::S(self.name));
164        self.data.insert("num".to_string(), CData::N(self.num as isize));
165        CData::M(self.data)
166    }
167}
168
169impl Display for Card {
170    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
171        writeln!(f, "{}*{} : ", self.num, self.name)?;
172        for (k, v) in &self.data {
173            writeln!(f, ".{}:{}", k, v)?;
174        }
175        Ok(())
176    }
177}