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
use chrono::prelude::*;
use chrono::NaiveDateTime;
use crate::client::HglibError;
#[derive(Debug, PartialEq)]
pub struct Revision {
pub rev: u64,
pub node: String,
pub tags: String,
pub branch: String,
pub author: String,
pub desc: String,
pub date: DateTime<Utc>,
}
pub const CHANGESETS_TEMPLATE: &str =
"{rev}\\0{node}\\0{tags}\\0{branch}\\0{author}\\0{desc}\\0{date}\\0";
pub fn parserevs(data: Vec<u8>) -> Result<Vec<Revision>, HglibError> {
let mut count = 0;
let mut parts: Vec<&[u8]> = vec![&[]; 6];
let mut res = Vec::new();
let mut rev: u64 = 0;
for buf in data.split(|x| *x == b'\0') {
if count == 0 {
rev = buf.iter().fold(0, |r, x| r * 10 + u64::from(*x - b'0'));
count += 1;
} else if count == 6 {
count = 0;
let timestamp = buf
.iter()
.take_while(|x| **x != b'.')
.fold(0, |r, x| r * 10 + i64::from(*x - b'0'));
res.push(Revision {
rev,
node: String::from_utf8(parts[1].to_vec())?,
tags: String::from_utf8(parts[2].to_vec())?,
branch: String::from_utf8(parts[3].to_vec())?,
author: String::from_utf8(parts[4].to_vec())?,
desc: String::from_utf8(parts[5].to_vec())?,
date: DateTime::from_utc(NaiveDateTime::from_timestamp(timestamp, 0), Utc),
});
rev = 0;
} else {
parts[count] = &buf;
count += 1;
}
}
Ok(res)
}
pub fn eatlines(buf: &[u8], n: u32) -> &[u8] {
let mut iter = buf.iter();
let mut count = 0;
while let Some(c) = iter.next() {
if *c == b'\n' {
if count == n - 1 {
return iter.as_slice();
} else {
count += 1;
}
}
}
&[]
}
pub fn handle_err(x: Result<(Vec<u8>, i32), HglibError>) -> Result<bool, HglibError> {
match x {
Ok((_, code)) => Ok(code == 0),
Err(err) => {
if err.code == 0 {
Ok(true)
} else if err.code == 1 {
Ok(false)
} else {
Err(err)
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_eatlines() {
let s = "rust
is
an
amazing
programming
language";
let s = s.as_bytes();
let r = eatlines(s, 1);
assert!(&r[..2] == b"is");
let r = eatlines(s, 2);
assert!(&r[..2] == b"an");
let r = eatlines(s, 4);
assert!(&r[..2] == b"pr");
}
}