hglib/commands/
common.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this file,
3// You can obtain one at http://mozilla.org/MPL/2.0/.
4
5use 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}