git_ref/store/file/loose/reference/
decode.rs1use std::convert::{TryFrom, TryInto};
2
3use git_hash::ObjectId;
4use git_object::bstr::BString;
5use nom::{
6 bytes::complete::{tag, take_while},
7 combinator::{map, opt},
8 sequence::terminated,
9 IResult,
10};
11
12use crate::{
13 parse::{hex_hash, newline},
14 store_impl::file::loose::Reference,
15 FullName, Target,
16};
17
18enum MaybeUnsafeState {
19 Id(ObjectId),
20 UnvalidatedPath(BString),
21}
22
23#[derive(Debug, thiserror::Error)]
25#[allow(missing_docs)]
26pub enum Error {
27 #[error("{content:?} could not be parsed")]
28 Parse { content: BString },
29 #[error("The path {path:?} to a symbolic reference within a ref file is invalid")]
30 RefnameValidation {
31 source: git_validate::reference::name::Error,
32 path: BString,
33 },
34}
35
36impl TryFrom<MaybeUnsafeState> for Target {
37 type Error = Error;
38
39 fn try_from(v: MaybeUnsafeState) -> Result<Self, Self::Error> {
40 Ok(match v {
41 MaybeUnsafeState::Id(id) => Target::Peeled(id),
42 MaybeUnsafeState::UnvalidatedPath(name) => Target::Symbolic(match git_validate::refname(name.as_ref()) {
43 Ok(_) => FullName(name),
44 Err(err) => {
45 return Err(Error::RefnameValidation {
46 source: err,
47 path: name,
48 })
49 }
50 }),
51 })
52 }
53}
54
55impl Reference {
56 pub fn try_from_path(name: FullName, path_contents: &[u8]) -> Result<Self, Error> {
59 Ok(Reference {
60 name,
61 target: parse(path_contents)
62 .map_err(|_| Error::Parse {
63 content: path_contents.into(),
64 })?
65 .1
66 .try_into()?,
67 })
68 }
69}
70
71fn parse(bytes: &[u8]) -> IResult<&[u8], MaybeUnsafeState> {
72 let is_space = |b: u8| b == b' ';
73 if let (path, Some(_ref_prefix)) = opt(terminated(tag("ref: "), take_while(is_space)))(bytes)? {
74 map(
75 terminated(take_while(|b| b != b'\r' && b != b'\n'), opt(newline)),
76 |path| MaybeUnsafeState::UnvalidatedPath(path.into()),
77 )(path)
78 } else {
79 map(terminated(hex_hash, opt(newline)), |hex| {
80 MaybeUnsafeState::Id(ObjectId::from_hex(hex).expect("prior validation"))
81 })(bytes)
82 }
83}