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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
use crate::kval_enum::{KVal, Decimal};
use regex::{Regex, Match};
use crate::enc_dec::decode::decode;
use crate::enc_dec::encode_to_vec::encode_to_vec;
use once_cell::sync::Lazy;
use crate::error::ComResult;
pub fn to_kvals<I : Iterator<Item=String>>(strs : I) -> Vec<KVal>{
strs.map(|s| to_enum(s)).collect()
}
pub fn compress_strings<I : Iterator<Item=String>>(strs : I) -> ComResult<Vec<u8>>{
let vec : Vec<KVal> = to_kvals(strs);
let encoded = encode_to_vec(&vec)?;
return Ok(encoded);
}
pub fn decompress(mut bytes : &[u8]) -> ComResult<(Vec<String>, usize)>{
let (kihons, size) = decode(&mut bytes)?;
Ok((to_strings(&kihons), size))
}
pub fn to_strings(kihons : &Vec<KVal>) -> Vec<String>{
kihons.iter().map(|k| to_string(k)).collect()
}
pub fn to_string(k : &KVal) -> String{
fn s(t : &str) -> String{ t.to_string() }
return match k{
KVal::Null => s("null"),
KVal::Bit(b) => if *b{ s("1") } else{ s("0") }
KVal::Bool(b) => if *b{ s("true")} else{ s("false") }
KVal::Byte(b) => b.to_string(),
KVal::Str16(s) => s.to_string(),
KVal::Int(i) => i.to_string(),
KVal::Float(f) => f.to_string(),
KVal::Str256(s) => s.to_string(),
KVal::Double(d) => d.to_string(),
KVal::Decimal(d) => d.to_string(),
KVal::BigStr(s) => s.to_string(),
KVal::Binary(v) => format!("{:?}", v),
KVal::BinaryArc(v) => format!("{:?}", v),
KVal::Binary8(v) => format!("{:?}", v),
KVal::Binary4(v) => format!("{:?}", v),
KVal::Binary2(v) => format!("{:?}", v),
KVal::Undefined(u) => format!("undefined{}", u),
}
}
fn to_enum(string : String) -> KVal {
let s = &string;
if s == "0"{ return KVal::Bit(false) }
if s == "1"{ return KVal::Bit(true) }
if s == "true"{ return KVal::Bool(true) }
if s == "false"{ return KVal::Bool(false) }
if let Some(number) = get_number(s){
if number.number == 0 && number.minus {
return get_str(string);
} else if let Some(dot) = number.dot{
return KVal::Decimal(Decimal::new(number.number, dot));
} else{
if number.number == number.number as i64 as i128{
let number = number.number as i64;
if number == number as i8 as i64{
return KVal::Byte(number as i8);
} else {
return KVal::Int(number as i64);
}
} else{
return KVal::Decimal(Decimal::new(number.number, 0));
}
}
} else { return get_str(string); }
}
fn get_str(s : String) -> KVal {
if s.len() < 16{
return KVal::Str16(s);
} else if s.len() < 256{
return KVal::Str256(s);
} else{
return KVal::BigStr(s);
}
}
struct NumResult{
pub(crate) minus : bool,
pub(crate) dot : Option<u8>,
pub(crate) number : i128,
}
fn rex(s : &str) -> Option<regex::Captures>{
static RE: Lazy<Regex> = Lazy::new(|| regex::Regex::new(r#"^(-?)(([0-9]+)(.?)([0-9]*))$"#).unwrap());
return RE.captures(s);
}
fn get_number(s : &str) -> Option<NumResult>{
if let Some(caps) = rex(s){
let minus = (&caps[1]).len() != 0;
fn get_dot_info(m : Option<Match>, len : usize) -> Result<Option<u8>, ()>{
if let Some(m) = m{
if m.as_str().len() != 0 {
let pos = len - m.start() - 1;
if pos < 256 {
return Ok(Some(pos as u8));
} else{
return Err(());
}
}
}
return Ok(None);
}
let dot = get_dot_info(caps.get(4), s.len()).ok()?;
let num_str = format!("{}{}{}",&caps[1], &caps[3], &caps[5]);
let number = num_str.parse::<i128>().ok()?;
let result = NumResult{ minus, dot, number };
let s = &caps[2];
if s.ends_with("."){
return None;
}
if s.starts_with("0"){
if s.starts_with("0."){
return Some(result);
} else{
return None;
}
} else{
return Some(result);
}
} else{ return None; }
}