1use chrono::prelude::*;
6use chrono::NaiveDateTime;
7
8use crate::client::HglibError;
9
10#[derive(Debug, PartialEq)]
11pub struct Revision {
12 pub rev: u64,
13 pub node: String,
14 pub tags: String,
15 pub branch: String,
16 pub author: String,
17 pub desc: String,
18 pub date: DateTime<Utc>,
19}
20
21pub const CHANGESETS_TEMPLATE: &str =
22 "{rev}\\0{node}\\0{tags}\\0{branch}\\0{author}\\0{desc}\\0{date}\\0";
23
24pub fn parserevs(data: Vec<u8>) -> Result<Vec<Revision>, HglibError> {
25 let mut count = 0;
26 let mut parts: Vec<&[u8]> = vec![&[]; 6];
27 let mut res = Vec::new();
28 let mut rev: u64 = 0;
29
30 for buf in data.split(|x| *x == b'\0') {
31 if count == 0 {
32 rev = buf.iter().fold(0, |r, x| r * 10 + u64::from(*x - b'0'));
33 count += 1;
34 } else if count == 6 {
35 count = 0;
36 let timestamp = buf
37 .iter()
38 .take_while(|x| **x != b'.')
39 .fold(0, |r, x| r * 10 + i64::from(*x - b'0'));
40 res.push(Revision {
41 rev,
42 node: String::from_utf8(parts[1].to_vec())?,
43 tags: String::from_utf8(parts[2].to_vec())?,
44 branch: String::from_utf8(parts[3].to_vec())?,
45 author: String::from_utf8(parts[4].to_vec())?,
46 desc: String::from_utf8(parts[5].to_vec())?,
47 date: DateTime::from_utc(NaiveDateTime::from_timestamp(timestamp, 0), Utc),
48 });
49 rev = 0;
50 } else {
51 parts[count] = &buf;
52 count += 1;
53 }
54 }
55 Ok(res)
56}
57
58pub fn eatlines(buf: &[u8], n: u32) -> &[u8] {
59 let mut iter = buf.iter();
60 let mut count = 0;
61 while let Some(c) = iter.next() {
62 if *c == b'\n' {
63 if count == n - 1 {
64 return iter.as_slice();
65 } else {
66 count += 1;
67 }
68 }
69 }
70 &[]
71}
72
73pub fn handle_err(x: Result<(Vec<u8>, i32), HglibError>) -> Result<bool, HglibError> {
74 match x {
75 Ok((_, code)) => Ok(code == 0),
76 Err(err) => {
77 if err.code == 0 {
78 Ok(true)
79 } else if err.code == 1 {
80 Ok(false)
81 } else {
82 Err(err)
83 }
84 }
85 }
86}
87
88#[cfg(test)]
89mod tests {
90
91 use super::*;
92
93 #[test]
94 fn test_eatlines() {
95 let s = "rust
96is
97an
98amazing
99programming
100language";
101 let s = s.as_bytes();
102 let r = eatlines(s, 1);
103 assert!(&r[..2] == b"is");
104
105 let r = eatlines(s, 2);
106 assert!(&r[..2] == b"an");
107
108 let r = eatlines(s, 4);
109 assert!(&r[..2] == b"pr");
110 }
111}