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}