o5m_stream/
parse.rs

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}