1use std::io::{self};
10
11pub mod raw;
12
13pub fn lenenc_int_len(x: u64) -> u64 {
15 if x < 251 {
16 1
17 } else if x < 65_536 {
18 3
19 } else if x < 16_777_216 {
20 4
21 } else {
22 9
23 }
24}
25
26pub fn lenenc_str_len(s: &[u8]) -> u64 {
28 let len = s.len() as u64;
29 lenenc_int_len(len) + len
30}
31
32pub(crate) fn unexpected_buf_eof() -> io::Error {
33 io::Error::new(
34 io::ErrorKind::UnexpectedEof,
35 "can't parse: buf doesn't have enough data",
36 )
37}
38
39pub fn split_version<T: AsRef<[u8]>>(version_str: T) -> (u8, u8, u8) {
43 let bytes = version_str.as_ref();
44 split_version_inner(bytes).unwrap_or((0, 0, 0))
45}
46
47fn split_version_inner(input: &[u8]) -> Option<(u8, u8, u8)> {
51 let mut nums = [0_u8; 3];
52 let mut iter = input.split(|c| *c == b'.');
53 for (i, chunk) in (&mut iter).take(2).enumerate() {
54 nums[i] = btoi::btoi(chunk).ok()?;
55 }
56 let chunk_with_junk = iter.next()?;
58 let end_of_digits = chunk_with_junk.iter().position(|c| *c < b'0' || *c > b'9');
59 let chunk = match end_of_digits {
60 Some(pos) => &chunk_with_junk[..pos],
61 None => chunk_with_junk,
62 };
63 nums[2] = btoi::btoi(chunk).ok()?;
64
65 Some((nums[0], nums[1], nums[2]))
66}
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71
72 #[test]
73 fn should_split_version() {
74 assert_eq!((1, 2, 3), split_version("1.2.3"));
75 assert_eq!((10, 20, 30), split_version("10.20.30foo"));
76 assert_eq!((0, 0, 0), split_version("100.200.300foo"));
77 assert_eq!((0, 0, 0), split_version("100.200foo"));
78 assert_eq!((0, 0, 0), split_version("1,2.3"));
79 assert_eq!((0, 0, 0), split_version("1"));
80 assert_eq!((0, 0, 0), split_version("1.2"));
81 }
82}