gix_object/tag/
ref_iter.rs1use bstr::BStr;
2use gix_hash::{oid, ObjectId};
3
4use crate::{bstr::ByteSlice, tag::decode, Kind, TagRefIter};
5
6#[derive(Default, Copy, Clone)]
7pub(crate) enum State {
8 #[default]
9 Target,
10 TargetKind,
11 Name,
12 Tagger,
13 Message,
14}
15
16impl<'a> TagRefIter<'a> {
17 pub fn from_bytes(data: &'a [u8], hash_kind: gix_hash::Kind) -> TagRefIter<'a> {
19 TagRefIter {
20 data,
21 state: State::default(),
22 hash_kind,
23 }
24 }
25
26 pub fn target_id(mut self) -> Result<ObjectId, crate::decode::Error> {
34 let token = self.next().ok_or_else(missing_field)??;
35 Token::into_id(token).ok_or_else(missing_field)
36 }
37
38 pub fn tagger(mut self) -> Result<Option<gix_actor::SignatureRef<'a>>, crate::decode::Error> {
41 self.find_map(|t| match t {
42 Ok(Token::Tagger(signature)) => Some(Ok(signature)),
43 Err(err) => Some(Err(err)),
44 _ => None,
45 })
46 .ok_or_else(missing_field)?
47 }
48}
49
50fn missing_field() -> crate::decode::Error {
51 crate::decode::empty_error()
52}
53
54impl<'a> TagRefIter<'a> {
55 #[inline]
56 fn next_inner(
57 mut i: &'a [u8],
58 state: &mut State,
59 hash_kind: gix_hash::Kind,
60 ) -> Result<(&'a [u8], Token<'a>), crate::decode::Error> {
61 let input = &mut i;
62 match Self::next_inner_(input, state, hash_kind) {
63 Ok(token) => Ok((*input, token)),
64 Err(err) => Err(err),
65 }
66 }
67
68 fn next_inner_(
69 input: &mut &'a [u8],
70 state: &mut State,
71 hash_kind: gix_hash::Kind,
72 ) -> Result<Token<'a>, crate::decode::Error> {
73 use State::*;
74 Ok(match state {
75 Target => {
76 let target = decode::target(input, hash_kind)?;
77 *state = TargetKind;
78 Token::Target {
79 id: ObjectId::from_hex(target).expect("parsing validation"),
80 }
81 }
82 TargetKind => {
83 let kind = decode::kind(input)?;
84 *state = Name;
85 Token::TargetKind(kind)
86 }
87 Name => {
88 let tag_version = decode::name(input)?;
89 *state = Tagger;
90 Token::Name(tag_version.as_bstr())
91 }
92 Tagger => {
93 *state = Message;
94 let signature = decode::tagger(input)?;
95 Token::Tagger(signature)
96 }
97 Message => {
98 let (message, pgp_signature) = decode::message(input)?;
99 debug_assert!(
100 input.is_empty(),
101 "we should have consumed all data - otherwise iter may go forever"
102 );
103 Token::Body { message, pgp_signature }
104 }
105 })
106 }
107}
108
109impl<'a> Iterator for TagRefIter<'a> {
110 type Item = Result<Token<'a>, crate::decode::Error>;
111
112 fn next(&mut self) -> Option<Self::Item> {
113 if self.data.is_empty() {
114 return None;
115 }
116 match Self::next_inner(self.data, &mut self.state, self.hash_kind) {
117 Ok((data, token)) => {
118 self.data = data;
119 Some(Ok(token))
120 }
121 Err(err) => {
122 self.data = &[];
123 Some(Err(err))
124 }
125 }
126 }
127}
128
129#[allow(missing_docs)]
131#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
132pub enum Token<'a> {
133 Target {
134 id: ObjectId,
135 },
136 TargetKind(Kind),
137 Name(&'a BStr),
138 Tagger(Option<gix_actor::SignatureRef<'a>>),
139 Body {
140 message: &'a BStr,
141 pgp_signature: Option<&'a BStr>,
142 },
143}
144
145impl Token<'_> {
146 pub fn id(&self) -> Option<&oid> {
148 match self {
149 Token::Target { id } => Some(id.as_ref()),
150 _ => None,
151 }
152 }
153
154 pub fn into_id(self) -> Option<ObjectId> {
156 match self {
157 Token::Target { id } => Some(id),
158 _ => None,
159 }
160 }
161}