1use crate::{DecodeError,Info};
2type Strings = std::collections::VecDeque<(Vec<u8>,Vec<u8>)>;
3use std::backtrace::Backtrace;
4
5pub fn info(buf: &[u8], prev_id: &Option<u64>, prev_info: &Option<Info>, strings: &mut Strings)
6-> Result<(usize,(u64,Option<Info>)),DecodeError> {
7 let mut offset = 0;
8 let mut info = Info::new();
9 let id = {
10 let (s,x) = signed(&buf[offset..])?;
11 offset += s;
12 (x + prev_id.unwrap_or(0) as i64) as u64
13 };
14 info.version = {
15 let (s,x) = unsigned(&buf[offset..])?;
16 offset += s;
17 if x == 0 { return Ok((offset, (id, None))) }
18 Some(x)
19 };
20 info.timestamp = {
21 let (s,x) = signed(&buf[offset..])?;
22 offset += s;
23 let p = prev_info.as_ref().map(|info| {
24 info.timestamp.unwrap_or(0)
25 }).unwrap_or(0);
26 if x + p == 0 { return Ok((offset, (id, Some(info)))) }
27 Some(x + p)
28 };
29 info.changeset = {
30 let (s,x) = signed(&buf[offset..])?;
31 offset += s;
32 let p = prev_info.as_ref().map(|info| {
33 info.changeset.unwrap_or(0)
34 }).unwrap_or(0) as i64;
35 Some((x + p) as u64)
36 };
37 {
38 let (s,x) = unsigned(&buf[offset..])?;
39 offset += s;
40 if x == 0 {
41 let (s,x) = unsigned(&buf[offset..])?;
42 let uid_bytes = &buf[offset..offset+s];
43 offset += s;
44 info.uid = Some(x);
45 if buf[offset] != 0 {
46 return Err(DecodeError::UnexpectedByte {
47 info: "decoding uid".to_string(),
48 expected: 0,
49 received: buf[offset],
50 backtrace: Backtrace::capture(),
51 });
52 }
53 offset += 1;
54 let i = offset + buf[offset..].iter()
55 .position(|p| *p == 0x00).unwrap_or(buf.len()-offset);
56 info.user = Some(std::str::from_utf8(&buf[offset..i])
57 .map_err(|e| DecodeError::StringEncodingError {
58 source: Box::new(e.into())
59 })?
60 .to_string()
61 );
62 if uid_bytes.len() + (i-offset) <= 250 {
63 strings.push_front((uid_bytes.to_vec(),buf[offset..i].to_vec()));
64 if strings.len() > 15_000 { strings.pop_back(); }
65 }
66 offset = i+1;
67 } else {
68 let pair = strings.get((x as usize)-1);
69 if pair.is_none() {
70 return Err(DecodeError::StringUnavailable {
71 index: x as usize,
72 backtrace: Backtrace::capture(),
73 });
74 }
75 let (uid_bytes,user_bytes) = pair.unwrap();
76 info.uid = Some(unsigned(uid_bytes)?.1);
77 info.user = Some(String::from_utf8(user_bytes.to_vec())
78 .map_err(|e| DecodeError::StringEncodingError { source: Box::new(e.into()) })?
79 );
80 }
81 }
82 Ok((offset, (id, Some(info))))
83}
84
85type Tags = std::collections::HashMap<String,String>;
86
87pub fn tags(buf: &[u8], strings: &mut Strings) -> Result<(usize,Tags),DecodeError> {
88 let mut tags = std::collections::HashMap::new();
89 let mut offset = 0;
90 while offset < buf.len() {
91 let (s,x) = unsigned(&buf[offset..])?;
92 offset += s;
93 if x == 0 {
94 let i = offset + buf[offset..].iter()
95 .position(|p| *p == 0x00).unwrap_or(buf.len()-offset);
96 let key_bytes = &buf[offset..i];
97 let key = std::str::from_utf8(key_bytes)
98 .map_err(|e| DecodeError::StringEncodingError { source: Box::new(e.into()) })?
99 .to_string();
100 offset = i+1;
101 let j = offset + buf[offset..].iter()
102 .position(|p| *p == 0x00).unwrap_or(buf.len()-offset);
103 let value_bytes = &buf[offset..j];
104 let value = std::str::from_utf8(value_bytes)
105 .map_err(|e| DecodeError::StringEncodingError { source: Box::new(e.into()) })?
106 .to_string();
107 offset = j+1;
108 tags.insert(key, value);
109 if key_bytes.len() + value_bytes.len() <= 250 {
110 strings.push_front((key_bytes.to_vec(),value_bytes.to_vec()));
111 if strings.len() > 15_000 { strings.pop_back(); }
112 }
113 } else {
114 let pair = strings.get((x as usize)-1);
115 if pair.is_none() {
116 return Err(DecodeError::StringUnavailable {
117 index: x as usize,
118 backtrace: Backtrace::capture(),
119 });
120 }
121 let (key_bytes,value_bytes) = pair.unwrap();
122 let key = String::from_utf8(key_bytes.to_vec())
123 .map_err(|e| DecodeError::StringEncodingError { source: Box::new(e.into()) })?;
124 let value = String::from_utf8(value_bytes.to_vec())
125 .map_err(|e| DecodeError::StringEncodingError { source: Box::new(e.into()) })?;
126 tags.insert(key, value);
127 }
128 }
129 Ok((offset,tags))
130}
131
132pub fn signed(buf: &[u8]) -> Result<(usize,i64),DecodeError> {
133 let mut value = 0;
134 let mut lshift = 0;
135 for (i,b) in buf.iter().enumerate() {
136 value += ((*b as i64) & 0x7f) << lshift;
137 lshift += 7;
138 if *b < 0x80 {
139 let sign = match value % 2 { 0 => 1, _ => -1 };
140 value = value * sign / 2;
141 if sign < 0 { value -= 1 }
142 return Ok((i+1,value));
143 }
144 }
145 Err(DecodeError::UnterminatedSignedInteger { backtrace: Backtrace::capture() })
146}
147
148pub fn unsigned(buf: &[u8]) -> Result<(usize,u64),DecodeError> {
149 let mut value = 0;
150 let mut lshift = 0;
151 for (i,b) in buf.iter().enumerate() {
152 value += ((*b as u64) & 0x7f) << lshift;
153 lshift += 7;
154 if *b < 0x80 {
155 return Ok((i+1,value));
156 }
157 }
158 Err(DecodeError::UnterminatedUnsignedInteger { backtrace: Backtrace::capture() })
159}