Skip to main content

thin_fetch/
reference.rs

1use std::{collections::HashMap, str::FromStr};
2
3use crate::{Error, WithError as _};
4
5#[derive(Debug, Clone)]
6pub struct Reference {
7    pub hash: String,
8    pub name: String,
9    pub peeled: Option<String>,
10    pub symref_target: Option<String>,
11}
12
13impl Reference {
14    #[must_use]
15    pub fn target(&self) -> &str {
16        if let Some(ref peeled) = self.peeled {
17            peeled
18        } else {
19            &self.hash
20        }
21    }
22}
23
24impl FromStr for Reference {
25    type Err = Error;
26
27    fn from_str(s: &str) -> Result<Self, Self::Err> {
28        let mut parts = s.trim_end().split(' ');
29
30        let hash = parts.next().with_err_msg("hash not found")?;
31        let name = parts.next().with_err_msg("name not found")?;
32
33        let mut res = Self {
34            hash: hash.to_owned(),
35            name: name.to_owned(),
36            peeled: None,
37            symref_target: None,
38        };
39
40        let mut args = parts
41            .filter_map(|arg| arg.split_once(':'))
42            .collect::<HashMap<&str, &str>>();
43
44        if let Some(peeled) = args.remove("peeled") {
45            res.peeled.replace(peeled.to_owned());
46        }
47
48        if let Some(value) = args.remove("symref-target") {
49            res.symref_target.replace(value.to_owned());
50        }
51
52        assert!(args.is_empty(), "unparsed args: {args:?}");
53
54        Ok(res)
55    }
56}