Coverage Report

Created: 2026-02-14 07:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gitoxide/gix-revision/src/spec/parse/function.rs
Line
Count
Source
1
use std::{str::FromStr, time::SystemTime};
2
3
use crate::{
4
    spec,
5
    spec::parse::{delegate, delegate::SiblingBranch, Delegate, Error},
6
};
7
use bstr::{BStr, BString, ByteSlice, ByteVec};
8
use gix_error::{ErrorExt, Exn, ResultExt};
9
10
/// Parse a git [`revspec`](https://git-scm.com/docs/git-rev-parse#_specifying_revisions) and call `delegate` for each token
11
/// successfully parsed.
12
///
13
/// Note that the `delegate` is expected to maintain enough state to lookup revisions properly.
14
/// Returns `Ok(())` if all of `input` was consumed, or the error if either the `revspec` syntax was incorrect or
15
/// the `delegate` failed to perform the request.
16
18.3k
pub fn parse(mut input: &BStr, delegate: &mut impl Delegate) -> Result<(), Exn<Error>> {
17
    use delegate::{Kind, Revision};
18
18.3k
    let mut delegate = InterceptRev::new(delegate);
19
18.3k
    let mut prev_kind = None;
20
18.3k
    if let Some(b'^') = input.first() {
21
114
        input = next(input).1;
22
114
        let kind = spec::Kind::ExcludeReachable;
23
114
        delegate
24
114
            .kind(kind)
25
114
            .or_raise(|| Error::new(format!("delegate.kind({kind:?}) failed")))?;
Unexecuted instantiation: gix_revision::spec::parse::function::parse::<gix_refspec::parse::revparse::Noop>::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::parse::<_>::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::parse::<_>::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::parse::<parse::Noop>::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::parse::<_>::{closure#0}
26
114
        prev_kind = kind.into();
27
18.2k
    }
28
29
    let mut found_revision;
30
6.59k
    (input, found_revision) = {
31
18.3k
        let rest = revision(input, &mut delegate)?;
32
6.59k
        (rest, rest != input)
33
    };
34
6.59k
    if delegate.done {
35
611
        return if input.is_empty() {
36
350
            Ok(())
37
        } else {
38
261
            Err(Error::new_with_input("unconsumed input", input).raise())
39
        };
40
5.98k
    }
41
5.98k
    if let Some((rest, kind)) = try_range(input) {
42
1.46k
        if let Some(prev_kind) = prev_kind {
43
3
            return Err(Error::new(format!(
44
3
                "cannot set spec kind more than once (was {prev_kind:?}, now {kind:?})"
45
3
            ))
46
3
            .raise());
47
1.45k
        }
48
1.45k
        if !found_revision {
49
82
            delegate
50
82
                .find_ref("HEAD".into())
51
82
                .or_raise(|| Error::new("delegate did not find the HEAD reference"))?;
Unexecuted instantiation: gix_revision::spec::parse::function::parse::<gix_refspec::parse::revparse::Noop>::{closure#1}
Unexecuted instantiation: gix_revision::spec::parse::function::parse::<_>::{closure#1}
Unexecuted instantiation: gix_revision::spec::parse::function::parse::<_>::{closure#1}
Unexecuted instantiation: gix_revision::spec::parse::function::parse::<parse::Noop>::{closure#1}
Unexecuted instantiation: gix_revision::spec::parse::function::parse::<_>::{closure#1}
52
1.37k
        }
53
1.45k
        delegate
54
1.45k
            .kind(kind)
55
1.45k
            .or_raise(|| Error::new(format!("delegate.kind({kind:?}) failed")))?;
Unexecuted instantiation: gix_revision::spec::parse::function::parse::<gix_refspec::parse::revparse::Noop>::{closure#2}
Unexecuted instantiation: gix_revision::spec::parse::function::parse::<_>::{closure#2}
Unexecuted instantiation: gix_revision::spec::parse::function::parse::<_>::{closure#2}
Unexecuted instantiation: gix_revision::spec::parse::function::parse::<parse::Noop>::{closure#2}
Unexecuted instantiation: gix_revision::spec::parse::function::parse::<_>::{closure#2}
56
591
        (input, found_revision) = {
57
1.45k
            let remainder = revision(rest.as_bstr(), &mut delegate)?;
58
591
            (remainder, remainder != rest)
59
        };
60
591
        if !found_revision {
61
25
            delegate
62
25
                .find_ref("HEAD".into())
63
25
                .or_raise(|| Error::new("delegate did not find the HEAD reference"))?;
Unexecuted instantiation: gix_revision::spec::parse::function::parse::<gix_refspec::parse::revparse::Noop>::{closure#3}
Unexecuted instantiation: gix_revision::spec::parse::function::parse::<_>::{closure#3}
Unexecuted instantiation: gix_revision::spec::parse::function::parse::<_>::{closure#3}
Unexecuted instantiation: gix_revision::spec::parse::function::parse::<parse::Noop>::{closure#3}
Unexecuted instantiation: gix_revision::spec::parse::function::parse::<_>::{closure#3}
64
566
        }
65
4.52k
    }
66
67
5.11k
    if input.is_empty() {
68
4.44k
        delegate
69
4.44k
            .done()
70
4.44k
            .or_raise(|| Error::new("No revision was produced after all input was consumed"))
Unexecuted instantiation: gix_revision::spec::parse::function::parse::<gix_refspec::parse::revparse::Noop>::{closure#4}
Unexecuted instantiation: gix_revision::spec::parse::function::parse::<_>::{closure#4}
Unexecuted instantiation: gix_revision::spec::parse::function::parse::<_>::{closure#4}
Unexecuted instantiation: gix_revision::spec::parse::function::parse::<parse::Noop>::{closure#4}
Unexecuted instantiation: gix_revision::spec::parse::function::parse::<_>::{closure#4}
71
    } else {
72
662
        Err(Error::new_with_input("unconsumed input", input).raise())
73
    }
74
18.3k
}
gix_revision::spec::parse::function::parse::<gix_refspec::parse::revparse::Noop>
Line
Count
Source
16
8.38k
pub fn parse(mut input: &BStr, delegate: &mut impl Delegate) -> Result<(), Exn<Error>> {
17
    use delegate::{Kind, Revision};
18
8.38k
    let mut delegate = InterceptRev::new(delegate);
19
8.38k
    let mut prev_kind = None;
20
8.38k
    if let Some(b'^') = input.first() {
21
14
        input = next(input).1;
22
14
        let kind = spec::Kind::ExcludeReachable;
23
14
        delegate
24
14
            .kind(kind)
25
14
            .or_raise(|| Error::new(format!("delegate.kind({kind:?}) failed")))?;
26
14
        prev_kind = kind.into();
27
8.37k
    }
28
29
    let mut found_revision;
30
3.03k
    (input, found_revision) = {
31
8.38k
        let rest = revision(input, &mut delegate)?;
32
3.03k
        (rest, rest != input)
33
    };
34
3.03k
    if delegate.done {
35
322
        return if input.is_empty() {
36
175
            Ok(())
37
        } else {
38
147
            Err(Error::new_with_input("unconsumed input", input).raise())
39
        };
40
2.71k
    }
41
2.71k
    if let Some((rest, kind)) = try_range(input) {
42
574
        if let Some(prev_kind) = prev_kind {
43
2
            return Err(Error::new(format!(
44
2
                "cannot set spec kind more than once (was {prev_kind:?}, now {kind:?})"
45
2
            ))
46
2
            .raise());
47
572
        }
48
572
        if !found_revision {
49
42
            delegate
50
42
                .find_ref("HEAD".into())
51
42
                .or_raise(|| Error::new("delegate did not find the HEAD reference"))?;
52
530
        }
53
572
        delegate
54
572
            .kind(kind)
55
572
            .or_raise(|| Error::new(format!("delegate.kind({kind:?}) failed")))?;
56
261
        (input, found_revision) = {
57
572
            let remainder = revision(rest.as_bstr(), &mut delegate)?;
58
261
            (remainder, remainder != rest)
59
        };
60
261
        if !found_revision {
61
14
            delegate
62
14
                .find_ref("HEAD".into())
63
14
                .or_raise(|| Error::new("delegate did not find the HEAD reference"))?;
64
247
        }
65
2.14k
    }
66
67
2.40k
    if input.is_empty() {
68
2.09k
        delegate
69
2.09k
            .done()
70
2.09k
            .or_raise(|| Error::new("No revision was produced after all input was consumed"))
71
    } else {
72
308
        Err(Error::new_with_input("unconsumed input", input).raise())
73
    }
74
8.38k
}
Unexecuted instantiation: gix_revision::spec::parse::function::parse::<_>
Unexecuted instantiation: gix_revision::spec::parse::function::parse::<_>
gix_revision::spec::parse::function::parse::<parse::Noop>
Line
Count
Source
16
9.98k
pub fn parse(mut input: &BStr, delegate: &mut impl Delegate) -> Result<(), Exn<Error>> {
17
    use delegate::{Kind, Revision};
18
9.98k
    let mut delegate = InterceptRev::new(delegate);
19
9.98k
    let mut prev_kind = None;
20
9.98k
    if let Some(b'^') = input.first() {
21
100
        input = next(input).1;
22
100
        let kind = spec::Kind::ExcludeReachable;
23
100
        delegate
24
100
            .kind(kind)
25
100
            .or_raise(|| Error::new(format!("delegate.kind({kind:?}) failed")))?;
26
100
        prev_kind = kind.into();
27
9.88k
    }
28
29
    let mut found_revision;
30
3.55k
    (input, found_revision) = {
31
9.98k
        let rest = revision(input, &mut delegate)?;
32
3.55k
        (rest, rest != input)
33
    };
34
3.55k
    if delegate.done {
35
289
        return if input.is_empty() {
36
175
            Ok(())
37
        } else {
38
114
            Err(Error::new_with_input("unconsumed input", input).raise())
39
        };
40
3.26k
    }
41
3.26k
    if let Some((rest, kind)) = try_range(input) {
42
888
        if let Some(prev_kind) = prev_kind {
43
1
            return Err(Error::new(format!(
44
1
                "cannot set spec kind more than once (was {prev_kind:?}, now {kind:?})"
45
1
            ))
46
1
            .raise());
47
887
        }
48
887
        if !found_revision {
49
40
            delegate
50
40
                .find_ref("HEAD".into())
51
40
                .or_raise(|| Error::new("delegate did not find the HEAD reference"))?;
52
847
        }
53
887
        delegate
54
887
            .kind(kind)
55
887
            .or_raise(|| Error::new(format!("delegate.kind({kind:?}) failed")))?;
56
330
        (input, found_revision) = {
57
887
            let remainder = revision(rest.as_bstr(), &mut delegate)?;
58
330
            (remainder, remainder != rest)
59
        };
60
330
        if !found_revision {
61
11
            delegate
62
11
                .find_ref("HEAD".into())
63
11
                .or_raise(|| Error::new("delegate did not find the HEAD reference"))?;
64
319
        }
65
2.37k
    }
66
67
2.70k
    if input.is_empty() {
68
2.35k
        delegate
69
2.35k
            .done()
70
2.35k
            .or_raise(|| Error::new("No revision was produced after all input was consumed"))
71
    } else {
72
354
        Err(Error::new_with_input("unconsumed input", input).raise())
73
    }
74
9.98k
}
Unexecuted instantiation: gix_revision::spec::parse::function::parse::<_>
75
76
mod intercept {
77
    use crate::spec::parse::{delegate, Delegate};
78
    use bstr::{BStr, BString};
79
    use gix_error::Exn;
80
81
    #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
82
    pub(crate) enum PrefixHintOwned {
83
        MustBeCommit,
84
        DescribeAnchor { ref_name: BString, generation: usize },
85
    }
86
87
    impl PrefixHintOwned {
88
164
        pub fn to_ref(&self) -> delegate::PrefixHint<'_> {
89
164
            match self {
90
9
                PrefixHintOwned::MustBeCommit => delegate::PrefixHint::MustBeCommit,
91
155
                PrefixHintOwned::DescribeAnchor { ref_name, generation } => delegate::PrefixHint::DescribeAnchor {
92
155
                    ref_name: ref_name.as_ref(),
93
155
                    generation: *generation,
94
155
                },
95
            }
96
164
        }
<gix_revision::spec::parse::function::intercept::PrefixHintOwned>::to_ref
Line
Count
Source
88
85
        pub fn to_ref(&self) -> delegate::PrefixHint<'_> {
89
85
            match self {
90
4
                PrefixHintOwned::MustBeCommit => delegate::PrefixHint::MustBeCommit,
91
81
                PrefixHintOwned::DescribeAnchor { ref_name, generation } => delegate::PrefixHint::DescribeAnchor {
92
81
                    ref_name: ref_name.as_ref(),
93
81
                    generation: *generation,
94
81
                },
95
            }
96
85
        }
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::PrefixHintOwned>::to_ref
<gix_revision::spec::parse::function::intercept::PrefixHintOwned>::to_ref
Line
Count
Source
88
79
        pub fn to_ref(&self) -> delegate::PrefixHint<'_> {
89
79
            match self {
90
5
                PrefixHintOwned::MustBeCommit => delegate::PrefixHint::MustBeCommit,
91
74
                PrefixHintOwned::DescribeAnchor { ref_name, generation } => delegate::PrefixHint::DescribeAnchor {
92
74
                    ref_name: ref_name.as_ref(),
93
74
                    generation: *generation,
94
74
                },
95
            }
96
79
        }
97
    }
98
99
    impl<'a> From<delegate::PrefixHint<'a>> for PrefixHintOwned {
100
572
        fn from(v: delegate::PrefixHint<'a>) -> Self {
101
572
            match v {
102
60
                delegate::PrefixHint::MustBeCommit => PrefixHintOwned::MustBeCommit,
103
512
                delegate::PrefixHint::DescribeAnchor { generation, ref_name } => PrefixHintOwned::DescribeAnchor {
104
512
                    ref_name: ref_name.to_owned(),
105
512
                    generation,
106
512
                },
107
            }
108
572
        }
<gix_revision::spec::parse::function::intercept::PrefixHintOwned as core::convert::From<gix_revision::spec::parse::delegate::PrefixHint>>::from
Line
Count
Source
100
280
        fn from(v: delegate::PrefixHint<'a>) -> Self {
101
280
            match v {
102
27
                delegate::PrefixHint::MustBeCommit => PrefixHintOwned::MustBeCommit,
103
253
                delegate::PrefixHint::DescribeAnchor { generation, ref_name } => PrefixHintOwned::DescribeAnchor {
104
253
                    ref_name: ref_name.to_owned(),
105
253
                    generation,
106
253
                },
107
            }
108
280
        }
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::PrefixHintOwned as core::convert::From<gix_revision::spec::parse::delegate::PrefixHint>>::from
<gix_revision::spec::parse::function::intercept::PrefixHintOwned as core::convert::From<gix_revision::spec::parse::delegate::PrefixHint>>::from
Line
Count
Source
100
292
        fn from(v: delegate::PrefixHint<'a>) -> Self {
101
292
            match v {
102
33
                delegate::PrefixHint::MustBeCommit => PrefixHintOwned::MustBeCommit,
103
259
                delegate::PrefixHint::DescribeAnchor { generation, ref_name } => PrefixHintOwned::DescribeAnchor {
104
259
                    ref_name: ref_name.to_owned(),
105
259
                    generation,
106
259
                },
107
            }
108
292
        }
109
    }
110
111
    pub(crate) struct InterceptRev<'a, T> {
112
        pub inner: &'a mut T,
113
        pub last_ref: Option<BString>, // TODO: smallvec to save the unnecessary allocation? Can't keep ref due to lifetime constraints in traits
114
        pub last_prefix: Option<(gix_hash::Prefix, Option<PrefixHintOwned>)>,
115
        pub done: bool,
116
    }
117
118
    impl<'a, T> InterceptRev<'a, T>
119
    where
120
        T: Delegate,
121
    {
122
18.3k
        pub fn new(delegate: &'a mut T) -> Self {
123
18.3k
            InterceptRev {
124
18.3k
                inner: delegate,
125
18.3k
                last_ref: None,
126
18.3k
                last_prefix: None,
127
18.3k
                done: false,
128
18.3k
            }
129
18.3k
        }
<gix_revision::spec::parse::function::intercept::InterceptRev<gix_refspec::parse::revparse::Noop>>::new
Line
Count
Source
122
8.38k
        pub fn new(delegate: &'a mut T) -> Self {
123
8.38k
            InterceptRev {
124
8.38k
                inner: delegate,
125
8.38k
                last_ref: None,
126
8.38k
                last_prefix: None,
127
8.38k
                done: false,
128
8.38k
            }
129
8.38k
        }
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_>>::new
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_>>::new
<gix_revision::spec::parse::function::intercept::InterceptRev<parse::Noop>>::new
Line
Count
Source
122
9.98k
        pub fn new(delegate: &'a mut T) -> Self {
123
9.98k
            InterceptRev {
124
9.98k
                inner: delegate,
125
9.98k
                last_ref: None,
126
9.98k
                last_prefix: None,
127
9.98k
                done: false,
128
9.98k
            }
129
9.98k
        }
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_>>::new
130
    }
131
132
    impl<T> Delegate for InterceptRev<'_, T>
133
    where
134
        T: Delegate,
135
    {
136
5.09k
        fn done(&mut self) -> Result<(), Exn> {
137
5.09k
            self.done = true;
138
5.09k
            self.inner.done()
139
5.09k
        }
<gix_revision::spec::parse::function::intercept::InterceptRev<gix_refspec::parse::revparse::Noop> as gix_revision::spec::parse::Delegate>::done
Line
Count
Source
136
2.43k
        fn done(&mut self) -> Result<(), Exn> {
137
2.43k
            self.done = true;
138
2.43k
            self.inner.done()
139
2.43k
        }
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_> as gix_revision::spec::parse::Delegate>::done
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_> as gix_revision::spec::parse::Delegate>::done
<gix_revision::spec::parse::function::intercept::InterceptRev<parse::Noop> as gix_revision::spec::parse::Delegate>::done
Line
Count
Source
136
2.65k
        fn done(&mut self) -> Result<(), Exn> {
137
2.65k
            self.done = true;
138
2.65k
            self.inner.done()
139
2.65k
        }
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_> as gix_revision::spec::parse::Delegate>::done
140
    }
141
142
    impl<T> delegate::Revision for InterceptRev<'_, T>
143
    where
144
        T: Delegate,
145
    {
146
6.12k
        fn find_ref(&mut self, name: &BStr) -> Result<(), Exn> {
147
6.12k
            self.last_ref = name.to_owned().into();
148
6.12k
            self.inner.find_ref(name)
149
6.12k
        }
<gix_revision::spec::parse::function::intercept::InterceptRev<gix_refspec::parse::revparse::Noop> as gix_revision::spec::parse::delegate::Revision>::find_ref
Line
Count
Source
146
3.13k
        fn find_ref(&mut self, name: &BStr) -> Result<(), Exn> {
147
3.13k
            self.last_ref = name.to_owned().into();
148
3.13k
            self.inner.find_ref(name)
149
3.13k
        }
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_> as gix_revision::spec::parse::delegate::Revision>::find_ref
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_> as gix_revision::spec::parse::delegate::Revision>::find_ref
<gix_revision::spec::parse::function::intercept::InterceptRev<parse::Noop> as gix_revision::spec::parse::delegate::Revision>::find_ref
Line
Count
Source
146
2.99k
        fn find_ref(&mut self, name: &BStr) -> Result<(), Exn> {
147
2.99k
            self.last_ref = name.to_owned().into();
148
2.99k
            self.inner.find_ref(name)
149
2.99k
        }
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_> as gix_revision::spec::parse::delegate::Revision>::find_ref
150
151
797
        fn disambiguate_prefix(
152
797
            &mut self,
153
797
            prefix: gix_hash::Prefix,
154
797
            hint: Option<delegate::PrefixHint<'_>>,
155
797
        ) -> Result<(), Exn> {
156
797
            self.last_prefix = Some((prefix, hint.map(Into::into)));
157
797
            self.inner.disambiguate_prefix(prefix, hint)
158
797
        }
<gix_revision::spec::parse::function::intercept::InterceptRev<gix_refspec::parse::revparse::Noop> as gix_revision::spec::parse::delegate::Revision>::disambiguate_prefix
Line
Count
Source
151
397
        fn disambiguate_prefix(
152
397
            &mut self,
153
397
            prefix: gix_hash::Prefix,
154
397
            hint: Option<delegate::PrefixHint<'_>>,
155
397
        ) -> Result<(), Exn> {
156
397
            self.last_prefix = Some((prefix, hint.map(Into::into)));
157
397
            self.inner.disambiguate_prefix(prefix, hint)
158
397
        }
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_> as gix_revision::spec::parse::delegate::Revision>::disambiguate_prefix
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_> as gix_revision::spec::parse::delegate::Revision>::disambiguate_prefix
<gix_revision::spec::parse::function::intercept::InterceptRev<parse::Noop> as gix_revision::spec::parse::delegate::Revision>::disambiguate_prefix
Line
Count
Source
151
400
        fn disambiguate_prefix(
152
400
            &mut self,
153
400
            prefix: gix_hash::Prefix,
154
400
            hint: Option<delegate::PrefixHint<'_>>,
155
400
        ) -> Result<(), Exn> {
156
400
            self.last_prefix = Some((prefix, hint.map(Into::into)));
157
400
            self.inner.disambiguate_prefix(prefix, hint)
158
400
        }
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_> as gix_revision::spec::parse::delegate::Revision>::disambiguate_prefix
159
160
2.88k
        fn reflog(&mut self, query: delegate::ReflogLookup) -> Result<(), Exn> {
161
2.88k
            self.inner.reflog(query)
162
2.88k
        }
<gix_revision::spec::parse::function::intercept::InterceptRev<gix_refspec::parse::revparse::Noop> as gix_revision::spec::parse::delegate::Revision>::reflog
Line
Count
Source
160
1.09k
        fn reflog(&mut self, query: delegate::ReflogLookup) -> Result<(), Exn> {
161
1.09k
            self.inner.reflog(query)
162
1.09k
        }
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_> as gix_revision::spec::parse::delegate::Revision>::reflog
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_> as gix_revision::spec::parse::delegate::Revision>::reflog
<gix_revision::spec::parse::function::intercept::InterceptRev<parse::Noop> as gix_revision::spec::parse::delegate::Revision>::reflog
Line
Count
Source
160
1.79k
        fn reflog(&mut self, query: delegate::ReflogLookup) -> Result<(), Exn> {
161
1.79k
            self.inner.reflog(query)
162
1.79k
        }
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_> as gix_revision::spec::parse::delegate::Revision>::reflog
163
164
169
        fn nth_checked_out_branch(&mut self, branch_no: usize) -> Result<(), Exn> {
165
169
            self.inner.nth_checked_out_branch(branch_no)
166
169
        }
<gix_revision::spec::parse::function::intercept::InterceptRev<gix_refspec::parse::revparse::Noop> as gix_revision::spec::parse::delegate::Revision>::nth_checked_out_branch
Line
Count
Source
164
85
        fn nth_checked_out_branch(&mut self, branch_no: usize) -> Result<(), Exn> {
165
85
            self.inner.nth_checked_out_branch(branch_no)
166
85
        }
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_> as gix_revision::spec::parse::delegate::Revision>::nth_checked_out_branch
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_> as gix_revision::spec::parse::delegate::Revision>::nth_checked_out_branch
<gix_revision::spec::parse::function::intercept::InterceptRev<parse::Noop> as gix_revision::spec::parse::delegate::Revision>::nth_checked_out_branch
Line
Count
Source
164
84
        fn nth_checked_out_branch(&mut self, branch_no: usize) -> Result<(), Exn> {
165
84
            self.inner.nth_checked_out_branch(branch_no)
166
84
        }
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_> as gix_revision::spec::parse::delegate::Revision>::nth_checked_out_branch
167
168
20
        fn sibling_branch(&mut self, kind: delegate::SiblingBranch) -> Result<(), Exn> {
169
20
            self.inner.sibling_branch(kind)
170
20
        }
<gix_revision::spec::parse::function::intercept::InterceptRev<gix_refspec::parse::revparse::Noop> as gix_revision::spec::parse::delegate::Revision>::sibling_branch
Line
Count
Source
168
10
        fn sibling_branch(&mut self, kind: delegate::SiblingBranch) -> Result<(), Exn> {
169
10
            self.inner.sibling_branch(kind)
170
10
        }
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_> as gix_revision::spec::parse::delegate::Revision>::sibling_branch
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_> as gix_revision::spec::parse::delegate::Revision>::sibling_branch
<gix_revision::spec::parse::function::intercept::InterceptRev<parse::Noop> as gix_revision::spec::parse::delegate::Revision>::sibling_branch
Line
Count
Source
168
10
        fn sibling_branch(&mut self, kind: delegate::SiblingBranch) -> Result<(), Exn> {
169
10
            self.inner.sibling_branch(kind)
170
10
        }
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_> as gix_revision::spec::parse::delegate::Revision>::sibling_branch
171
    }
172
173
    impl<T> delegate::Navigate for InterceptRev<'_, T>
174
    where
175
        T: Delegate,
176
    {
177
45.9k
        fn traverse(&mut self, kind: delegate::Traversal) -> Result<(), Exn> {
178
45.9k
            self.inner.traverse(kind)
179
45.9k
        }
<gix_revision::spec::parse::function::intercept::InterceptRev<gix_refspec::parse::revparse::Noop> as gix_revision::spec::parse::delegate::Navigate>::traverse
Line
Count
Source
177
14.4k
        fn traverse(&mut self, kind: delegate::Traversal) -> Result<(), Exn> {
178
14.4k
            self.inner.traverse(kind)
179
14.4k
        }
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_> as gix_revision::spec::parse::delegate::Navigate>::traverse
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_> as gix_revision::spec::parse::delegate::Navigate>::traverse
<gix_revision::spec::parse::function::intercept::InterceptRev<parse::Noop> as gix_revision::spec::parse::delegate::Navigate>::traverse
Line
Count
Source
177
31.5k
        fn traverse(&mut self, kind: delegate::Traversal) -> Result<(), Exn> {
178
31.5k
            self.inner.traverse(kind)
179
31.5k
        }
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_> as gix_revision::spec::parse::delegate::Navigate>::traverse
180
181
5.75k
        fn peel_until(&mut self, kind: delegate::PeelTo<'_>) -> Result<(), Exn> {
182
5.75k
            self.inner.peel_until(kind)
183
5.75k
        }
<gix_revision::spec::parse::function::intercept::InterceptRev<gix_refspec::parse::revparse::Noop> as gix_revision::spec::parse::delegate::Navigate>::peel_until
Line
Count
Source
181
2.70k
        fn peel_until(&mut self, kind: delegate::PeelTo<'_>) -> Result<(), Exn> {
182
2.70k
            self.inner.peel_until(kind)
183
2.70k
        }
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_> as gix_revision::spec::parse::delegate::Navigate>::peel_until
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_> as gix_revision::spec::parse::delegate::Navigate>::peel_until
<gix_revision::spec::parse::function::intercept::InterceptRev<parse::Noop> as gix_revision::spec::parse::delegate::Navigate>::peel_until
Line
Count
Source
181
3.04k
        fn peel_until(&mut self, kind: delegate::PeelTo<'_>) -> Result<(), Exn> {
182
3.04k
            self.inner.peel_until(kind)
183
3.04k
        }
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_> as gix_revision::spec::parse::delegate::Navigate>::peel_until
184
185
4.27k
        fn find(&mut self, regex: &BStr, negated: bool) -> Result<(), Exn> {
186
4.27k
            self.inner.find(regex, negated)
187
4.27k
        }
<gix_revision::spec::parse::function::intercept::InterceptRev<gix_refspec::parse::revparse::Noop> as gix_revision::spec::parse::delegate::Navigate>::find
Line
Count
Source
185
2.26k
        fn find(&mut self, regex: &BStr, negated: bool) -> Result<(), Exn> {
186
2.26k
            self.inner.find(regex, negated)
187
2.26k
        }
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_> as gix_revision::spec::parse::delegate::Navigate>::find
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_> as gix_revision::spec::parse::delegate::Navigate>::find
<gix_revision::spec::parse::function::intercept::InterceptRev<parse::Noop> as gix_revision::spec::parse::delegate::Navigate>::find
Line
Count
Source
185
2.01k
        fn find(&mut self, regex: &BStr, negated: bool) -> Result<(), Exn> {
186
2.01k
            self.inner.find(regex, negated)
187
2.01k
        }
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_> as gix_revision::spec::parse::delegate::Navigate>::find
188
189
61
        fn index_lookup(&mut self, path: &BStr, stage: u8) -> Result<(), Exn> {
190
61
            self.inner.index_lookup(path, stage)
191
61
        }
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<gix_refspec::parse::revparse::Noop> as gix_revision::spec::parse::delegate::Navigate>::index_lookup
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_> as gix_revision::spec::parse::delegate::Navigate>::index_lookup
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_> as gix_revision::spec::parse::delegate::Navigate>::index_lookup
<gix_revision::spec::parse::function::intercept::InterceptRev<parse::Noop> as gix_revision::spec::parse::delegate::Navigate>::index_lookup
Line
Count
Source
189
61
        fn index_lookup(&mut self, path: &BStr, stage: u8) -> Result<(), Exn> {
190
61
            self.inner.index_lookup(path, stage)
191
61
        }
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_> as gix_revision::spec::parse::delegate::Navigate>::index_lookup
192
    }
193
194
    impl<T> delegate::Kind for InterceptRev<'_, T>
195
    where
196
        T: Delegate,
197
    {
198
2.23k
        fn kind(&mut self, kind: crate::spec::Kind) -> Result<(), Exn> {
199
2.23k
            self.inner.kind(kind)
200
2.23k
        }
<gix_revision::spec::parse::function::intercept::InterceptRev<gix_refspec::parse::revparse::Noop> as gix_revision::spec::parse::delegate::Kind>::kind
Line
Count
Source
198
931
        fn kind(&mut self, kind: crate::spec::Kind) -> Result<(), Exn> {
199
931
            self.inner.kind(kind)
200
931
        }
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_> as gix_revision::spec::parse::delegate::Kind>::kind
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_> as gix_revision::spec::parse::delegate::Kind>::kind
<gix_revision::spec::parse::function::intercept::InterceptRev<parse::Noop> as gix_revision::spec::parse::delegate::Kind>::kind
Line
Count
Source
198
1.30k
        fn kind(&mut self, kind: crate::spec::Kind) -> Result<(), Exn> {
199
1.30k
            self.inner.kind(kind)
200
1.30k
        }
Unexecuted instantiation: <gix_revision::spec::parse::function::intercept::InterceptRev<_> as gix_revision::spec::parse::delegate::Kind>::kind
201
    }
202
}
203
use intercept::InterceptRev;
204
205
trait ResultExt2 {
206
    fn or_else_none<F>(self, f: F) -> Option<()>
207
    where
208
        F: FnOnce(Exn);
209
}
210
211
impl ResultExt2 for Result<(), Exn> {
212
6.02k
    fn or_else_none<F>(self, f: F) -> Option<()>
213
6.02k
    where
214
6.02k
        F: FnOnce(Exn),
215
    {
216
6.02k
        match self {
217
6.02k
            Ok(()) => Some(()),
218
0
            Err(err) => {
219
0
                f(err);
220
0
                None
221
            }
222
        }
223
6.02k
    }
<core::result::Result<(), gix_error::exn::Exn> as gix_revision::spec::parse::function::ResultExt2>::or_else_none::<gix_revision::spec::parse::function::try_set_prefix<gix_revision::spec::parse::function::intercept::InterceptRev<gix_refspec::parse::revparse::Noop>>::{closure#0}::{closure#0}>
Line
Count
Source
212
306
    fn or_else_none<F>(self, f: F) -> Option<()>
213
306
    where
214
306
        F: FnOnce(Exn),
215
    {
216
306
        match self {
217
306
            Ok(()) => Some(()),
218
0
            Err(err) => {
219
0
                f(err);
220
0
                None
221
            }
222
        }
223
306
    }
<core::result::Result<(), gix_error::exn::Exn> as gix_revision::spec::parse::function::ResultExt2>::or_else_none::<gix_revision::spec::parse::function::revision<gix_refspec::parse::revparse::Noop>::{closure#13}::{closure#0}::{closure#0}>
Line
Count
Source
212
2.77k
    fn or_else_none<F>(self, f: F) -> Option<()>
213
2.77k
    where
214
2.77k
        F: FnOnce(Exn),
215
    {
216
2.77k
        match self {
217
2.77k
            Ok(()) => Some(()),
218
0
            Err(err) => {
219
0
                f(err);
220
0
                None
221
            }
222
        }
223
2.77k
    }
Unexecuted instantiation: <core::result::Result<(), gix_error::exn::Exn> as gix_revision::spec::parse::function::ResultExt2>::or_else_none::<_>
Unexecuted instantiation: <core::result::Result<(), gix_error::exn::Exn> as gix_revision::spec::parse::function::ResultExt2>::or_else_none::<_>
<core::result::Result<(), gix_error::exn::Exn> as gix_revision::spec::parse::function::ResultExt2>::or_else_none::<gix_revision::spec::parse::function::try_set_prefix<gix_revision::spec::parse::function::intercept::InterceptRev<parse::Noop>>::{closure#0}::{closure#0}>
Line
Count
Source
212
317
    fn or_else_none<F>(self, f: F) -> Option<()>
213
317
    where
214
317
        F: FnOnce(Exn),
215
    {
216
317
        match self {
217
317
            Ok(()) => Some(()),
218
0
            Err(err) => {
219
0
                f(err);
220
0
                None
221
            }
222
        }
223
317
    }
<core::result::Result<(), gix_error::exn::Exn> as gix_revision::spec::parse::function::ResultExt2>::or_else_none::<gix_revision::spec::parse::function::revision<parse::Noop>::{closure#13}::{closure#0}::{closure#0}>
Line
Count
Source
212
2.62k
    fn or_else_none<F>(self, f: F) -> Option<()>
213
2.62k
    where
214
2.62k
        F: FnOnce(Exn),
215
    {
216
2.62k
        match self {
217
2.62k
            Ok(()) => Some(()),
218
0
            Err(err) => {
219
0
                f(err);
220
0
                None
221
            }
222
        }
223
2.62k
    }
Unexecuted instantiation: <core::result::Result<(), gix_error::exn::Exn> as gix_revision::spec::parse::function::ResultExt2>::or_else_none::<_>
224
}
225
226
1.56k
fn try_set_prefix(
227
1.56k
    delegate: &mut impl Delegate,
228
1.56k
    hex_name: &BStr,
229
1.56k
    hint: Option<delegate::PrefixHint<'_>>,
230
1.56k
    errors: &mut Vec<Exn>,
231
1.56k
) -> Option<()> {
232
1.56k
    gix_hash::Prefix::from_hex(hex_name.to_str().expect("hexadecimal only"))
233
1.56k
        .ok()
234
1.56k
        .and_then(|prefix| {
235
623
            delegate
236
623
                .disambiguate_prefix(prefix, hint)
237
623
                .or_else_none(|err| errors.push(err))
Unexecuted instantiation: gix_revision::spec::parse::function::try_set_prefix::<gix_revision::spec::parse::function::intercept::InterceptRev<gix_refspec::parse::revparse::Noop>>::{closure#0}::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::try_set_prefix::<_>::{closure#0}::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::try_set_prefix::<_>::{closure#0}::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::try_set_prefix::<gix_revision::spec::parse::function::intercept::InterceptRev<parse::Noop>>::{closure#0}::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::try_set_prefix::<_>::{closure#0}::{closure#0}
238
623
        })
gix_revision::spec::parse::function::try_set_prefix::<gix_revision::spec::parse::function::intercept::InterceptRev<gix_refspec::parse::revparse::Noop>>::{closure#0}
Line
Count
Source
234
306
        .and_then(|prefix| {
235
306
            delegate
236
306
                .disambiguate_prefix(prefix, hint)
237
306
                .or_else_none(|err| errors.push(err))
238
306
        })
Unexecuted instantiation: gix_revision::spec::parse::function::try_set_prefix::<_>::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::try_set_prefix::<_>::{closure#0}
gix_revision::spec::parse::function::try_set_prefix::<gix_revision::spec::parse::function::intercept::InterceptRev<parse::Noop>>::{closure#0}
Line
Count
Source
234
317
        .and_then(|prefix| {
235
317
            delegate
236
317
                .disambiguate_prefix(prefix, hint)
237
317
                .or_else_none(|err| errors.push(err))
238
317
        })
Unexecuted instantiation: gix_revision::spec::parse::function::try_set_prefix::<_>::{closure#0}
239
1.56k
}
gix_revision::spec::parse::function::try_set_prefix::<gix_revision::spec::parse::function::intercept::InterceptRev<gix_refspec::parse::revparse::Noop>>
Line
Count
Source
226
763
fn try_set_prefix(
227
763
    delegate: &mut impl Delegate,
228
763
    hex_name: &BStr,
229
763
    hint: Option<delegate::PrefixHint<'_>>,
230
763
    errors: &mut Vec<Exn>,
231
763
) -> Option<()> {
232
763
    gix_hash::Prefix::from_hex(hex_name.to_str().expect("hexadecimal only"))
233
763
        .ok()
234
763
        .and_then(|prefix| {
235
            delegate
236
                .disambiguate_prefix(prefix, hint)
237
                .or_else_none(|err| errors.push(err))
238
        })
239
763
}
Unexecuted instantiation: gix_revision::spec::parse::function::try_set_prefix::<_>
Unexecuted instantiation: gix_revision::spec::parse::function::try_set_prefix::<_>
gix_revision::spec::parse::function::try_set_prefix::<gix_revision::spec::parse::function::intercept::InterceptRev<parse::Noop>>
Line
Count
Source
226
797
fn try_set_prefix(
227
797
    delegate: &mut impl Delegate,
228
797
    hex_name: &BStr,
229
797
    hint: Option<delegate::PrefixHint<'_>>,
230
797
    errors: &mut Vec<Exn>,
231
797
) -> Option<()> {
232
797
    gix_hash::Prefix::from_hex(hex_name.to_str().expect("hexadecimal only"))
233
797
        .ok()
234
797
        .and_then(|prefix| {
235
            delegate
236
                .disambiguate_prefix(prefix, hint)
237
                .or_else_none(|err| errors.push(err))
238
        })
239
797
}
Unexecuted instantiation: gix_revision::spec::parse::function::try_set_prefix::<_>
240
241
19.2k
fn long_describe_prefix(name: &BStr) -> Option<(&BStr, delegate::PrefixHint<'_>)> {
242
70.1M
    let mut iter = name.rsplit(|b| *b == b'-');
gix_revision::spec::parse::function::long_describe_prefix::{closure#0}
Line
Count
Source
242
26.2M
    let mut iter = name.rsplit(|b| *b == b'-');
Unexecuted instantiation: gix_revision::spec::parse::function::long_describe_prefix::{closure#0}
gix_revision::spec::parse::function::long_describe_prefix::{closure#0}
Line
Count
Source
242
43.8M
    let mut iter = name.rsplit(|b| *b == b'-');
243
2.97M
    let candidate = iter.by_ref().find_map(|substr| {
244
2.97M
        if substr.first()? != &b'g' {
245
25.8k
            return None;
246
2.26k
        }
247
2.26k
        let rest = substr.get(1..)?;
248
2.26k
        rest.iter().all(u8::is_ascii_hexdigit).then(|| rest.as_bstr())
gix_revision::spec::parse::function::long_describe_prefix::{closure#1}::{closure#0}
Line
Count
Source
248
481
        rest.iter().all(u8::is_ascii_hexdigit).then(|| rest.as_bstr())
Unexecuted instantiation: gix_revision::spec::parse::function::long_describe_prefix::{closure#1}::{closure#0}
gix_revision::spec::parse::function::long_describe_prefix::{closure#1}::{closure#0}
Line
Count
Source
248
522
        rest.iter().all(u8::is_ascii_hexdigit).then(|| rest.as_bstr())
249
2.97M
    })?;
gix_revision::spec::parse::function::long_describe_prefix::{closure#1}
Line
Count
Source
243
1.47M
    let candidate = iter.by_ref().find_map(|substr| {
244
1.47M
        if substr.first()? != &b'g' {
245
18.9k
            return None;
246
736
        }
247
736
        let rest = substr.get(1..)?;
248
736
        rest.iter().all(u8::is_ascii_hexdigit).then(|| rest.as_bstr())
249
1.47M
    })?;
Unexecuted instantiation: gix_revision::spec::parse::function::long_describe_prefix::{closure#1}
gix_revision::spec::parse::function::long_describe_prefix::{closure#1}
Line
Count
Source
243
1.50M
    let candidate = iter.by_ref().find_map(|substr| {
244
1.50M
        if substr.first()? != &b'g' {
245
6.85k
            return None;
246
1.52k
        }
247
1.52k
        let rest = substr.get(1..)?;
248
1.52k
        rest.iter().all(u8::is_ascii_hexdigit).then(|| rest.as_bstr())
249
1.50M
    })?;
250
251
61.4k
    let candidate = iter.clone().any(|token| !token.is_empty()).then_some(candidate);
gix_revision::spec::parse::function::long_describe_prefix::{closure#2}
Line
Count
Source
251
60.1k
    let candidate = iter.clone().any(|token| !token.is_empty()).then_some(candidate);
Unexecuted instantiation: gix_revision::spec::parse::function::long_describe_prefix::{closure#2}
gix_revision::spec::parse::function::long_describe_prefix::{closure#2}
Line
Count
Source
251
1.32k
    let candidate = iter.clone().any(|token| !token.is_empty()).then_some(candidate);
252
1.00k
    let hint = iter
253
1.00k
        .next()
254
1.00k
        .and_then(|gen| gen.to_str().ok().and_then(|gen| usize::from_str(gen).ok()))
gix_revision::spec::parse::function::long_describe_prefix::{closure#3}
Line
Count
Source
254
467
        .and_then(|gen| gen.to_str().ok().and_then(|gen| usize::from_str(gen).ok()))
Unexecuted instantiation: gix_revision::spec::parse::function::long_describe_prefix::{closure#3}
gix_revision::spec::parse::function::long_describe_prefix::{closure#3}
Line
Count
Source
254
489
        .and_then(|gen| gen.to_str().ok().and_then(|gen| usize::from_str(gen).ok()))
gix_revision::spec::parse::function::long_describe_prefix::{closure#3}::{closure#0}
Line
Count
Source
254
375
        .and_then(|gen| gen.to_str().ok().and_then(|gen| usize::from_str(gen).ok()))
Unexecuted instantiation: gix_revision::spec::parse::function::long_describe_prefix::{closure#3}::{closure#0}
gix_revision::spec::parse::function::long_describe_prefix::{closure#3}::{closure#0}
Line
Count
Source
254
393
        .and_then(|gen| gen.to_str().ok().and_then(|gen| usize::from_str(gen).ok()))
255
1.00k
        .and_then(|generation| {
256
529
            iter.next().map(|token| {
257
488
                let last_token_len = token.len();
258
488
                let first_token_ptr = iter.next_back().map_or(token.as_ptr(), <[_]>::as_ptr);
259
                // SAFETY: both pointers are definitely part of the same object
260
                #[allow(unsafe_code)]
261
488
                let prior_tokens_len: usize = unsafe { token.as_ptr().offset_from(first_token_ptr) }
262
488
                    .try_into()
263
488
                    .expect("positive value");
264
488
                delegate::PrefixHint::DescribeAnchor {
265
488
                    ref_name: name[..prior_tokens_len + last_token_len].as_bstr(),
266
488
                    generation,
267
488
                }
268
488
            })
gix_revision::spec::parse::function::long_describe_prefix::{closure#4}::{closure#0}
Line
Count
Source
256
226
            iter.next().map(|token| {
257
226
                let last_token_len = token.len();
258
226
                let first_token_ptr = iter.next_back().map_or(token.as_ptr(), <[_]>::as_ptr);
259
                // SAFETY: both pointers are definitely part of the same object
260
                #[allow(unsafe_code)]
261
226
                let prior_tokens_len: usize = unsafe { token.as_ptr().offset_from(first_token_ptr) }
262
226
                    .try_into()
263
226
                    .expect("positive value");
264
226
                delegate::PrefixHint::DescribeAnchor {
265
226
                    ref_name: name[..prior_tokens_len + last_token_len].as_bstr(),
266
226
                    generation,
267
226
                }
268
226
            })
Unexecuted instantiation: gix_revision::spec::parse::function::long_describe_prefix::{closure#4}::{closure#0}
gix_revision::spec::parse::function::long_describe_prefix::{closure#4}::{closure#0}
Line
Count
Source
256
262
            iter.next().map(|token| {
257
262
                let last_token_len = token.len();
258
262
                let first_token_ptr = iter.next_back().map_or(token.as_ptr(), <[_]>::as_ptr);
259
                // SAFETY: both pointers are definitely part of the same object
260
                #[allow(unsafe_code)]
261
262
                let prior_tokens_len: usize = unsafe { token.as_ptr().offset_from(first_token_ptr) }
262
262
                    .try_into()
263
262
                    .expect("positive value");
264
262
                delegate::PrefixHint::DescribeAnchor {
265
262
                    ref_name: name[..prior_tokens_len + last_token_len].as_bstr(),
266
262
                    generation,
267
262
                }
268
262
            })
269
529
        })
gix_revision::spec::parse::function::long_describe_prefix::{closure#4}
Line
Count
Source
255
240
        .and_then(|generation| {
256
240
            iter.next().map(|token| {
257
                let last_token_len = token.len();
258
                let first_token_ptr = iter.next_back().map_or(token.as_ptr(), <[_]>::as_ptr);
259
                // SAFETY: both pointers are definitely part of the same object
260
                #[allow(unsafe_code)]
261
                let prior_tokens_len: usize = unsafe { token.as_ptr().offset_from(first_token_ptr) }
262
                    .try_into()
263
                    .expect("positive value");
264
                delegate::PrefixHint::DescribeAnchor {
265
                    ref_name: name[..prior_tokens_len + last_token_len].as_bstr(),
266
                    generation,
267
                }
268
            })
269
240
        })
Unexecuted instantiation: gix_revision::spec::parse::function::long_describe_prefix::{closure#4}
gix_revision::spec::parse::function::long_describe_prefix::{closure#4}
Line
Count
Source
255
289
        .and_then(|generation| {
256
289
            iter.next().map(|token| {
257
                let last_token_len = token.len();
258
                let first_token_ptr = iter.next_back().map_or(token.as_ptr(), <[_]>::as_ptr);
259
                // SAFETY: both pointers are definitely part of the same object
260
                #[allow(unsafe_code)]
261
                let prior_tokens_len: usize = unsafe { token.as_ptr().offset_from(first_token_ptr) }
262
                    .try_into()
263
                    .expect("positive value");
264
                delegate::PrefixHint::DescribeAnchor {
265
                    ref_name: name[..prior_tokens_len + last_token_len].as_bstr(),
266
                    generation,
267
                }
268
            })
269
289
        })
270
1.00k
        .unwrap_or(delegate::PrefixHint::MustBeCommit);
271
272
1.00k
    candidate.map(|c| (c, hint))
gix_revision::spec::parse::function::long_describe_prefix::{closure#5}
Line
Count
Source
272
444
    candidate.map(|c| (c, hint))
Unexecuted instantiation: gix_revision::spec::parse::function::long_describe_prefix::{closure#5}
gix_revision::spec::parse::function::long_describe_prefix::{closure#5}
Line
Count
Source
272
467
    candidate.map(|c| (c, hint))
273
19.2k
}
gix_revision::spec::parse::function::long_describe_prefix
Line
Count
Source
241
8.72k
fn long_describe_prefix(name: &BStr) -> Option<(&BStr, delegate::PrefixHint<'_>)> {
242
8.72k
    let mut iter = name.rsplit(|b| *b == b'-');
243
8.72k
    let candidate = iter.by_ref().find_map(|substr| {
244
        if substr.first()? != &b'g' {
245
            return None;
246
        }
247
        let rest = substr.get(1..)?;
248
        rest.iter().all(u8::is_ascii_hexdigit).then(|| rest.as_bstr())
249
8.24k
    })?;
250
251
481
    let candidate = iter.clone().any(|token| !token.is_empty()).then_some(candidate);
252
481
    let hint = iter
253
481
        .next()
254
481
        .and_then(|gen| gen.to_str().ok().and_then(|gen| usize::from_str(gen).ok()))
255
481
        .and_then(|generation| {
256
            iter.next().map(|token| {
257
                let last_token_len = token.len();
258
                let first_token_ptr = iter.next_back().map_or(token.as_ptr(), <[_]>::as_ptr);
259
                // SAFETY: both pointers are definitely part of the same object
260
                #[allow(unsafe_code)]
261
                let prior_tokens_len: usize = unsafe { token.as_ptr().offset_from(first_token_ptr) }
262
                    .try_into()
263
                    .expect("positive value");
264
                delegate::PrefixHint::DescribeAnchor {
265
                    ref_name: name[..prior_tokens_len + last_token_len].as_bstr(),
266
                    generation,
267
                }
268
            })
269
        })
270
481
        .unwrap_or(delegate::PrefixHint::MustBeCommit);
271
272
481
    candidate.map(|c| (c, hint))
273
8.72k
}
Unexecuted instantiation: gix_revision::spec::parse::function::long_describe_prefix
gix_revision::spec::parse::function::long_describe_prefix
Line
Count
Source
241
10.5k
fn long_describe_prefix(name: &BStr) -> Option<(&BStr, delegate::PrefixHint<'_>)> {
242
10.5k
    let mut iter = name.rsplit(|b| *b == b'-');
243
10.5k
    let candidate = iter.by_ref().find_map(|substr| {
244
        if substr.first()? != &b'g' {
245
            return None;
246
        }
247
        let rest = substr.get(1..)?;
248
        rest.iter().all(u8::is_ascii_hexdigit).then(|| rest.as_bstr())
249
10.0k
    })?;
250
251
522
    let candidate = iter.clone().any(|token| !token.is_empty()).then_some(candidate);
252
522
    let hint = iter
253
522
        .next()
254
522
        .and_then(|gen| gen.to_str().ok().and_then(|gen| usize::from_str(gen).ok()))
255
522
        .and_then(|generation| {
256
            iter.next().map(|token| {
257
                let last_token_len = token.len();
258
                let first_token_ptr = iter.next_back().map_or(token.as_ptr(), <[_]>::as_ptr);
259
                // SAFETY: both pointers are definitely part of the same object
260
                #[allow(unsafe_code)]
261
                let prior_tokens_len: usize = unsafe { token.as_ptr().offset_from(first_token_ptr) }
262
                    .try_into()
263
                    .expect("positive value");
264
                delegate::PrefixHint::DescribeAnchor {
265
                    ref_name: name[..prior_tokens_len + last_token_len].as_bstr(),
266
                    generation,
267
                }
268
            })
269
        })
270
522
        .unwrap_or(delegate::PrefixHint::MustBeCommit);
271
272
522
    candidate.map(|c| (c, hint))
273
10.5k
}
274
275
18.3k
fn short_describe_prefix(name: &BStr) -> Option<&BStr> {
276
45.0M
    let mut iter = name.split(|b| *b == b'-');
gix_revision::spec::parse::function::short_describe_prefix::{closure#0}
Line
Count
Source
276
15.6M
    let mut iter = name.split(|b| *b == b'-');
Unexecuted instantiation: gix_revision::spec::parse::function::short_describe_prefix::{closure#0}
gix_revision::spec::parse::function::short_describe_prefix::{closure#0}
Line
Count
Source
276
29.4M
    let mut iter = name.split(|b| *b == b'-');
277
18.3k
    let candidate = iter
278
18.3k
        .next()
279
18.3k
        .and_then(|prefix| prefix.iter().all(u8::is_ascii_hexdigit).then(|| prefix.as_bstr()));
gix_revision::spec::parse::function::short_describe_prefix::{closure#1}
Line
Count
Source
279
8.28k
        .and_then(|prefix| prefix.iter().all(u8::is_ascii_hexdigit).then(|| prefix.as_bstr()));
Unexecuted instantiation: gix_revision::spec::parse::function::short_describe_prefix::{closure#1}
gix_revision::spec::parse::function::short_describe_prefix::{closure#1}
Line
Count
Source
279
10.0k
        .and_then(|prefix| prefix.iter().all(u8::is_ascii_hexdigit).then(|| prefix.as_bstr()));
gix_revision::spec::parse::function::short_describe_prefix::{closure#1}::{closure#0}
Line
Count
Source
279
6.20k
        .and_then(|prefix| prefix.iter().all(u8::is_ascii_hexdigit).then(|| prefix.as_bstr()));
Unexecuted instantiation: gix_revision::spec::parse::function::short_describe_prefix::{closure#1}::{closure#0}
gix_revision::spec::parse::function::short_describe_prefix::{closure#1}::{closure#0}
Line
Count
Source
279
8.22k
        .and_then(|prefix| prefix.iter().all(u8::is_ascii_hexdigit).then(|| prefix.as_bstr()));
280
18.3k
    (iter.count() == 1).then_some(candidate).flatten()
281
18.3k
}
gix_revision::spec::parse::function::short_describe_prefix
Line
Count
Source
275
8.28k
fn short_describe_prefix(name: &BStr) -> Option<&BStr> {
276
8.28k
    let mut iter = name.split(|b| *b == b'-');
277
8.28k
    let candidate = iter
278
8.28k
        .next()
279
8.28k
        .and_then(|prefix| prefix.iter().all(u8::is_ascii_hexdigit).then(|| prefix.as_bstr()));
280
8.28k
    (iter.count() == 1).then_some(candidate).flatten()
281
8.28k
}
Unexecuted instantiation: gix_revision::spec::parse::function::short_describe_prefix
gix_revision::spec::parse::function::short_describe_prefix
Line
Count
Source
275
10.0k
fn short_describe_prefix(name: &BStr) -> Option<&BStr> {
276
10.0k
    let mut iter = name.split(|b| *b == b'-');
277
10.0k
    let candidate = iter
278
10.0k
        .next()
279
10.0k
        .and_then(|prefix| prefix.iter().all(u8::is_ascii_hexdigit).then(|| prefix.as_bstr()));
280
10.0k
    (iter.count() == 1).then_some(candidate).flatten()
281
10.0k
}
282
283
type InsideParensRestConsumed<'a> = (std::borrow::Cow<'a, BStr>, &'a BStr, usize);
284
54.2k
fn parens(input: &[u8]) -> Result<Option<InsideParensRestConsumed<'_>>, Error> {
285
54.2k
    if input.first() != Some(&b'{') {
286
31.6k
        return Ok(None);
287
22.5k
    }
288
22.5k
    let mut open_braces = 0;
289
22.5k
    let mut ignore_next = false;
290
22.5k
    let mut skip_list = Vec::new();
291
168M
    for (idx, b) in input.iter().enumerate() {
292
168M
        match *b {
293
            b'{' => {
294
32.2k
                if ignore_next {
295
2.57k
                    ignore_next = false;
296
29.6k
                } else {
297
29.6k
                    open_braces += 1;
298
29.6k
                }
299
            }
300
            b'}' => {
301
30.6k
                if ignore_next {
302
1.70k
                    ignore_next = false;
303
28.9k
                } else {
304
28.9k
                    open_braces -= 1;
305
28.9k
                }
306
            }
307
            b'\\' => {
308
13.4M
                skip_list.push(idx);
309
13.4M
                if ignore_next {
310
6.51M
                    skip_list.pop();
311
6.51M
                    ignore_next = false;
312
6.92M
                } else {
313
6.92M
                    ignore_next = true;
314
6.92M
                }
315
            }
316
            _ => {
317
155M
                if ignore_next {
318
398k
                    skip_list.pop();
319
154M
                }
320
155M
                ignore_next = false;
321
            }
322
        }
323
168M
        if open_braces == 0 {
324
22.2k
            let inner: std::borrow::Cow<'_, _> = if skip_list.is_empty() {
325
19.3k
                input[1..idx].as_bstr().into()
326
            } else {
327
2.89k
                let mut from = 1;
328
2.89k
                let mut buf = BString::default();
329
4.94M
                for next in skip_list.into_iter() {
330
4.94M
                    buf.push_str(&input[from..next]);
331
4.94M
                    from = next + 1;
332
4.94M
                }
333
2.89k
                if let Some(rest) = input.get(from..idx) {
334
2.89k
                    buf.push_str(rest);
335
2.89k
                }
336
2.89k
                buf.into()
337
            };
338
22.2k
            return Ok(Some((inner, input[idx + 1..].as_bstr(), idx + 1)));
339
168M
        }
340
    }
341
280
    Err(Error::new_with_input("unclosed brace pair", input))
342
54.2k
}
gix_revision::spec::parse::function::parens
Line
Count
Source
284
20.0k
fn parens(input: &[u8]) -> Result<Option<InsideParensRestConsumed<'_>>, Error> {
285
20.0k
    if input.first() != Some(&b'{') {
286
9.62k
        return Ok(None);
287
10.3k
    }
288
10.3k
    let mut open_braces = 0;
289
10.3k
    let mut ignore_next = false;
290
10.3k
    let mut skip_list = Vec::new();
291
66.8M
    for (idx, b) in input.iter().enumerate() {
292
66.8M
        match *b {
293
            b'{' => {
294
12.7k
                if ignore_next {
295
269
                    ignore_next = false;
296
12.4k
                } else {
297
12.4k
                    open_braces += 1;
298
12.4k
                }
299
            }
300
            b'}' => {
301
12.4k
                if ignore_next {
302
350
                    ignore_next = false;
303
12.0k
                } else {
304
12.0k
                    open_braces -= 1;
305
12.0k
                }
306
            }
307
            b'\\' => {
308
7.12M
                skip_list.push(idx);
309
7.12M
                if ignore_next {
310
3.38M
                    skip_list.pop();
311
3.38M
                    ignore_next = false;
312
3.74M
                } else {
313
3.74M
                    ignore_next = true;
314
3.74M
                }
315
            }
316
            _ => {
317
59.6M
                if ignore_next {
318
355k
                    skip_list.pop();
319
59.3M
                }
320
59.6M
                ignore_next = false;
321
            }
322
        }
323
66.8M
        if open_braces == 0 {
324
10.2k
            let inner: std::borrow::Cow<'_, _> = if skip_list.is_empty() {
325
8.80k
                input[1..idx].as_bstr().into()
326
            } else {
327
1.42k
                let mut from = 1;
328
1.42k
                let mut buf = BString::default();
329
2.48M
                for next in skip_list.into_iter() {
330
2.48M
                    buf.push_str(&input[from..next]);
331
2.48M
                    from = next + 1;
332
2.48M
                }
333
1.42k
                if let Some(rest) = input.get(from..idx) {
334
1.42k
                    buf.push_str(rest);
335
1.42k
                }
336
1.42k
                buf.into()
337
            };
338
10.2k
            return Ok(Some((inner, input[idx + 1..].as_bstr(), idx + 1)));
339
66.8M
        }
340
    }
341
170
    Err(Error::new_with_input("unclosed brace pair", input))
342
20.0k
}
Unexecuted instantiation: gix_revision::spec::parse::function::parens
gix_revision::spec::parse::function::parens
Line
Count
Source
284
34.2k
fn parens(input: &[u8]) -> Result<Option<InsideParensRestConsumed<'_>>, Error> {
285
34.2k
    if input.first() != Some(&b'{') {
286
22.0k
        return Ok(None);
287
12.1k
    }
288
12.1k
    let mut open_braces = 0;
289
12.1k
    let mut ignore_next = false;
290
12.1k
    let mut skip_list = Vec::new();
291
101M
    for (idx, b) in input.iter().enumerate() {
292
101M
        match *b {
293
            b'{' => {
294
19.4k
                if ignore_next {
295
2.30k
                    ignore_next = false;
296
17.1k
                } else {
297
17.1k
                    open_braces += 1;
298
17.1k
                }
299
            }
300
            b'}' => {
301
18.1k
                if ignore_next {
302
1.35k
                    ignore_next = false;
303
16.8k
                } else {
304
16.8k
                    open_braces -= 1;
305
16.8k
                }
306
            }
307
            b'\\' => {
308
6.31M
                skip_list.push(idx);
309
6.31M
                if ignore_next {
310
3.13M
                    skip_list.pop();
311
3.13M
                    ignore_next = false;
312
3.17M
                } else {
313
3.17M
                    ignore_next = true;
314
3.17M
                }
315
            }
316
            _ => {
317
95.5M
                if ignore_next {
318
43.6k
                    skip_list.pop();
319
95.5M
                }
320
95.5M
                ignore_next = false;
321
            }
322
        }
323
101M
        if open_braces == 0 {
324
12.0k
            let inner: std::borrow::Cow<'_, _> = if skip_list.is_empty() {
325
10.5k
                input[1..idx].as_bstr().into()
326
            } else {
327
1.46k
                let mut from = 1;
328
1.46k
                let mut buf = BString::default();
329
2.45M
                for next in skip_list.into_iter() {
330
2.45M
                    buf.push_str(&input[from..next]);
331
2.45M
                    from = next + 1;
332
2.45M
                }
333
1.46k
                if let Some(rest) = input.get(from..idx) {
334
1.46k
                    buf.push_str(rest);
335
1.46k
                }
336
1.46k
                buf.into()
337
            };
338
12.0k
            return Ok(Some((inner, input[idx + 1..].as_bstr(), idx + 1)));
339
101M
        }
340
    }
341
110
    Err(Error::new_with_input("unclosed brace pair", input))
342
34.2k
}
343
344
32.3k
fn try_parse<T: FromStr + PartialEq + Default>(input: &BStr) -> Result<Option<T>, Error> {
345
32.3k
    input
346
32.3k
        .to_str()
347
32.3k
        .ok()
348
32.3k
        .and_then(|n| {
349
31.5k
            n.parse().ok().map(|n| {
350
18.3k
                if n == T::default() && input[0] == b'-' {
351
102
                    return Err(Error::new_with_input(
352
102
                        "negative zero is invalid - remove the minus sign",
353
102
                        input,
354
102
                    ));
355
18.2k
                }
356
18.2k
                Ok(n)
357
18.3k
            })
gix_revision::spec::parse::function::try_parse::<isize>::{closure#0}::{closure#0}
Line
Count
Source
349
245
            n.parse().ok().map(|n| {
350
245
                if n == T::default() && input[0] == b'-' {
351
31
                    return Err(Error::new_with_input(
352
31
                        "negative zero is invalid - remove the minus sign",
353
31
                        input,
354
31
                    ));
355
214
                }
356
214
                Ok(n)
357
245
            })
gix_revision::spec::parse::function::try_parse::<isize>::{closure#0}::{closure#0}
Line
Count
Source
349
3.58k
            n.parse().ok().map(|n| {
350
3.58k
                if n == T::default() && input[0] == b'-' {
351
34
                    return Err(Error::new_with_input(
352
34
                        "negative zero is invalid - remove the minus sign",
353
34
                        input,
354
34
                    ));
355
3.55k
                }
356
3.55k
                Ok(n)
357
3.58k
            })
gix_revision::spec::parse::function::try_parse::<usize>::{closure#0}::{closure#0}
Line
Count
Source
349
2.37k
            n.parse().ok().map(|n| {
350
2.37k
                if n == T::default() && input[0] == b'-' {
351
0
                    return Err(Error::new_with_input(
352
0
                        "negative zero is invalid - remove the minus sign",
353
0
                        input,
354
0
                    ));
355
2.37k
                }
356
2.37k
                Ok(n)
357
2.37k
            })
Unexecuted instantiation: gix_revision::spec::parse::function::try_parse::<isize>::{closure#0}::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::try_parse::<usize>::{closure#0}::{closure#0}
gix_revision::spec::parse::function::try_parse::<isize>::{closure#0}::{closure#0}
Line
Count
Source
349
208
            n.parse().ok().map(|n| {
350
208
                if n == T::default() && input[0] == b'-' {
351
3
                    return Err(Error::new_with_input(
352
3
                        "negative zero is invalid - remove the minus sign",
353
3
                        input,
354
3
                    ));
355
205
                }
356
205
                Ok(n)
357
208
            })
gix_revision::spec::parse::function::try_parse::<isize>::{closure#0}::{closure#0}
Line
Count
Source
349
7.88k
            n.parse().ok().map(|n| {
350
7.88k
                if n == T::default() && input[0] == b'-' {
351
34
                    return Err(Error::new_with_input(
352
34
                        "negative zero is invalid - remove the minus sign",
353
34
                        input,
354
34
                    ));
355
7.85k
                }
356
7.85k
                Ok(n)
357
7.88k
            })
gix_revision::spec::parse::function::try_parse::<usize>::{closure#0}::{closure#0}
Line
Count
Source
349
4.06k
            n.parse().ok().map(|n| {
350
4.06k
                if n == T::default() && input[0] == b'-' {
351
0
                    return Err(Error::new_with_input(
352
0
                        "negative zero is invalid - remove the minus sign",
353
0
                        input,
354
0
                    ));
355
4.06k
                }
356
4.06k
                Ok(n)
357
4.06k
            })
358
31.5k
        })
gix_revision::spec::parse::function::try_parse::<isize>::{closure#0}
Line
Count
Source
348
5.62k
        .and_then(|n| {
349
5.62k
            n.parse().ok().map(|n| {
350
                if n == T::default() && input[0] == b'-' {
351
                    return Err(Error::new_with_input(
352
                        "negative zero is invalid - remove the minus sign",
353
                        input,
354
                    ));
355
                }
356
                Ok(n)
357
            })
358
5.62k
        })
gix_revision::spec::parse::function::try_parse::<isize>::{closure#0}
Line
Count
Source
348
3.65k
        .and_then(|n| {
349
3.65k
            n.parse().ok().map(|n| {
350
                if n == T::default() && input[0] == b'-' {
351
                    return Err(Error::new_with_input(
352
                        "negative zero is invalid - remove the minus sign",
353
                        input,
354
                    ));
355
                }
356
                Ok(n)
357
            })
358
3.65k
        })
gix_revision::spec::parse::function::try_parse::<usize>::{closure#0}
Line
Count
Source
348
2.41k
        .and_then(|n| {
349
2.41k
            n.parse().ok().map(|n| {
350
                if n == T::default() && input[0] == b'-' {
351
                    return Err(Error::new_with_input(
352
                        "negative zero is invalid - remove the minus sign",
353
                        input,
354
                    ));
355
                }
356
                Ok(n)
357
            })
358
2.41k
        })
Unexecuted instantiation: gix_revision::spec::parse::function::try_parse::<isize>::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::try_parse::<usize>::{closure#0}
gix_revision::spec::parse::function::try_parse::<isize>::{closure#0}
Line
Count
Source
348
7.78k
        .and_then(|n| {
349
7.78k
            n.parse().ok().map(|n| {
350
                if n == T::default() && input[0] == b'-' {
351
                    return Err(Error::new_with_input(
352
                        "negative zero is invalid - remove the minus sign",
353
                        input,
354
                    ));
355
                }
356
                Ok(n)
357
            })
358
7.78k
        })
gix_revision::spec::parse::function::try_parse::<isize>::{closure#0}
Line
Count
Source
348
7.96k
        .and_then(|n| {
349
7.96k
            n.parse().ok().map(|n| {
350
                if n == T::default() && input[0] == b'-' {
351
                    return Err(Error::new_with_input(
352
                        "negative zero is invalid - remove the minus sign",
353
                        input,
354
                    ));
355
                }
356
                Ok(n)
357
            })
358
7.96k
        })
gix_revision::spec::parse::function::try_parse::<usize>::{closure#0}
Line
Count
Source
348
4.10k
        .and_then(|n| {
349
4.10k
            n.parse().ok().map(|n| {
350
                if n == T::default() && input[0] == b'-' {
351
                    return Err(Error::new_with_input(
352
                        "negative zero is invalid - remove the minus sign",
353
                        input,
354
                    ));
355
                }
356
                Ok(n)
357
            })
358
4.10k
        })
359
32.3k
        .transpose()
360
32.3k
}
gix_revision::spec::parse::function::try_parse::<isize>
Line
Count
Source
344
6.02k
fn try_parse<T: FromStr + PartialEq + Default>(input: &BStr) -> Result<Option<T>, Error> {
345
6.02k
    input
346
6.02k
        .to_str()
347
6.02k
        .ok()
348
6.02k
        .and_then(|n| {
349
            n.parse().ok().map(|n| {
350
                if n == T::default() && input[0] == b'-' {
351
                    return Err(Error::new_with_input(
352
                        "negative zero is invalid - remove the minus sign",
353
                        input,
354
                    ));
355
                }
356
                Ok(n)
357
            })
358
        })
359
6.02k
        .transpose()
360
6.02k
}
gix_revision::spec::parse::function::try_parse::<isize>
Line
Count
Source
344
3.65k
fn try_parse<T: FromStr + PartialEq + Default>(input: &BStr) -> Result<Option<T>, Error> {
345
3.65k
    input
346
3.65k
        .to_str()
347
3.65k
        .ok()
348
3.65k
        .and_then(|n| {
349
            n.parse().ok().map(|n| {
350
                if n == T::default() && input[0] == b'-' {
351
                    return Err(Error::new_with_input(
352
                        "negative zero is invalid - remove the minus sign",
353
                        input,
354
                    ));
355
                }
356
                Ok(n)
357
            })
358
        })
359
3.65k
        .transpose()
360
3.65k
}
gix_revision::spec::parse::function::try_parse::<usize>
Line
Count
Source
344
2.41k
fn try_parse<T: FromStr + PartialEq + Default>(input: &BStr) -> Result<Option<T>, Error> {
345
2.41k
    input
346
2.41k
        .to_str()
347
2.41k
        .ok()
348
2.41k
        .and_then(|n| {
349
            n.parse().ok().map(|n| {
350
                if n == T::default() && input[0] == b'-' {
351
                    return Err(Error::new_with_input(
352
                        "negative zero is invalid - remove the minus sign",
353
                        input,
354
                    ));
355
                }
356
                Ok(n)
357
            })
358
        })
359
2.41k
        .transpose()
360
2.41k
}
Unexecuted instantiation: gix_revision::spec::parse::function::try_parse::<isize>
Unexecuted instantiation: gix_revision::spec::parse::function::try_parse::<usize>
gix_revision::spec::parse::function::try_parse::<isize>
Line
Count
Source
344
8.14k
fn try_parse<T: FromStr + PartialEq + Default>(input: &BStr) -> Result<Option<T>, Error> {
345
8.14k
    input
346
8.14k
        .to_str()
347
8.14k
        .ok()
348
8.14k
        .and_then(|n| {
349
            n.parse().ok().map(|n| {
350
                if n == T::default() && input[0] == b'-' {
351
                    return Err(Error::new_with_input(
352
                        "negative zero is invalid - remove the minus sign",
353
                        input,
354
                    ));
355
                }
356
                Ok(n)
357
            })
358
        })
359
8.14k
        .transpose()
360
8.14k
}
gix_revision::spec::parse::function::try_parse::<isize>
Line
Count
Source
344
7.96k
fn try_parse<T: FromStr + PartialEq + Default>(input: &BStr) -> Result<Option<T>, Error> {
345
7.96k
    input
346
7.96k
        .to_str()
347
7.96k
        .ok()
348
7.96k
        .and_then(|n| {
349
            n.parse().ok().map(|n| {
350
                if n == T::default() && input[0] == b'-' {
351
                    return Err(Error::new_with_input(
352
                        "negative zero is invalid - remove the minus sign",
353
                        input,
354
                    ));
355
                }
356
                Ok(n)
357
            })
358
        })
359
7.96k
        .transpose()
360
7.96k
}
gix_revision::spec::parse::function::try_parse::<usize>
Line
Count
Source
344
4.10k
fn try_parse<T: FromStr + PartialEq + Default>(input: &BStr) -> Result<Option<T>, Error> {
345
4.10k
    input
346
4.10k
        .to_str()
347
4.10k
        .ok()
348
4.10k
        .and_then(|n| {
349
            n.parse().ok().map(|n| {
350
                if n == T::default() && input[0] == b'-' {
351
                    return Err(Error::new_with_input(
352
                        "negative zero is invalid - remove the minus sign",
353
                        input,
354
                    ));
355
                }
356
                Ok(n)
357
            })
358
        })
359
4.10k
        .transpose()
360
4.10k
}
361
362
19.8k
fn revision<'a, T>(mut input: &'a BStr, delegate: &mut InterceptRev<'_, T>) -> Result<&'a BStr, Exn<Error>>
363
19.8k
where
364
19.8k
    T: Delegate,
365
{
366
    use delegate::{Navigate, Revision};
367
77
    fn consume_all(res: Result<(), Exn>, err: impl FnOnce() -> String) -> Result<&'static BStr, Exn<Error>> {
368
77
        res.map(|_| "".into()).or_raise(|| Error::new(err()))
Unexecuted instantiation: gix_revision::spec::parse::function::revision::consume_all::<gix_revision::spec::parse::function::revision<gix_refspec::parse::revparse::Noop>::{closure#0}>::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::consume_all::<gix_revision::spec::parse::function::revision<gix_refspec::parse::revparse::Noop>::{closure#2}>::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::consume_all::<gix_revision::spec::parse::function::revision<gix_refspec::parse::revparse::Noop>::{closure#3}>::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::consume_all::<gix_revision::spec::parse::function::revision<gix_refspec::parse::revparse::Noop>::{closure#4}>::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::consume_all::<gix_revision::spec::parse::function::revision<gix_refspec::parse::revparse::Noop>::{closure#1}>::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::consume_all::<_>::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::consume_all::<_>::{closure#0}
gix_revision::spec::parse::function::revision::consume_all::<gix_revision::spec::parse::function::revision<parse::Noop>::{closure#0}>::{closure#0}
Line
Count
Source
368
16
        res.map(|_| "".into()).or_raise(|| Error::new(err()))
gix_revision::spec::parse::function::revision::consume_all::<gix_revision::spec::parse::function::revision<parse::Noop>::{closure#2}>::{closure#0}
Line
Count
Source
368
1
        res.map(|_| "".into()).or_raise(|| Error::new(err()))
gix_revision::spec::parse::function::revision::consume_all::<gix_revision::spec::parse::function::revision<parse::Noop>::{closure#3}>::{closure#0}
Line
Count
Source
368
1
        res.map(|_| "".into()).or_raise(|| Error::new(err()))
gix_revision::spec::parse::function::revision::consume_all::<gix_revision::spec::parse::function::revision<parse::Noop>::{closure#4}>::{closure#0}
Line
Count
Source
368
57
        res.map(|_| "".into()).or_raise(|| Error::new(err()))
gix_revision::spec::parse::function::revision::consume_all::<gix_revision::spec::parse::function::revision<parse::Noop>::{closure#1}>::{closure#0}
Line
Count
Source
368
2
        res.map(|_| "".into()).or_raise(|| Error::new(err()))
Unexecuted instantiation: gix_revision::spec::parse::function::revision::consume_all::<_>::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::consume_all::<gix_revision::spec::parse::function::revision<gix_refspec::parse::revparse::Noop>::{closure#0}>::{closure#1}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::consume_all::<gix_revision::spec::parse::function::revision<gix_refspec::parse::revparse::Noop>::{closure#2}>::{closure#1}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::consume_all::<gix_revision::spec::parse::function::revision<gix_refspec::parse::revparse::Noop>::{closure#3}>::{closure#1}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::consume_all::<gix_revision::spec::parse::function::revision<gix_refspec::parse::revparse::Noop>::{closure#4}>::{closure#1}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::consume_all::<gix_revision::spec::parse::function::revision<gix_refspec::parse::revparse::Noop>::{closure#1}>::{closure#1}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::consume_all::<_>::{closure#1}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::consume_all::<_>::{closure#1}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::consume_all::<gix_revision::spec::parse::function::revision<parse::Noop>::{closure#0}>::{closure#1}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::consume_all::<gix_revision::spec::parse::function::revision<parse::Noop>::{closure#2}>::{closure#1}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::consume_all::<gix_revision::spec::parse::function::revision<parse::Noop>::{closure#3}>::{closure#1}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::consume_all::<gix_revision::spec::parse::function::revision<parse::Noop>::{closure#4}>::{closure#1}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::consume_all::<gix_revision::spec::parse::function::revision<parse::Noop>::{closure#1}>::{closure#1}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::consume_all::<_>::{closure#1}
369
77
    }
Unexecuted instantiation: gix_revision::spec::parse::function::revision::consume_all::<gix_revision::spec::parse::function::revision<gix_refspec::parse::revparse::Noop>::{closure#0}>
Unexecuted instantiation: gix_revision::spec::parse::function::revision::consume_all::<gix_revision::spec::parse::function::revision<gix_refspec::parse::revparse::Noop>::{closure#2}>
Unexecuted instantiation: gix_revision::spec::parse::function::revision::consume_all::<gix_revision::spec::parse::function::revision<gix_refspec::parse::revparse::Noop>::{closure#3}>
Unexecuted instantiation: gix_revision::spec::parse::function::revision::consume_all::<gix_revision::spec::parse::function::revision<gix_refspec::parse::revparse::Noop>::{closure#4}>
Unexecuted instantiation: gix_revision::spec::parse::function::revision::consume_all::<gix_revision::spec::parse::function::revision<gix_refspec::parse::revparse::Noop>::{closure#1}>
Unexecuted instantiation: gix_revision::spec::parse::function::revision::consume_all::<_>
Unexecuted instantiation: gix_revision::spec::parse::function::revision::consume_all::<_>
gix_revision::spec::parse::function::revision::consume_all::<gix_revision::spec::parse::function::revision<parse::Noop>::{closure#0}>
Line
Count
Source
367
16
    fn consume_all(res: Result<(), Exn>, err: impl FnOnce() -> String) -> Result<&'static BStr, Exn<Error>> {
368
16
        res.map(|_| "".into()).or_raise(|| Error::new(err()))
369
16
    }
gix_revision::spec::parse::function::revision::consume_all::<gix_revision::spec::parse::function::revision<parse::Noop>::{closure#2}>
Line
Count
Source
367
1
    fn consume_all(res: Result<(), Exn>, err: impl FnOnce() -> String) -> Result<&'static BStr, Exn<Error>> {
368
1
        res.map(|_| "".into()).or_raise(|| Error::new(err()))
369
1
    }
gix_revision::spec::parse::function::revision::consume_all::<gix_revision::spec::parse::function::revision<parse::Noop>::{closure#3}>
Line
Count
Source
367
1
    fn consume_all(res: Result<(), Exn>, err: impl FnOnce() -> String) -> Result<&'static BStr, Exn<Error>> {
368
1
        res.map(|_| "".into()).or_raise(|| Error::new(err()))
369
1
    }
gix_revision::spec::parse::function::revision::consume_all::<gix_revision::spec::parse::function::revision<parse::Noop>::{closure#4}>
Line
Count
Source
367
57
    fn consume_all(res: Result<(), Exn>, err: impl FnOnce() -> String) -> Result<&'static BStr, Exn<Error>> {
368
57
        res.map(|_| "".into()).or_raise(|| Error::new(err()))
369
57
    }
gix_revision::spec::parse::function::revision::consume_all::<gix_revision::spec::parse::function::revision<parse::Noop>::{closure#1}>
Line
Count
Source
367
2
    fn consume_all(res: Result<(), Exn>, err: impl FnOnce() -> String) -> Result<&'static BStr, Exn<Error>> {
368
2
        res.map(|_| "".into()).or_raise(|| Error::new(err()))
369
2
    }
Unexecuted instantiation: gix_revision::spec::parse::function::revision::consume_all::<_>
370
19.8k
    match input.as_bytes() {
371
19.8k
        [b':'] => {
372
1
            return Err(
373
1
                Error::new("':' must be followed by either slash and regex or path to lookup in HEAD tree").raise(),
374
1
            )
375
        }
376
19.6k
        [b':', b'/'] => return Err(Error::new("':/' must be followed by a regular expression").raise()),
377
29
        [b':', b'/', regex @ ..] => {
378
29
            let (regex, negated) = parse_regex_prefix(regex.as_bstr())?;
379
17
            if regex.is_empty() {
380
1
                return Err(Error::new_with_input("unconsumed input", input).raise());
381
16
            }
382
16
            return consume_all(delegate.find(regex, negated), || {
383
0
                format!("Delegate couldn't find '{regex}' (negated: {negated})")
384
0
            });
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<parse::Noop>::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#0}
385
        }
386
2
        [b':', b'0', b':', path @ ..] => {
387
2
            return consume_all(delegate.index_lookup(path.as_bstr(), 0), || {
388
0
                format!("Couldn't find index '{path}' stage 0", path = path.as_bstr())
389
0
            })
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>::{closure#1}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#1}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#1}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<parse::Noop>::{closure#1}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#1}
390
        }
391
1
        [b':', b'1', b':', path @ ..] => {
392
1
            return consume_all(delegate.index_lookup(path.as_bstr(), 1), || {
393
0
                format!("Couldn't find index '{path}' stage 1", path = path.as_bstr())
394
0
            })
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>::{closure#2}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#2}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#2}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<parse::Noop>::{closure#2}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#2}
395
        }
396
1
        [b':', b'2', b':', path @ ..] => {
397
1
            return consume_all(delegate.index_lookup(path.as_bstr(), 2), || {
398
0
                format!("Couldn't find index '{path}' stage 2", path = path.as_bstr())
399
0
            })
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>::{closure#3}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#3}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#3}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<parse::Noop>::{closure#3}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#3}
400
        }
401
57
        [b':', path @ ..] => {
402
57
            return consume_all(delegate.index_lookup(path.as_bstr(), 0), || {
403
0
                format!("Couldn't find index '{path}' stage 0 (implicit)", path = path.as_bstr())
404
0
            })
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>::{closure#4}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#4}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#4}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<parse::Noop>::{closure#4}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#4}
405
        }
406
19.7k
        _ => {}
407
    }
408
409
19.7k
    let mut sep_pos = None;
410
19.7k
    let mut consecutive_hex_chars = Some(0);
411
    {
412
19.7k
        let mut cursor = input;
413
19.7k
        let mut ofs = 0;
414
        const SEPARATORS: &[u8] = b"~^:.";
415
77.4M
        while let Some((pos, b)) = cursor.iter().enumerate().find(|(pos, b)| {
416
77.4M
            if **b == b'@' {
417
2.26M
                if cursor.len() == 1 {
418
30
                    return true;
419
2.26M
                }
420
2.26M
                let next = cursor.get(pos + 1);
421
2.26M
                let next_next = cursor.get(pos + 2);
422
2.26M
                if *pos != 0 && (next, next_next) == (Some(&b'.'), Some(&b'.')) {
423
17
                    return false;
424
2.26M
                }
425
2.26M
                next == Some(&b'{') || next.is_some_and(|b| SEPARATORS.contains(b))
gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>::{closure#5}::{closure#0}
Line
Count
Source
425
1.91M
                next == Some(&b'{') || next.is_some_and(|b| SEPARATORS.contains(b))
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#5}::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#5}::{closure#0}
gix_revision::spec::parse::function::revision::<parse::Noop>::{closure#5}::{closure#0}
Line
Count
Source
425
335k
                next == Some(&b'{') || next.is_some_and(|b| SEPARATORS.contains(b))
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#5}::{closure#0}
426
75.1M
            } else if SEPARATORS.contains(b) {
427
18.2k
                true
428
            } else {
429
75.1M
                if let Some(num) = consecutive_hex_chars.as_mut() {
430
16.4M
                    if b.is_ascii_hexdigit() {
431
16.4M
                        *num += 1;
432
16.4M
                    } else {
433
4.86k
                        consecutive_hex_chars = None;
434
4.86k
                    }
435
58.6M
                }
436
75.1M
                false
437
            }
438
77.4M
        }) {
gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>::{closure#5}
Line
Count
Source
415
33.0M
        while let Some((pos, b)) = cursor.iter().enumerate().find(|(pos, b)| {
416
33.0M
            if **b == b'@' {
417
1.92M
                if cursor.len() == 1 {
418
15
                    return true;
419
1.92M
                }
420
1.92M
                let next = cursor.get(pos + 1);
421
1.92M
                let next_next = cursor.get(pos + 2);
422
1.92M
                if *pos != 0 && (next, next_next) == (Some(&b'.'), Some(&b'.')) {
423
8
                    return false;
424
1.92M
                }
425
1.92M
                next == Some(&b'{') || next.is_some_and(|b| SEPARATORS.contains(b))
426
31.1M
            } else if SEPARATORS.contains(b) {
427
12.3k
                true
428
            } else {
429
31.1M
                if let Some(num) = consecutive_hex_chars.as_mut() {
430
6.17M
                    if b.is_ascii_hexdigit() {
431
6.17M
                        *num += 1;
432
6.17M
                    } else {
433
2.54k
                        consecutive_hex_chars = None;
434
2.54k
                    }
435
24.9M
                }
436
31.1M
                false
437
            }
438
33.0M
        }) {
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#5}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#5}
gix_revision::spec::parse::function::revision::<parse::Noop>::{closure#5}
Line
Count
Source
415
44.3M
        while let Some((pos, b)) = cursor.iter().enumerate().find(|(pos, b)| {
416
44.3M
            if **b == b'@' {
417
343k
                if cursor.len() == 1 {
418
15
                    return true;
419
343k
                }
420
343k
                let next = cursor.get(pos + 1);
421
343k
                let next_next = cursor.get(pos + 2);
422
343k
                if *pos != 0 && (next, next_next) == (Some(&b'.'), Some(&b'.')) {
423
9
                    return false;
424
343k
                }
425
343k
                next == Some(&b'{') || next.is_some_and(|b| SEPARATORS.contains(b))
426
44.0M
            } else if SEPARATORS.contains(b) {
427
5.89k
                true
428
            } else {
429
44.0M
                if let Some(num) = consecutive_hex_chars.as_mut() {
430
10.3M
                    if b.is_ascii_hexdigit() {
431
10.3M
                        *num += 1;
432
10.3M
                    } else {
433
2.31k
                        consecutive_hex_chars = None;
434
2.31k
                    }
435
33.7M
                }
436
44.0M
                false
437
            }
438
44.3M
        }) {
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#5}
439
33.1k
            if *b != b'.' || cursor.get(pos + 1) == Some(&b'.') {
440
18.3k
                sep_pos = Some(ofs + pos);
441
18.3k
                break;
442
14.7k
            }
443
14.7k
            ofs += pos + 1;
444
14.7k
            cursor = &cursor[pos + 1..];
445
        }
446
    }
447
448
19.7k
    let name = &input[..sep_pos.unwrap_or(input.len())].as_bstr();
449
19.7k
    let mut sep = sep_pos.map(|pos| input[pos]);
gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>::{closure#6}
Line
Count
Source
449
8.22k
    let mut sep = sep_pos.map(|pos| input[pos]);
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#6}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#6}
gix_revision::spec::parse::function::revision::<parse::Noop>::{closure#6}
Line
Count
Source
449
10.1k
    let mut sep = sep_pos.map(|pos| input[pos]);
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#6}
450
19.7k
    let mut has_ref_or_implied_name = name.is_empty();
451
19.7k
    if name.is_empty() && sep == Some(b'@') && sep_pos.and_then(|pos| input.get(pos + 1)) != Some(&b'{') {
gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>::{closure#7}
Line
Count
Source
451
5.79k
    if name.is_empty() && sep == Some(b'@') && sep_pos.and_then(|pos| input.get(pos + 1)) != Some(&b'{') {
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#7}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#7}
gix_revision::spec::parse::function::revision::<parse::Noop>::{closure#7}
Line
Count
Source
451
7.70k
    if name.is_empty() && sep == Some(b'@') && sep_pos.and_then(|pos| input.get(pos + 1)) != Some(&b'{') {
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#7}
452
268
        delegate
453
268
            .find_ref("HEAD".into())
454
268
            .or_raise(|| Error::new("delegate did not find the HEAD reference"))?;
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>::{closure#8}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#8}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#8}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<parse::Noop>::{closure#8}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#8}
455
268
        sep_pos = sep_pos.map(|pos| pos + 1);
gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>::{closure#9}
Line
Count
Source
455
123
        sep_pos = sep_pos.map(|pos| pos + 1);
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#9}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#9}
gix_revision::spec::parse::function::revision::<parse::Noop>::{closure#9}
Line
Count
Source
455
145
        sep_pos = sep_pos.map(|pos| pos + 1);
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#9}
456
268
        sep = match sep_pos.and_then(|pos| input.get(pos).copied()) {
gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>::{closure#10}
Line
Count
Source
456
123
        sep = match sep_pos.and_then(|pos| input.get(pos).copied()) {
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#10}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#10}
gix_revision::spec::parse::function::revision::<parse::Noop>::{closure#10}
Line
Count
Source
456
145
        sep = match sep_pos.and_then(|pos| input.get(pos).copied()) {
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#10}
457
7
            None => return Ok("".into()),
458
261
            Some(pos) => Some(pos),
459
        };
460
    } else {
461
19.4k
        let mut errors = Vec::new();
462
19.4k
        (consecutive_hex_chars.unwrap_or(0) >= gix_hash::Prefix::MIN_HEX_LEN)
463
19.4k
            .then(|| try_set_prefix(delegate, name, None, &mut errors))
gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>::{closure#11}
Line
Count
Source
463
209
            .then(|| try_set_prefix(delegate, name, None, &mut errors))
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#11}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#11}
gix_revision::spec::parse::function::revision::<parse::Noop>::{closure#11}
Line
Count
Source
463
219
            .then(|| try_set_prefix(delegate, name, None, &mut errors))
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#11}
464
19.4k
            .flatten()
465
19.4k
            .or_else(|| {
466
19.2k
                let (prefix, hint) = long_describe_prefix(name)
467
19.2k
                    .map(|(c, h)| (c, Some(h)))
gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>::{closure#12}::{closure#0}
Line
Count
Source
467
444
                    .map(|(c, h)| (c, Some(h)))
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#12}::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#12}::{closure#0}
gix_revision::spec::parse::function::revision::<parse::Noop>::{closure#12}::{closure#0}
Line
Count
Source
467
467
                    .map(|(c, h)| (c, Some(h)))
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#12}::{closure#0}
468
19.2k
                    .or_else(|| short_describe_prefix(name).map(|c| (c, None)))?;
gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>::{closure#12}::{closure#1}
Line
Count
Source
468
8.28k
                    .or_else(|| short_describe_prefix(name).map(|c| (c, None)))?;
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#12}::{closure#1}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#12}::{closure#1}
gix_revision::spec::parse::function::revision::<parse::Noop>::{closure#12}::{closure#1}
Line
Count
Source
468
10.0k
                    .or_else(|| short_describe_prefix(name).map(|c| (c, None)))?;
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#12}::{closure#1}
gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>::{closure#12}::{closure#1}::{closure#0}
Line
Count
Source
468
110
                    .or_else(|| short_describe_prefix(name).map(|c| (c, None)))?;
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#12}::{closure#1}::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#12}::{closure#1}::{closure#0}
gix_revision::spec::parse::function::revision::<parse::Noop>::{closure#12}::{closure#1}::{closure#0}
Line
Count
Source
468
111
                    .or_else(|| short_describe_prefix(name).map(|c| (c, None)))?;
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#12}::{closure#1}::{closure#0}
469
1.13k
                try_set_prefix(delegate, prefix, hint, &mut errors)
470
19.2k
            })
gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>::{closure#12}
Line
Count
Source
465
8.72k
            .or_else(|| {
466
8.72k
                let (prefix, hint) = long_describe_prefix(name)
467
8.72k
                    .map(|(c, h)| (c, Some(h)))
468
8.72k
                    .or_else(|| short_describe_prefix(name).map(|c| (c, None)))?;
469
554
                try_set_prefix(delegate, prefix, hint, &mut errors)
470
8.72k
            })
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#12}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#12}
gix_revision::spec::parse::function::revision::<parse::Noop>::{closure#12}
Line
Count
Source
465
10.5k
            .or_else(|| {
466
10.5k
                let (prefix, hint) = long_describe_prefix(name)
467
10.5k
                    .map(|(c, h)| (c, Some(h)))
468
10.5k
                    .or_else(|| short_describe_prefix(name).map(|c| (c, None)))?;
469
578
                try_set_prefix(delegate, prefix, hint, &mut errors)
470
10.5k
            })
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#12}
471
19.4k
            .or_else(|| {
472
18.8k
                name.is_empty().then_some(()).or_else(|| {
473
                    #[allow(clippy::let_unit_value)]
474
                    {
475
5.39k
                        let res = delegate.find_ref(name).or_else_none(|err| {
476
0
                            errors.push(err);
477
0
                        })?;
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>::{closure#13}::{closure#0}::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#13}::{closure#0}::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#13}::{closure#0}::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<parse::Noop>::{closure#13}::{closure#0}::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#13}::{closure#0}::{closure#0}
478
5.39k
                        has_ref_or_implied_name = true;
479
5.39k
                        res.into()
480
                    }
481
5.39k
                })
gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>::{closure#13}::{closure#0}
Line
Count
Source
472
2.77k
                name.is_empty().then_some(()).or_else(|| {
473
                    #[allow(clippy::let_unit_value)]
474
                    {
475
2.77k
                        let res = delegate.find_ref(name).or_else_none(|err| {
476
                            errors.push(err);
477
0
                        })?;
478
2.77k
                        has_ref_or_implied_name = true;
479
2.77k
                        res.into()
480
                    }
481
2.77k
                })
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#13}::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#13}::{closure#0}
gix_revision::spec::parse::function::revision::<parse::Noop>::{closure#13}::{closure#0}
Line
Count
Source
472
2.62k
                name.is_empty().then_some(()).or_else(|| {
473
                    #[allow(clippy::let_unit_value)]
474
                    {
475
2.62k
                        let res = delegate.find_ref(name).or_else_none(|err| {
476
                            errors.push(err);
477
0
                        })?;
478
2.62k
                        has_ref_or_implied_name = true;
479
2.62k
                        res.into()
480
                    }
481
2.62k
                })
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#13}::{closure#0}
482
18.8k
            })
gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>::{closure#13}
Line
Count
Source
471
8.52k
            .or_else(|| {
472
8.52k
                name.is_empty().then_some(()).or_else(|| {
473
                    #[allow(clippy::let_unit_value)]
474
                    {
475
                        let res = delegate.find_ref(name).or_else_none(|err| {
476
                            errors.push(err);
477
                        })?;
478
                        has_ref_or_implied_name = true;
479
                        res.into()
480
                    }
481
                })
482
8.52k
            })
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#13}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#13}
gix_revision::spec::parse::function::revision::<parse::Noop>::{closure#13}
Line
Count
Source
471
10.3k
            .or_else(|| {
472
10.3k
                name.is_empty().then_some(()).or_else(|| {
473
                    #[allow(clippy::let_unit_value)]
474
                    {
475
                        let res = delegate.find_ref(name).or_else_none(|err| {
476
                            errors.push(err);
477
                        })?;
478
                        has_ref_or_implied_name = true;
479
                        res.into()
480
                    }
481
                })
482
10.3k
            })
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#13}
483
19.4k
            .ok_or_else(|| Error::new_with_input("couldn't parse revision", input).raise_all(errors))?;
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>::{closure#14}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#14}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#14}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<parse::Noop>::{closure#14}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#14}
484
    }
485
486
    input = {
487
19.7k
        if let Some(b'@') = sep {
488
14.5k
            let past_sep = input[sep_pos.map_or(input.len(), |pos| pos + 1)..].as_bstr();
gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>::{closure#15}
Line
Count
Source
488
6.25k
            let past_sep = input[sep_pos.map_or(input.len(), |pos| pos + 1)..].as_bstr();
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#15}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#15}
gix_revision::spec::parse::function::revision::<parse::Noop>::{closure#15}
Line
Count
Source
488
8.33k
            let past_sep = input[sep_pos.map_or(input.len(), |pos| pos + 1)..].as_bstr();
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#15}
489
14.5k
            let (nav, rest, _consumed) = parens(past_sep)?.ok_or_else(|| {
490
178
                Error::new_with_input(
491
                    "@ character must be standalone or followed by {<content>}",
492
178
                    &input[sep_pos.unwrap_or(input.len())..],
493
                )
494
178
            })?;
gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>::{closure#16}
Line
Count
Source
489
90
            let (nav, rest, _consumed) = parens(past_sep)?.ok_or_else(|| {
490
90
                Error::new_with_input(
491
                    "@ character must be standalone or followed by {<content>}",
492
90
                    &input[sep_pos.unwrap_or(input.len())..],
493
                )
494
90
            })?;
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#16}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#16}
gix_revision::spec::parse::function::revision::<parse::Noop>::{closure#16}
Line
Count
Source
489
88
            let (nav, rest, _consumed) = parens(past_sep)?.ok_or_else(|| {
490
88
                Error::new_with_input(
491
                    "@ character must be standalone or followed by {<content>}",
492
88
                    &input[sep_pos.unwrap_or(input.len())..],
493
                )
494
88
            })?;
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#16}
495
14.1k
            let nav = nav.as_ref();
496
14.1k
            if let Some(n) = try_parse::<isize>(nav)? {
497
419
                if n < 0 {
498
187
                    if name.is_empty() {
499
169
                        delegate.nth_checked_out_branch(n.unsigned_abs()).or_raise(|| {
500
0
                            Error::new_with_input(
501
0
                                format!("delegate.nth_checked_out_branch({n:?}) didn't find a branch"),
502
0
                                nav,
503
                            )
504
0
                        })?;
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>::{closure#17}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#17}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#17}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<parse::Noop>::{closure#17}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#17}
505
                    } else {
506
18
                        return Err(Error::new_with_input(
507
18
                            "reference name must be followed by positive numbers in @{n}",
508
18
                            nav,
509
18
                        )
510
18
                        .raise());
511
                    }
512
232
                } else if has_ref_or_implied_name {
513
225
                    let lookup = if n >= 100000000 {
514
114
                        let time = nav
515
114
                            .to_str()
516
114
                            .or_raise(|| Error::new_with_input("could not parse time for reflog lookup", nav))
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>::{closure#18}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#18}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#18}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<parse::Noop>::{closure#18}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#18}
517
114
                            .and_then(|date| {
518
114
                                gix_date::parse(date, None)
519
114
                                    .or_raise(|| Error::new_with_input("could not parse time for reflog lookup", nav))
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>::{closure#19}::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#19}::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#19}::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<parse::Noop>::{closure#19}::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#19}::{closure#0}
520
114
                            })?;
gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>::{closure#19}
Line
Count
Source
517
59
                            .and_then(|date| {
518
59
                                gix_date::parse(date, None)
519
59
                                    .or_raise(|| Error::new_with_input("could not parse time for reflog lookup", nav))
520
59
                            })?;
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#19}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#19}
gix_revision::spec::parse::function::revision::<parse::Noop>::{closure#19}
Line
Count
Source
517
55
                            .and_then(|date| {
518
55
                                gix_date::parse(date, None)
519
55
                                    .or_raise(|| Error::new_with_input("could not parse time for reflog lookup", nav))
520
55
                            })?;
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#19}
521
114
                        delegate::ReflogLookup::Date(time)
522
                    } else {
523
111
                        delegate::ReflogLookup::Entry(n.try_into().expect("non-negative isize fits usize"))
524
                    };
525
225
                    delegate
526
225
                        .reflog(lookup)
527
225
                        .or_raise(|| Error::new_with_input(format!("delegate.reflog({lookup:?}) failed"), nav))?;
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>::{closure#20}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#20}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#20}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<parse::Noop>::{closure#20}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#20}
528
                } else {
529
7
                    return Err(Error::new_with_input("reflog entries require a ref name", *name).raise());
530
                }
531
13.7k
            } else if let Some(kind) = SiblingBranch::parse(nav) {
532
36
                if has_ref_or_implied_name {
533
20
                    delegate
534
20
                        .sibling_branch(kind)
535
20
                        .or_raise(|| Error::new_with_input(format!("delegate.sibling_branch({kind:?}) failed"), nav))
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>::{closure#21}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#21}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#21}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<parse::Noop>::{closure#21}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#21}
536
                } else {
537
16
                    Err(Error::new_with_input(
538
16
                        "sibling branches like 'upstream' or 'push' require a branch name with remote configuration",
539
16
                        *name,
540
16
                    )
541
16
                    .raise())
542
16
                }?;
543
13.6k
            } else if has_ref_or_implied_name {
544
13.5k
                let time = nav
545
13.5k
                    .to_str()
546
13.5k
                    .map_err(|_| Error::new_with_input("could not parse time for reflog lookup", nav))
gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>::{closure#22}
Line
Count
Source
546
370
                    .map_err(|_| Error::new_with_input("could not parse time for reflog lookup", nav))
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#22}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#22}
gix_revision::spec::parse::function::revision::<parse::Noop>::{closure#22}
Line
Count
Source
546
336
                    .map_err(|_| Error::new_with_input("could not parse time for reflog lookup", nav))
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#22}
547
13.5k
                    .and_then(|date| {
548
12.8k
                        gix_date::parse(date, Some(SystemTime::now()))
549
12.8k
                            .map_err(|_| Error::new_with_input("could not parse time for reflog lookup", nav))
gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>::{closure#23}::{closure#0}
Line
Count
Source
549
4.36k
                            .map_err(|_| Error::new_with_input("could not parse time for reflog lookup", nav))
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#23}::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#23}::{closure#0}
gix_revision::spec::parse::function::revision::<parse::Noop>::{closure#23}::{closure#0}
Line
Count
Source
549
5.85k
                            .map_err(|_| Error::new_with_input("could not parse time for reflog lookup", nav))
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#23}::{closure#0}
550
12.8k
                    })?;
gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>::{closure#23}
Line
Count
Source
547
5.34k
                    .and_then(|date| {
548
5.34k
                        gix_date::parse(date, Some(SystemTime::now()))
549
5.34k
                            .map_err(|_| Error::new_with_input("could not parse time for reflog lookup", nav))
550
5.34k
                    })?;
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#23}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#23}
gix_revision::spec::parse::function::revision::<parse::Noop>::{closure#23}
Line
Count
Source
547
7.54k
                    .and_then(|date| {
548
7.54k
                        gix_date::parse(date, Some(SystemTime::now()))
549
7.54k
                            .map_err(|_| Error::new_with_input("could not parse time for reflog lookup", nav))
550
7.54k
                    })?;
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#23}
551
2.66k
                let lookup = delegate::ReflogLookup::Date(time);
552
2.66k
                delegate
553
2.66k
                    .reflog(lookup)
554
2.66k
                    .or_raise(|| Error::new_with_input(format!("delegate.reflog({lookup:?}) failed"), nav))?;
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>::{closure#24}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#24}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#24}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<parse::Noop>::{closure#24}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>::{closure#24}
555
            } else {
556
84
                return Err(Error::new_with_input("reflog entries require a ref name", *name).raise());
557
            }
558
3.07k
            rest
559
        } else {
560
5.14k
            if sep_pos == Some(0) && sep == Some(b'~') {
561
15
                return Err(Error::new("tilde needs to follow an anchor, like @~").raise());
562
5.13k
            }
563
5.13k
            input[sep_pos.unwrap_or(input.len())..].as_bstr()
564
        }
565
    };
566
567
8.20k
    navigate(input, delegate)
568
19.8k
}
gix_revision::spec::parse::function::revision::<gix_refspec::parse::revparse::Noop>
Line
Count
Source
362
8.95k
fn revision<'a, T>(mut input: &'a BStr, delegate: &mut InterceptRev<'_, T>) -> Result<&'a BStr, Exn<Error>>
363
8.95k
where
364
8.95k
    T: Delegate,
365
{
366
    use delegate::{Navigate, Revision};
367
    fn consume_all(res: Result<(), Exn>, err: impl FnOnce() -> String) -> Result<&'static BStr, Exn<Error>> {
368
        res.map(|_| "".into()).or_raise(|| Error::new(err()))
369
    }
370
8.95k
    match input.as_bytes() {
371
8.95k
        [b':'] => {
372
0
            return Err(
373
0
                Error::new("':' must be followed by either slash and regex or path to lookup in HEAD tree").raise(),
374
0
            )
375
        }
376
8.87k
        [b':', b'/'] => return Err(Error::new("':/' must be followed by a regular expression").raise()),
377
0
        [b':', b'/', regex @ ..] => {
378
0
            let (regex, negated) = parse_regex_prefix(regex.as_bstr())?;
379
0
            if regex.is_empty() {
380
0
                return Err(Error::new_with_input("unconsumed input", input).raise());
381
0
            }
382
0
            return consume_all(delegate.find(regex, negated), || {
383
                format!("Delegate couldn't find '{regex}' (negated: {negated})")
384
            });
385
        }
386
0
        [b':', b'0', b':', path @ ..] => {
387
0
            return consume_all(delegate.index_lookup(path.as_bstr(), 0), || {
388
                format!("Couldn't find index '{path}' stage 0", path = path.as_bstr())
389
            })
390
        }
391
0
        [b':', b'1', b':', path @ ..] => {
392
0
            return consume_all(delegate.index_lookup(path.as_bstr(), 1), || {
393
                format!("Couldn't find index '{path}' stage 1", path = path.as_bstr())
394
            })
395
        }
396
0
        [b':', b'2', b':', path @ ..] => {
397
0
            return consume_all(delegate.index_lookup(path.as_bstr(), 2), || {
398
                format!("Couldn't find index '{path}' stage 2", path = path.as_bstr())
399
            })
400
        }
401
0
        [b':', path @ ..] => {
402
0
            return consume_all(delegate.index_lookup(path.as_bstr(), 0), || {
403
                format!("Couldn't find index '{path}' stage 0 (implicit)", path = path.as_bstr())
404
            })
405
        }
406
8.95k
        _ => {}
407
    }
408
409
8.95k
    let mut sep_pos = None;
410
8.95k
    let mut consecutive_hex_chars = Some(0);
411
    {
412
8.95k
        let mut cursor = input;
413
8.95k
        let mut ofs = 0;
414
        const SEPARATORS: &[u8] = b"~^:.";
415
19.4k
        while let Some((pos, b)) = cursor.iter().enumerate().find(|(pos, b)| {
416
            if **b == b'@' {
417
                if cursor.len() == 1 {
418
                    return true;
419
                }
420
                let next = cursor.get(pos + 1);
421
                let next_next = cursor.get(pos + 2);
422
                if *pos != 0 && (next, next_next) == (Some(&b'.'), Some(&b'.')) {
423
                    return false;
424
                }
425
                next == Some(&b'{') || next.is_some_and(|b| SEPARATORS.contains(b))
426
            } else if SEPARATORS.contains(b) {
427
                true
428
            } else {
429
                if let Some(num) = consecutive_hex_chars.as_mut() {
430
                    if b.is_ascii_hexdigit() {
431
                        *num += 1;
432
                    } else {
433
                        consecutive_hex_chars = None;
434
                    }
435
                }
436
                false
437
            }
438
        }) {
439
18.7k
            if *b != b'.' || cursor.get(pos + 1) == Some(&b'.') {
440
8.22k
                sep_pos = Some(ofs + pos);
441
8.22k
                break;
442
10.5k
            }
443
10.5k
            ofs += pos + 1;
444
10.5k
            cursor = &cursor[pos + 1..];
445
        }
446
    }
447
448
8.95k
    let name = &input[..sep_pos.unwrap_or(input.len())].as_bstr();
449
8.95k
    let mut sep = sep_pos.map(|pos| input[pos]);
450
8.95k
    let mut has_ref_or_implied_name = name.is_empty();
451
8.95k
    if name.is_empty() && sep == Some(b'@') && sep_pos.and_then(|pos| input.get(pos + 1)) != Some(&b'{') {
452
123
        delegate
453
123
            .find_ref("HEAD".into())
454
123
            .or_raise(|| Error::new("delegate did not find the HEAD reference"))?;
455
123
        sep_pos = sep_pos.map(|pos| pos + 1);
456
123
        sep = match sep_pos.and_then(|pos| input.get(pos).copied()) {
457
3
            None => return Ok("".into()),
458
120
            Some(pos) => Some(pos),
459
        };
460
    } else {
461
8.83k
        let mut errors = Vec::new();
462
8.83k
        (consecutive_hex_chars.unwrap_or(0) >= gix_hash::Prefix::MIN_HEX_LEN)
463
8.83k
            .then(|| try_set_prefix(delegate, name, None, &mut errors))
464
8.83k
            .flatten()
465
8.83k
            .or_else(|| {
466
                let (prefix, hint) = long_describe_prefix(name)
467
                    .map(|(c, h)| (c, Some(h)))
468
                    .or_else(|| short_describe_prefix(name).map(|c| (c, None)))?;
469
                try_set_prefix(delegate, prefix, hint, &mut errors)
470
            })
471
8.83k
            .or_else(|| {
472
                name.is_empty().then_some(()).or_else(|| {
473
                    #[allow(clippy::let_unit_value)]
474
                    {
475
                        let res = delegate.find_ref(name).or_else_none(|err| {
476
                            errors.push(err);
477
                        })?;
478
                        has_ref_or_implied_name = true;
479
                        res.into()
480
                    }
481
                })
482
            })
483
8.83k
            .ok_or_else(|| Error::new_with_input("couldn't parse revision", input).raise_all(errors))?;
484
    }
485
486
    input = {
487
8.95k
        if let Some(b'@') = sep {
488
6.25k
            let past_sep = input[sep_pos.map_or(input.len(), |pos| pos + 1)..].as_bstr();
489
6.25k
            let (nav, rest, _consumed) = parens(past_sep)?.ok_or_else(|| {
490
                Error::new_with_input(
491
                    "@ character must be standalone or followed by {<content>}",
492
                    &input[sep_pos.unwrap_or(input.len())..],
493
                )
494
90
            })?;
495
6.02k
            let nav = nav.as_ref();
496
6.02k
            if let Some(n) = try_parse::<isize>(nav)? {
497
214
                if n < 0 {
498
97
                    if name.is_empty() {
499
85
                        delegate.nth_checked_out_branch(n.unsigned_abs()).or_raise(|| {
500
                            Error::new_with_input(
501
                                format!("delegate.nth_checked_out_branch({n:?}) didn't find a branch"),
502
                                nav,
503
                            )
504
0
                        })?;
505
                    } else {
506
12
                        return Err(Error::new_with_input(
507
12
                            "reference name must be followed by positive numbers in @{n}",
508
12
                            nav,
509
12
                        )
510
12
                        .raise());
511
                    }
512
117
                } else if has_ref_or_implied_name {
513
113
                    let lookup = if n >= 100000000 {
514
59
                        let time = nav
515
59
                            .to_str()
516
59
                            .or_raise(|| Error::new_with_input("could not parse time for reflog lookup", nav))
517
59
                            .and_then(|date| {
518
                                gix_date::parse(date, None)
519
                                    .or_raise(|| Error::new_with_input("could not parse time for reflog lookup", nav))
520
0
                            })?;
521
59
                        delegate::ReflogLookup::Date(time)
522
                    } else {
523
54
                        delegate::ReflogLookup::Entry(n.try_into().expect("non-negative isize fits usize"))
524
                    };
525
113
                    delegate
526
113
                        .reflog(lookup)
527
113
                        .or_raise(|| Error::new_with_input(format!("delegate.reflog({lookup:?}) failed"), nav))?;
528
                } else {
529
4
                    return Err(Error::new_with_input("reflog entries require a ref name", *name).raise());
530
                }
531
5.77k
            } else if let Some(kind) = SiblingBranch::parse(nav) {
532
25
                if has_ref_or_implied_name {
533
10
                    delegate
534
10
                        .sibling_branch(kind)
535
10
                        .or_raise(|| Error::new_with_input(format!("delegate.sibling_branch({kind:?}) failed"), nav))
536
                } else {
537
15
                    Err(Error::new_with_input(
538
15
                        "sibling branches like 'upstream' or 'push' require a branch name with remote configuration",
539
15
                        *name,
540
15
                    )
541
15
                    .raise())
542
15
                }?;
543
5.75k
            } else if has_ref_or_implied_name {
544
5.71k
                let time = nav
545
5.71k
                    .to_str()
546
5.71k
                    .map_err(|_| Error::new_with_input("could not parse time for reflog lookup", nav))
547
5.71k
                    .and_then(|date| {
548
                        gix_date::parse(date, Some(SystemTime::now()))
549
                            .map_err(|_| Error::new_with_input("could not parse time for reflog lookup", nav))
550
4.73k
                    })?;
551
977
                let lookup = delegate::ReflogLookup::Date(time);
552
977
                delegate
553
977
                    .reflog(lookup)
554
977
                    .or_raise(|| Error::new_with_input(format!("delegate.reflog({lookup:?}) failed"), nav))?;
555
            } else {
556
37
                return Err(Error::new_with_input("reflog entries require a ref name", *name).raise());
557
            }
558
1.18k
            rest
559
        } else {
560
2.70k
            if sep_pos == Some(0) && sep == Some(b'~') {
561
10
                return Err(Error::new("tilde needs to follow an anchor, like @~").raise());
562
2.69k
            }
563
2.69k
            input[sep_pos.unwrap_or(input.len())..].as_bstr()
564
        }
565
    };
566
567
3.87k
    navigate(input, delegate)
568
8.95k
}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>
gix_revision::spec::parse::function::revision::<parse::Noop>
Line
Count
Source
362
10.8k
fn revision<'a, T>(mut input: &'a BStr, delegate: &mut InterceptRev<'_, T>) -> Result<&'a BStr, Exn<Error>>
363
10.8k
where
364
10.8k
    T: Delegate,
365
{
366
    use delegate::{Navigate, Revision};
367
    fn consume_all(res: Result<(), Exn>, err: impl FnOnce() -> String) -> Result<&'static BStr, Exn<Error>> {
368
        res.map(|_| "".into()).or_raise(|| Error::new(err()))
369
    }
370
10.8k
    match input.as_bytes() {
371
10.8k
        [b':'] => {
372
1
            return Err(
373
1
                Error::new("':' must be followed by either slash and regex or path to lookup in HEAD tree").raise(),
374
1
            )
375
        }
376
10.8k
        [b':', b'/'] => return Err(Error::new("':/' must be followed by a regular expression").raise()),
377
29
        [b':', b'/', regex @ ..] => {
378
29
            let (regex, negated) = parse_regex_prefix(regex.as_bstr())?;
379
17
            if regex.is_empty() {
380
1
                return Err(Error::new_with_input("unconsumed input", input).raise());
381
16
            }
382
16
            return consume_all(delegate.find(regex, negated), || {
383
                format!("Delegate couldn't find '{regex}' (negated: {negated})")
384
            });
385
        }
386
2
        [b':', b'0', b':', path @ ..] => {
387
2
            return consume_all(delegate.index_lookup(path.as_bstr(), 0), || {
388
                format!("Couldn't find index '{path}' stage 0", path = path.as_bstr())
389
            })
390
        }
391
1
        [b':', b'1', b':', path @ ..] => {
392
1
            return consume_all(delegate.index_lookup(path.as_bstr(), 1), || {
393
                format!("Couldn't find index '{path}' stage 1", path = path.as_bstr())
394
            })
395
        }
396
1
        [b':', b'2', b':', path @ ..] => {
397
1
            return consume_all(delegate.index_lookup(path.as_bstr(), 2), || {
398
                format!("Couldn't find index '{path}' stage 2", path = path.as_bstr())
399
            })
400
        }
401
57
        [b':', path @ ..] => {
402
57
            return consume_all(delegate.index_lookup(path.as_bstr(), 0), || {
403
                format!("Couldn't find index '{path}' stage 0 (implicit)", path = path.as_bstr())
404
            })
405
        }
406
10.7k
        _ => {}
407
    }
408
409
10.7k
    let mut sep_pos = None;
410
10.7k
    let mut consecutive_hex_chars = Some(0);
411
    {
412
10.7k
        let mut cursor = input;
413
10.7k
        let mut ofs = 0;
414
        const SEPARATORS: &[u8] = b"~^:.";
415
15.0k
        while let Some((pos, b)) = cursor.iter().enumerate().find(|(pos, b)| {
416
            if **b == b'@' {
417
                if cursor.len() == 1 {
418
                    return true;
419
                }
420
                let next = cursor.get(pos + 1);
421
                let next_next = cursor.get(pos + 2);
422
                if *pos != 0 && (next, next_next) == (Some(&b'.'), Some(&b'.')) {
423
                    return false;
424
                }
425
                next == Some(&b'{') || next.is_some_and(|b| SEPARATORS.contains(b))
426
            } else if SEPARATORS.contains(b) {
427
                true
428
            } else {
429
                if let Some(num) = consecutive_hex_chars.as_mut() {
430
                    if b.is_ascii_hexdigit() {
431
                        *num += 1;
432
                    } else {
433
                        consecutive_hex_chars = None;
434
                    }
435
                }
436
                false
437
            }
438
        }) {
439
14.3k
            if *b != b'.' || cursor.get(pos + 1) == Some(&b'.') {
440
10.1k
                sep_pos = Some(ofs + pos);
441
10.1k
                break;
442
4.23k
            }
443
4.23k
            ofs += pos + 1;
444
4.23k
            cursor = &cursor[pos + 1..];
445
        }
446
    }
447
448
10.7k
    let name = &input[..sep_pos.unwrap_or(input.len())].as_bstr();
449
10.7k
    let mut sep = sep_pos.map(|pos| input[pos]);
450
10.7k
    let mut has_ref_or_implied_name = name.is_empty();
451
10.7k
    if name.is_empty() && sep == Some(b'@') && sep_pos.and_then(|pos| input.get(pos + 1)) != Some(&b'{') {
452
145
        delegate
453
145
            .find_ref("HEAD".into())
454
145
            .or_raise(|| Error::new("delegate did not find the HEAD reference"))?;
455
145
        sep_pos = sep_pos.map(|pos| pos + 1);
456
145
        sep = match sep_pos.and_then(|pos| input.get(pos).copied()) {
457
4
            None => return Ok("".into()),
458
141
            Some(pos) => Some(pos),
459
        };
460
    } else {
461
10.6k
        let mut errors = Vec::new();
462
10.6k
        (consecutive_hex_chars.unwrap_or(0) >= gix_hash::Prefix::MIN_HEX_LEN)
463
10.6k
            .then(|| try_set_prefix(delegate, name, None, &mut errors))
464
10.6k
            .flatten()
465
10.6k
            .or_else(|| {
466
                let (prefix, hint) = long_describe_prefix(name)
467
                    .map(|(c, h)| (c, Some(h)))
468
                    .or_else(|| short_describe_prefix(name).map(|c| (c, None)))?;
469
                try_set_prefix(delegate, prefix, hint, &mut errors)
470
            })
471
10.6k
            .or_else(|| {
472
                name.is_empty().then_some(()).or_else(|| {
473
                    #[allow(clippy::let_unit_value)]
474
                    {
475
                        let res = delegate.find_ref(name).or_else_none(|err| {
476
                            errors.push(err);
477
                        })?;
478
                        has_ref_or_implied_name = true;
479
                        res.into()
480
                    }
481
                })
482
            })
483
10.6k
            .ok_or_else(|| Error::new_with_input("couldn't parse revision", input).raise_all(errors))?;
484
    }
485
486
    input = {
487
10.7k
        if let Some(b'@') = sep {
488
8.33k
            let past_sep = input[sep_pos.map_or(input.len(), |pos| pos + 1)..].as_bstr();
489
8.33k
            let (nav, rest, _consumed) = parens(past_sep)?.ok_or_else(|| {
490
                Error::new_with_input(
491
                    "@ character must be standalone or followed by {<content>}",
492
                    &input[sep_pos.unwrap_or(input.len())..],
493
                )
494
88
            })?;
495
8.14k
            let nav = nav.as_ref();
496
8.14k
            if let Some(n) = try_parse::<isize>(nav)? {
497
205
                if n < 0 {
498
90
                    if name.is_empty() {
499
84
                        delegate.nth_checked_out_branch(n.unsigned_abs()).or_raise(|| {
500
                            Error::new_with_input(
501
                                format!("delegate.nth_checked_out_branch({n:?}) didn't find a branch"),
502
                                nav,
503
                            )
504
0
                        })?;
505
                    } else {
506
6
                        return Err(Error::new_with_input(
507
6
                            "reference name must be followed by positive numbers in @{n}",
508
6
                            nav,
509
6
                        )
510
6
                        .raise());
511
                    }
512
115
                } else if has_ref_or_implied_name {
513
112
                    let lookup = if n >= 100000000 {
514
55
                        let time = nav
515
55
                            .to_str()
516
55
                            .or_raise(|| Error::new_with_input("could not parse time for reflog lookup", nav))
517
55
                            .and_then(|date| {
518
                                gix_date::parse(date, None)
519
                                    .or_raise(|| Error::new_with_input("could not parse time for reflog lookup", nav))
520
0
                            })?;
521
55
                        delegate::ReflogLookup::Date(time)
522
                    } else {
523
57
                        delegate::ReflogLookup::Entry(n.try_into().expect("non-negative isize fits usize"))
524
                    };
525
112
                    delegate
526
112
                        .reflog(lookup)
527
112
                        .or_raise(|| Error::new_with_input(format!("delegate.reflog({lookup:?}) failed"), nav))?;
528
                } else {
529
3
                    return Err(Error::new_with_input("reflog entries require a ref name", *name).raise());
530
                }
531
7.94k
            } else if let Some(kind) = SiblingBranch::parse(nav) {
532
11
                if has_ref_or_implied_name {
533
10
                    delegate
534
10
                        .sibling_branch(kind)
535
10
                        .or_raise(|| Error::new_with_input(format!("delegate.sibling_branch({kind:?}) failed"), nav))
536
                } else {
537
1
                    Err(Error::new_with_input(
538
1
                        "sibling branches like 'upstream' or 'push' require a branch name with remote configuration",
539
1
                        *name,
540
1
                    )
541
1
                    .raise())
542
1
                }?;
543
7.92k
            } else if has_ref_or_implied_name {
544
7.88k
                let time = nav
545
7.88k
                    .to_str()
546
7.88k
                    .map_err(|_| Error::new_with_input("could not parse time for reflog lookup", nav))
547
7.88k
                    .and_then(|date| {
548
                        gix_date::parse(date, Some(SystemTime::now()))
549
                            .map_err(|_| Error::new_with_input("could not parse time for reflog lookup", nav))
550
6.19k
                    })?;
551
1.68k
                let lookup = delegate::ReflogLookup::Date(time);
552
1.68k
                delegate
553
1.68k
                    .reflog(lookup)
554
1.68k
                    .or_raise(|| Error::new_with_input(format!("delegate.reflog({lookup:?}) failed"), nav))?;
555
            } else {
556
47
                return Err(Error::new_with_input("reflog entries require a ref name", *name).raise());
557
            }
558
1.89k
            rest
559
        } else {
560
2.44k
            if sep_pos == Some(0) && sep == Some(b'~') {
561
5
                return Err(Error::new("tilde needs to follow an anchor, like @~").raise());
562
2.43k
            }
563
2.43k
            input[sep_pos.unwrap_or(input.len())..].as_bstr()
564
        }
565
    };
566
567
4.32k
    navigate(input, delegate)
568
10.8k
}
Unexecuted instantiation: gix_revision::spec::parse::function::revision::<_>
569
570
8.20k
fn navigate<'a, T>(input: &'a BStr, delegate: &mut InterceptRev<'_, T>) -> Result<&'a BStr, Exn<Error>>
571
8.20k
where
572
8.20k
    T: Delegate,
573
{
574
    use delegate::{Kind, Navigate, Revision};
575
8.20k
    let mut cursor = 0;
576
8.20k
    let done_msg = "navigation succeeded, but no revision was produced as intermediate step";
577
67.0k
    while let Some(b) = input.get(cursor) {
578
62.7k
        cursor += 1;
579
62.7k
        match *b {
580
            b'~' => {
581
9.04k
                let (number, consumed) = input
582
9.04k
                    .get(cursor..)
583
9.04k
                    .and_then(|past_sep| try_parse_usize(past_sep.as_bstr()).transpose())
gix_revision::spec::parse::function::navigate::<gix_refspec::parse::revparse::Noop>::{closure#0}
Line
Count
Source
583
3.94k
                    .and_then(|past_sep| try_parse_usize(past_sep.as_bstr()).transpose())
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#0}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#0}
gix_revision::spec::parse::function::navigate::<parse::Noop>::{closure#0}
Line
Count
Source
583
5.09k
                    .and_then(|past_sep| try_parse_usize(past_sep.as_bstr()).transpose())
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#0}
584
9.04k
                    .transpose()?
585
8.88k
                    .unwrap_or((1, 0));
586
8.88k
                if number != 0 {
587
6.20k
                    let traversal = delegate::Traversal::NthAncestor(number);
588
6.20k
                    delegate.traverse(traversal).or_raise(|| {
589
0
                        Error::new_with_input(format!("delegate.traverse({traversal:?}) failed"), input)
590
0
                    })?;
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<gix_refspec::parse::revparse::Noop>::{closure#1}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#1}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#1}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<parse::Noop>::{closure#1}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#1}
591
2.67k
                }
592
8.88k
                cursor += consumed;
593
            }
594
            b'^' => {
595
51.5k
                let past_sep = input.get(cursor..);
596
51.5k
                if let Some((number, negative, consumed)) = past_sep
597
51.5k
                    .and_then(|past_sep| try_parse_isize(past_sep.as_bstr()).transpose())
gix_revision::spec::parse::function::navigate::<gix_refspec::parse::revparse::Noop>::{closure#2}
Line
Count
Source
597
17.5k
                    .and_then(|past_sep| try_parse_isize(past_sep.as_bstr()).transpose())
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#2}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#2}
gix_revision::spec::parse::function::navigate::<parse::Noop>::{closure#2}
Line
Count
Source
597
34.0k
                    .and_then(|past_sep| try_parse_isize(past_sep.as_bstr()).transpose())
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#2}
598
51.5k
                    .transpose()?
599
                {
600
11.6k
                    if negative {
601
547
                        let traversal = delegate::Traversal::NthParent(
602
597
                            number
603
597
                                .checked_mul(-1)
604
597
                                .ok_or_else(|| {
605
50
                                    Error::new_with_input("could not parse number", past_sep.expect("present"))
606
50
                                })?
gix_revision::spec::parse::function::navigate::<gix_refspec::parse::revparse::Noop>::{closure#3}
Line
Count
Source
604
33
                                .ok_or_else(|| {
605
33
                                    Error::new_with_input("could not parse number", past_sep.expect("present"))
606
33
                                })?
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#3}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#3}
gix_revision::spec::parse::function::navigate::<parse::Noop>::{closure#3}
Line
Count
Source
604
17
                                .ok_or_else(|| {
605
17
                                    Error::new_with_input("could not parse number", past_sep.expect("present"))
606
17
                                })?
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#3}
607
547
                                .try_into()
608
547
                                .expect("non-negative"),
609
                        );
610
547
                        delegate.traverse(traversal).or_raise(|| {
611
0
                            Error::new_with_input(
612
                                "delegate.traverse({traversal:?}) failed",
613
0
                                past_sep.unwrap_or_default(),
614
                            )
615
0
                        })?;
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<gix_refspec::parse::revparse::Noop>::{closure#4}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#4}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#4}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<parse::Noop>::{closure#4}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#4}
616
547
                        let kind = spec::Kind::RangeBetween;
617
547
                        delegate.kind(kind).or_raise(|| {
618
0
                            Error::new_with_input(
619
0
                                format!("delegate.kind({kind:?}) failed"),
620
0
                                past_sep.unwrap_or_default(),
621
                            )
622
0
                        })?;
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<gix_refspec::parse::revparse::Noop>::{closure#5}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#5}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#5}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<parse::Noop>::{closure#5}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#5}
623
547
                        if let Some((prefix, hint)) = delegate.last_prefix.take() {
624
174
                            match &hint {
625
164
                                Some(hint) => delegate.disambiguate_prefix(prefix, hint.to_ref().into()),
626
10
                                None => delegate.disambiguate_prefix(prefix, None),
627
                            }
628
174
                            .or_raise(|| {
629
0
                                Error::new_with_input(
630
0
                                    format!("delegate.disambiguate_prefix({hint:?}) failed"),
631
0
                                    past_sep.unwrap_or_default(),
632
                                )
633
0
                            })?;
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<gix_refspec::parse::revparse::Noop>::{closure#6}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#6}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#6}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<parse::Noop>::{closure#6}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#6}
634
373
                        } else if let Some(name) = delegate.last_ref.take() {
635
354
                            delegate.find_ref(name.as_bstr()).or_raise(|| {
636
0
                                Error::new_with_input(
637
0
                                    format!("delegate.find_ref({name}) failed"),
638
0
                                    past_sep.unwrap_or_default(),
639
                                )
640
0
                            })?;
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<gix_refspec::parse::revparse::Noop>::{closure#7}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#7}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#7}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<parse::Noop>::{closure#7}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#7}
641
                        } else {
642
19
                            return Err(Error::new_with_input("unconsumed input", &input[cursor..]).raise());
643
                        }
644
528
                        cursor += consumed;
645
528
                        let rest = input[cursor..].as_bstr();
646
528
                        delegate.done().or_raise(|| Error::new_with_input(done_msg, rest))?;
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<gix_refspec::parse::revparse::Noop>::{closure#8}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#8}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#8}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<parse::Noop>::{closure#8}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#8}
647
528
                        return Ok(rest);
648
11.0k
                    } else if number == 0 {
649
3.26k
                        delegate.peel_until(delegate::PeelTo::ObjectKind(gix_object::Kind::Commit))
650
                    } else {
651
7.77k
                        delegate.traverse(delegate::Traversal::NthParent(
652
7.77k
                            number.try_into().expect("positive number"),
653
7.77k
                        ))
654
                    }
655
11.0k
                    .or_raise(|| Error::new_with_input("unknown navigation", past_sep.unwrap_or_default()))?;
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<gix_refspec::parse::revparse::Noop>::{closure#9}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#9}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#9}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<parse::Noop>::{closure#9}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#9}
656
11.0k
                    cursor += consumed;
657
8.11k
                } else if let Some((kind, _rest, consumed)) =
658
39.6k
                    past_sep.and_then(|past_sep| parens(past_sep).transpose()).transpose()?
gix_revision::spec::parse::function::navigate::<gix_refspec::parse::revparse::Noop>::{closure#10}
Line
Count
Source
658
13.7k
                    past_sep.and_then(|past_sep| parens(past_sep).transpose()).transpose()?
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#10}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#10}
gix_revision::spec::parse::function::navigate::<parse::Noop>::{closure#10}
Line
Count
Source
658
25.8k
                    past_sep.and_then(|past_sep| parens(past_sep).transpose()).transpose()?
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#10}
659
                {
660
8.11k
                    cursor += consumed;
661
8.11k
                    let target = match kind.as_ref().as_bytes() {
662
8.11k
                        b"commit" => delegate::PeelTo::ObjectKind(gix_object::Kind::Commit),
663
6.73k
                        b"tag" => delegate::PeelTo::ObjectKind(gix_object::Kind::Tag),
664
4.88k
                        b"tree" => delegate::PeelTo::ObjectKind(gix_object::Kind::Tree),
665
403
                        b"blob" => delegate::PeelTo::ObjectKind(gix_object::Kind::Blob),
666
417
                        b"object" => delegate::PeelTo::ValidObject,
667
3.39k
                        b"" => delegate::PeelTo::RecursiveTagObject,
668
5.64k
                        regex if regex.starts_with(b"/") => {
669
5.21k
                            let (regex, negated) = parse_regex_prefix(regex[1..].as_bstr())?;
670
5.10k
                            if !regex.is_empty() {
671
4.25k
                                delegate.find(regex, negated).or_raise(|| {
672
0
                                    Error::new(format!("Delegate couldn't find '{regex}' (negated: {negated})"))
673
0
                                })?;
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<gix_refspec::parse::revparse::Noop>::{closure#11}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#11}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#11}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<parse::Noop>::{closure#11}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#11}
674
848
                            }
675
5.10k
                            continue;
676
                        }
677
427
                        invalid => return Err(Error::new_with_input("cannot peel to unknown target", invalid).raise()),
678
                    };
679
2.46k
                    delegate.peel_until(target).or_raise(|| {
680
0
                        Error::new_with_input(
681
0
                            format!("delegate.peel_until({target:?}) failed"),
682
0
                            past_sep.unwrap_or_default(),
683
                        )
684
0
                    })?;
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<gix_refspec::parse::revparse::Noop>::{closure#12}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#12}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#12}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<parse::Noop>::{closure#12}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#12}
685
31.5k
                } else if past_sep.and_then(<[_]>::first) == Some(&b'!') {
686
39
                    let rest = input[cursor + 1..].as_bstr();
687
39
                    let kind = spec::Kind::ExcludeReachableFromParents;
688
39
                    delegate
689
39
                        .kind(kind)
690
39
                        .or_raise(|| Error::new_with_input(format!("delegate.kind({kind:?}) failed"), rest))?;
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<gix_refspec::parse::revparse::Noop>::{closure#13}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#13}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#13}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<parse::Noop>::{closure#13}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#13}
691
39
                    delegate.done().or_raise(|| Error::new_with_input(done_msg, rest))?;
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<gix_refspec::parse::revparse::Noop>::{closure#14}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#14}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#14}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<parse::Noop>::{closure#14}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#14}
692
39
                    return Ok(rest);
693
31.4k
                } else if past_sep.and_then(<[_]>::first) == Some(&b'@') {
694
77
                    let rest = input[cursor + 1..].as_bstr();
695
77
                    let kind = spec::Kind::IncludeReachableFromParents;
696
77
                    delegate
697
77
                        .kind(kind)
698
77
                        .or_raise(|| Error::new_with_input(format!("delegate.kind({kind:?}) failed"), rest))?;
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<gix_refspec::parse::revparse::Noop>::{closure#15}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#15}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#15}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<parse::Noop>::{closure#15}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#15}
699
77
                    delegate.done().or_raise(|| Error::new_with_input(done_msg, rest))?;
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<gix_refspec::parse::revparse::Noop>::{closure#16}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#16}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#16}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<parse::Noop>::{closure#16}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#16}
700
77
                    return Ok(rest);
701
                } else {
702
31.3k
                    let parent = delegate::Traversal::NthParent(1);
703
31.3k
                    delegate.traverse(parent).or_raise(|| {
704
0
                        Error::new_with_input(
705
0
                            format!("delegate.parent({parent:?}) failed",),
706
0
                            past_sep.unwrap_or_default(),
707
                        )
708
0
                    })?;
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<gix_refspec::parse::revparse::Noop>::{closure#17}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#17}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#17}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<parse::Noop>::{closure#17}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#17}
709
                }
710
            }
711
            b':' => {
712
21
                let to = delegate::PeelTo::Path(input[cursor..].as_bstr());
713
21
                delegate
714
21
                    .peel_until(to)
715
21
                    .or_raise(|| Error::new(format!("delegate.peel_until({to:?}) failed")))?;
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<gix_refspec::parse::revparse::Noop>::{closure#18}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#18}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#18}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<parse::Noop>::{closure#18}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>::{closure#18}
716
21
                return Ok("".into());
717
            }
718
2.11k
            _ => return Ok(input[cursor - 1..].as_bstr()),
719
        }
720
    }
721
4.32k
    Ok("".into())
722
8.20k
}
gix_revision::spec::parse::function::navigate::<gix_refspec::parse::revparse::Noop>
Line
Count
Source
570
3.87k
fn navigate<'a, T>(input: &'a BStr, delegate: &mut InterceptRev<'_, T>) -> Result<&'a BStr, Exn<Error>>
571
3.87k
where
572
3.87k
    T: Delegate,
573
{
574
    use delegate::{Kind, Navigate, Revision};
575
3.87k
    let mut cursor = 0;
576
3.87k
    let done_msg = "navigation succeeded, but no revision was produced as intermediate step";
577
24.4k
    while let Some(b) = input.get(cursor) {
578
22.3k
        cursor += 1;
579
22.3k
        match *b {
580
            b'~' => {
581
3.94k
                let (number, consumed) = input
582
3.94k
                    .get(cursor..)
583
3.94k
                    .and_then(|past_sep| try_parse_usize(past_sep.as_bstr()).transpose())
584
3.94k
                    .transpose()?
585
3.86k
                    .unwrap_or((1, 0));
586
3.86k
                if number != 0 {
587
2.81k
                    let traversal = delegate::Traversal::NthAncestor(number);
588
2.81k
                    delegate.traverse(traversal).or_raise(|| {
589
                        Error::new_with_input(format!("delegate.traverse({traversal:?}) failed"), input)
590
0
                    })?;
591
1.04k
                }
592
3.86k
                cursor += consumed;
593
            }
594
            b'^' => {
595
17.5k
                let past_sep = input.get(cursor..);
596
17.5k
                if let Some((number, negative, consumed)) = past_sep
597
17.5k
                    .and_then(|past_sep| try_parse_isize(past_sep.as_bstr()).transpose())
598
17.5k
                    .transpose()?
599
                {
600
3.66k
                    if negative {
601
273
                        let traversal = delegate::Traversal::NthParent(
602
306
                            number
603
306
                                .checked_mul(-1)
604
306
                                .ok_or_else(|| {
605
                                    Error::new_with_input("could not parse number", past_sep.expect("present"))
606
33
                                })?
607
273
                                .try_into()
608
273
                                .expect("non-negative"),
609
                        );
610
273
                        delegate.traverse(traversal).or_raise(|| {
611
                            Error::new_with_input(
612
                                "delegate.traverse({traversal:?}) failed",
613
                                past_sep.unwrap_or_default(),
614
                            )
615
0
                        })?;
616
273
                        let kind = spec::Kind::RangeBetween;
617
273
                        delegate.kind(kind).or_raise(|| {
618
                            Error::new_with_input(
619
                                format!("delegate.kind({kind:?}) failed"),
620
                                past_sep.unwrap_or_default(),
621
                            )
622
0
                        })?;
623
273
                        if let Some((prefix, hint)) = delegate.last_prefix.take() {
624
91
                            match &hint {
625
85
                                Some(hint) => delegate.disambiguate_prefix(prefix, hint.to_ref().into()),
626
6
                                None => delegate.disambiguate_prefix(prefix, None),
627
                            }
628
91
                            .or_raise(|| {
629
                                Error::new_with_input(
630
                                    format!("delegate.disambiguate_prefix({hint:?}) failed"),
631
                                    past_sep.unwrap_or_default(),
632
                                )
633
0
                            })?;
634
182
                        } else if let Some(name) = delegate.last_ref.take() {
635
175
                            delegate.find_ref(name.as_bstr()).or_raise(|| {
636
                                Error::new_with_input(
637
                                    format!("delegate.find_ref({name}) failed"),
638
                                    past_sep.unwrap_or_default(),
639
                                )
640
0
                            })?;
641
                        } else {
642
7
                            return Err(Error::new_with_input("unconsumed input", &input[cursor..]).raise());
643
                        }
644
266
                        cursor += consumed;
645
266
                        let rest = input[cursor..].as_bstr();
646
266
                        delegate.done().or_raise(|| Error::new_with_input(done_msg, rest))?;
647
266
                        return Ok(rest);
648
3.36k
                    } else if number == 0 {
649
1.48k
                        delegate.peel_until(delegate::PeelTo::ObjectKind(gix_object::Kind::Commit))
650
                    } else {
651
1.87k
                        delegate.traverse(delegate::Traversal::NthParent(
652
1.87k
                            number.try_into().expect("positive number"),
653
1.87k
                        ))
654
                    }
655
3.36k
                    .or_raise(|| Error::new_with_input("unknown navigation", past_sep.unwrap_or_default()))?;
656
3.36k
                    cursor += consumed;
657
4.20k
                } else if let Some((kind, _rest, consumed)) =
658
13.7k
                    past_sep.and_then(|past_sep| parens(past_sep).transpose()).transpose()?
659
                {
660
4.20k
                    cursor += consumed;
661
4.20k
                    let target = match kind.as_ref().as_bytes() {
662
4.20k
                        b"commit" => delegate::PeelTo::ObjectKind(gix_object::Kind::Commit),
663
3.50k
                        b"tag" => delegate::PeelTo::ObjectKind(gix_object::Kind::Tag),
664
2.56k
                        b"tree" => delegate::PeelTo::ObjectKind(gix_object::Kind::Tree),
665
201
                        b"blob" => delegate::PeelTo::ObjectKind(gix_object::Kind::Blob),
666
209
                        b"object" => delegate::PeelTo::ValidObject,
667
1.77k
                        b"" => delegate::PeelTo::RecursiveTagObject,
668
2.99k
                        regex if regex.starts_with(b"/") => {
669
2.76k
                            let (regex, negated) = parse_regex_prefix(regex[1..].as_bstr())?;
670
2.70k
                            if !regex.is_empty() {
671
2.26k
                                delegate.find(regex, negated).or_raise(|| {
672
                                    Error::new(format!("Delegate couldn't find '{regex}' (negated: {negated})"))
673
0
                                })?;
674
445
                            }
675
2.70k
                            continue;
676
                        }
677
222
                        invalid => return Err(Error::new_with_input("cannot peel to unknown target", invalid).raise()),
678
                    };
679
1.21k
                    delegate.peel_until(target).or_raise(|| {
680
                        Error::new_with_input(
681
                            format!("delegate.peel_until({target:?}) failed"),
682
                            past_sep.unwrap_or_default(),
683
                        )
684
0
                    })?;
685
9.53k
                } else if past_sep.and_then(<[_]>::first) == Some(&b'!') {
686
29
                    let rest = input[cursor + 1..].as_bstr();
687
29
                    let kind = spec::Kind::ExcludeReachableFromParents;
688
29
                    delegate
689
29
                        .kind(kind)
690
29
                        .or_raise(|| Error::new_with_input(format!("delegate.kind({kind:?}) failed"), rest))?;
691
29
                    delegate.done().or_raise(|| Error::new_with_input(done_msg, rest))?;
692
29
                    return Ok(rest);
693
9.50k
                } else if past_sep.and_then(<[_]>::first) == Some(&b'@') {
694
43
                    let rest = input[cursor + 1..].as_bstr();
695
43
                    let kind = spec::Kind::IncludeReachableFromParents;
696
43
                    delegate
697
43
                        .kind(kind)
698
43
                        .or_raise(|| Error::new_with_input(format!("delegate.kind({kind:?}) failed"), rest))?;
699
43
                    delegate.done().or_raise(|| Error::new_with_input(done_msg, rest))?;
700
43
                    return Ok(rest);
701
                } else {
702
9.46k
                    let parent = delegate::Traversal::NthParent(1);
703
9.46k
                    delegate.traverse(parent).or_raise(|| {
704
                        Error::new_with_input(
705
                            format!("delegate.parent({parent:?}) failed",),
706
                            past_sep.unwrap_or_default(),
707
                        )
708
0
                    })?;
709
                }
710
            }
711
            b':' => {
712
0
                let to = delegate::PeelTo::Path(input[cursor..].as_bstr());
713
0
                delegate
714
0
                    .peel_until(to)
715
0
                    .or_raise(|| Error::new(format!("delegate.peel_until({to:?}) failed")))?;
716
0
                return Ok("".into());
717
            }
718
874
            _ => return Ok(input[cursor - 1..].as_bstr()),
719
        }
720
    }
721
2.08k
    Ok("".into())
722
3.87k
}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>
gix_revision::spec::parse::function::navigate::<parse::Noop>
Line
Count
Source
570
4.32k
fn navigate<'a, T>(input: &'a BStr, delegate: &mut InterceptRev<'_, T>) -> Result<&'a BStr, Exn<Error>>
571
4.32k
where
572
4.32k
    T: Delegate,
573
{
574
    use delegate::{Kind, Navigate, Revision};
575
4.32k
    let mut cursor = 0;
576
4.32k
    let done_msg = "navigation succeeded, but no revision was produced as intermediate step";
577
42.6k
    while let Some(b) = input.get(cursor) {
578
40.3k
        cursor += 1;
579
40.3k
        match *b {
580
            b'~' => {
581
5.09k
                let (number, consumed) = input
582
5.09k
                    .get(cursor..)
583
5.09k
                    .and_then(|past_sep| try_parse_usize(past_sep.as_bstr()).transpose())
584
5.09k
                    .transpose()?
585
5.02k
                    .unwrap_or((1, 0));
586
5.02k
                if number != 0 {
587
3.39k
                    let traversal = delegate::Traversal::NthAncestor(number);
588
3.39k
                    delegate.traverse(traversal).or_raise(|| {
589
                        Error::new_with_input(format!("delegate.traverse({traversal:?}) failed"), input)
590
0
                    })?;
591
1.62k
                }
592
5.02k
                cursor += consumed;
593
            }
594
            b'^' => {
595
34.0k
                let past_sep = input.get(cursor..);
596
34.0k
                if let Some((number, negative, consumed)) = past_sep
597
34.0k
                    .and_then(|past_sep| try_parse_isize(past_sep.as_bstr()).transpose())
598
34.0k
                    .transpose()?
599
                {
600
7.96k
                    if negative {
601
274
                        let traversal = delegate::Traversal::NthParent(
602
291
                            number
603
291
                                .checked_mul(-1)
604
291
                                .ok_or_else(|| {
605
                                    Error::new_with_input("could not parse number", past_sep.expect("present"))
606
17
                                })?
607
274
                                .try_into()
608
274
                                .expect("non-negative"),
609
                        );
610
274
                        delegate.traverse(traversal).or_raise(|| {
611
                            Error::new_with_input(
612
                                "delegate.traverse({traversal:?}) failed",
613
                                past_sep.unwrap_or_default(),
614
                            )
615
0
                        })?;
616
274
                        let kind = spec::Kind::RangeBetween;
617
274
                        delegate.kind(kind).or_raise(|| {
618
                            Error::new_with_input(
619
                                format!("delegate.kind({kind:?}) failed"),
620
                                past_sep.unwrap_or_default(),
621
                            )
622
0
                        })?;
623
274
                        if let Some((prefix, hint)) = delegate.last_prefix.take() {
624
83
                            match &hint {
625
79
                                Some(hint) => delegate.disambiguate_prefix(prefix, hint.to_ref().into()),
626
4
                                None => delegate.disambiguate_prefix(prefix, None),
627
                            }
628
83
                            .or_raise(|| {
629
                                Error::new_with_input(
630
                                    format!("delegate.disambiguate_prefix({hint:?}) failed"),
631
                                    past_sep.unwrap_or_default(),
632
                                )
633
0
                            })?;
634
191
                        } else if let Some(name) = delegate.last_ref.take() {
635
179
                            delegate.find_ref(name.as_bstr()).or_raise(|| {
636
                                Error::new_with_input(
637
                                    format!("delegate.find_ref({name}) failed"),
638
                                    past_sep.unwrap_or_default(),
639
                                )
640
0
                            })?;
641
                        } else {
642
12
                            return Err(Error::new_with_input("unconsumed input", &input[cursor..]).raise());
643
                        }
644
262
                        cursor += consumed;
645
262
                        let rest = input[cursor..].as_bstr();
646
262
                        delegate.done().or_raise(|| Error::new_with_input(done_msg, rest))?;
647
262
                        return Ok(rest);
648
7.67k
                    } else if number == 0 {
649
1.77k
                        delegate.peel_until(delegate::PeelTo::ObjectKind(gix_object::Kind::Commit))
650
                    } else {
651
5.90k
                        delegate.traverse(delegate::Traversal::NthParent(
652
5.90k
                            number.try_into().expect("positive number"),
653
5.90k
                        ))
654
                    }
655
7.67k
                    .or_raise(|| Error::new_with_input("unknown navigation", past_sep.unwrap_or_default()))?;
656
7.67k
                    cursor += consumed;
657
3.90k
                } else if let Some((kind, _rest, consumed)) =
658
25.8k
                    past_sep.and_then(|past_sep| parens(past_sep).transpose()).transpose()?
659
                {
660
3.90k
                    cursor += consumed;
661
3.90k
                    let target = match kind.as_ref().as_bytes() {
662
3.90k
                        b"commit" => delegate::PeelTo::ObjectKind(gix_object::Kind::Commit),
663
3.23k
                        b"tag" => delegate::PeelTo::ObjectKind(gix_object::Kind::Tag),
664
2.32k
                        b"tree" => delegate::PeelTo::ObjectKind(gix_object::Kind::Tree),
665
202
                        b"blob" => delegate::PeelTo::ObjectKind(gix_object::Kind::Blob),
666
208
                        b"object" => delegate::PeelTo::ValidObject,
667
1.62k
                        b"" => delegate::PeelTo::RecursiveTagObject,
668
2.65k
                        regex if regex.starts_with(b"/") => {
669
2.44k
                            let (regex, negated) = parse_regex_prefix(regex[1..].as_bstr())?;
670
2.40k
                            if !regex.is_empty() {
671
1.99k
                                delegate.find(regex, negated).or_raise(|| {
672
                                    Error::new(format!("Delegate couldn't find '{regex}' (negated: {negated})"))
673
0
                                })?;
674
403
                            }
675
2.40k
                            continue;
676
                        }
677
205
                        invalid => return Err(Error::new_with_input("cannot peel to unknown target", invalid).raise()),
678
                    };
679
1.25k
                    delegate.peel_until(target).or_raise(|| {
680
                        Error::new_with_input(
681
                            format!("delegate.peel_until({target:?}) failed"),
682
                            past_sep.unwrap_or_default(),
683
                        )
684
0
                    })?;
685
21.9k
                } else if past_sep.and_then(<[_]>::first) == Some(&b'!') {
686
10
                    let rest = input[cursor + 1..].as_bstr();
687
10
                    let kind = spec::Kind::ExcludeReachableFromParents;
688
10
                    delegate
689
10
                        .kind(kind)
690
10
                        .or_raise(|| Error::new_with_input(format!("delegate.kind({kind:?}) failed"), rest))?;
691
10
                    delegate.done().or_raise(|| Error::new_with_input(done_msg, rest))?;
692
10
                    return Ok(rest);
693
21.9k
                } else if past_sep.and_then(<[_]>::first) == Some(&b'@') {
694
34
                    let rest = input[cursor + 1..].as_bstr();
695
34
                    let kind = spec::Kind::IncludeReachableFromParents;
696
34
                    delegate
697
34
                        .kind(kind)
698
34
                        .or_raise(|| Error::new_with_input(format!("delegate.kind({kind:?}) failed"), rest))?;
699
34
                    delegate.done().or_raise(|| Error::new_with_input(done_msg, rest))?;
700
34
                    return Ok(rest);
701
                } else {
702
21.9k
                    let parent = delegate::Traversal::NthParent(1);
703
21.9k
                    delegate.traverse(parent).or_raise(|| {
704
                        Error::new_with_input(
705
                            format!("delegate.parent({parent:?}) failed",),
706
                            past_sep.unwrap_or_default(),
707
                        )
708
0
                    })?;
709
                }
710
            }
711
            b':' => {
712
21
                let to = delegate::PeelTo::Path(input[cursor..].as_bstr());
713
21
                delegate
714
21
                    .peel_until(to)
715
21
                    .or_raise(|| Error::new(format!("delegate.peel_until({to:?}) failed")))?;
716
21
                return Ok("".into());
717
            }
718
1.23k
            _ => return Ok(input[cursor - 1..].as_bstr()),
719
        }
720
    }
721
2.23k
    Ok("".into())
722
4.32k
}
Unexecuted instantiation: gix_revision::spec::parse::function::navigate::<_>
723
724
5.24k
fn parse_regex_prefix(regex: &BStr) -> Result<(&BStr, bool), Error> {
725
5.24k
    Ok(match regex.strip_prefix(b"!") {
726
1.47k
        Some(regex) if regex.first() == Some(&b'!') => (regex.as_bstr(), false),
727
1.00k
        Some(regex) if regex.first() == Some(&b'-') => (regex[1..].as_bstr(), true),
728
120
        Some(_regex) => return Err(Error::new_with_input("need one character after /!, typically -", regex)),
729
3.76k
        None => (regex, false),
730
    })
731
5.24k
}
gix_revision::spec::parse::function::parse_regex_prefix
Line
Count
Source
724
2.76k
fn parse_regex_prefix(regex: &BStr) -> Result<(&BStr, bool), Error> {
725
2.76k
    Ok(match regex.strip_prefix(b"!") {
726
859
        Some(regex) if regex.first() == Some(&b'!') => (regex.as_bstr(), false),
727
590
        Some(regex) if regex.first() == Some(&b'-') => (regex[1..].as_bstr(), true),
728
61
        Some(_regex) => return Err(Error::new_with_input("need one character after /!, typically -", regex)),
729
1.90k
        None => (regex, false),
730
    })
731
2.76k
}
Unexecuted instantiation: gix_revision::spec::parse::function::parse_regex_prefix
gix_revision::spec::parse::function::parse_regex_prefix
Line
Count
Source
724
2.47k
fn parse_regex_prefix(regex: &BStr) -> Result<(&BStr, bool), Error> {
725
2.47k
    Ok(match regex.strip_prefix(b"!") {
726
618
        Some(regex) if regex.first() == Some(&b'!') => (regex.as_bstr(), false),
727
410
        Some(regex) if regex.first() == Some(&b'-') => (regex[1..].as_bstr(), true),
728
59
        Some(_regex) => return Err(Error::new_with_input("need one character after /!, typically -", regex)),
729
1.85k
        None => (regex, false),
730
    })
731
2.47k
}
732
733
9.04k
fn try_parse_usize(input: &BStr) -> Result<Option<(usize, usize)>, Error> {
734
9.04k
    let mut bytes = input.iter().peekable();
735
9.04k
    if bytes.peek().filter(|&&&b| b == b'-' || b == b'+').is_some() {
gix_revision::spec::parse::function::try_parse_usize::{closure#0}
Line
Count
Source
735
3.90k
    if bytes.peek().filter(|&&&b| b == b'-' || b == b'+').is_some() {
Unexecuted instantiation: gix_revision::spec::parse::function::try_parse_usize::{closure#0}
gix_revision::spec::parse::function::try_parse_usize::{closure#0}
Line
Count
Source
735
5.07k
    if bytes.peek().filter(|&&&b| b == b'-' || b == b'+').is_some() {
736
84
        return Err(Error::new_with_input(
737
84
            "negative or explicitly positive numbers are invalid here",
738
84
            input,
739
84
        ));
740
8.96k
    }
741
7.57M
    let num_digits = bytes.take_while(|b| b.is_ascii_digit()).count();
gix_revision::spec::parse::function::try_parse_usize::{closure#1}
Line
Count
Source
741
3.92M
    let num_digits = bytes.take_while(|b| b.is_ascii_digit()).count();
Unexecuted instantiation: gix_revision::spec::parse::function::try_parse_usize::{closure#1}
gix_revision::spec::parse::function::try_parse_usize::{closure#1}
Line
Count
Source
741
3.64M
    let num_digits = bytes.take_while(|b| b.is_ascii_digit()).count();
742
8.96k
    if num_digits == 0 {
743
2.44k
        return Ok(None);
744
6.51k
    }
745
6.51k
    let input = &input[..num_digits];
746
6.51k
    let number = try_parse(input)?.ok_or_else(|| Error::new_with_input("could not parse number", input))?;
gix_revision::spec::parse::function::try_parse_usize::{closure#2}
Line
Count
Source
746
42
    let number = try_parse(input)?.ok_or_else(|| Error::new_with_input("could not parse number", input))?;
Unexecuted instantiation: gix_revision::spec::parse::function::try_parse_usize::{closure#2}
gix_revision::spec::parse::function::try_parse_usize::{closure#2}
Line
Count
Source
746
41
    let number = try_parse(input)?.ok_or_else(|| Error::new_with_input("could not parse number", input))?;
747
6.43k
    Ok(Some((number, num_digits)))
748
9.04k
}
gix_revision::spec::parse::function::try_parse_usize
Line
Count
Source
733
3.94k
fn try_parse_usize(input: &BStr) -> Result<Option<(usize, usize)>, Error> {
734
3.94k
    let mut bytes = input.iter().peekable();
735
3.94k
    if bytes.peek().filter(|&&&b| b == b'-' || b == b'+').is_some() {
736
47
        return Err(Error::new_with_input(
737
47
            "negative or explicitly positive numbers are invalid here",
738
47
            input,
739
47
        ));
740
3.90k
    }
741
3.90k
    let num_digits = bytes.take_while(|b| b.is_ascii_digit()).count();
742
3.90k
    if num_digits == 0 {
743
1.49k
        return Ok(None);
744
2.41k
    }
745
2.41k
    let input = &input[..num_digits];
746
2.41k
    let number = try_parse(input)?.ok_or_else(|| Error::new_with_input("could not parse number", input))?;
747
2.37k
    Ok(Some((number, num_digits)))
748
3.94k
}
Unexecuted instantiation: gix_revision::spec::parse::function::try_parse_usize
gix_revision::spec::parse::function::try_parse_usize
Line
Count
Source
733
5.09k
fn try_parse_usize(input: &BStr) -> Result<Option<(usize, usize)>, Error> {
734
5.09k
    let mut bytes = input.iter().peekable();
735
5.09k
    if bytes.peek().filter(|&&&b| b == b'-' || b == b'+').is_some() {
736
37
        return Err(Error::new_with_input(
737
37
            "negative or explicitly positive numbers are invalid here",
738
37
            input,
739
37
        ));
740
5.06k
    }
741
5.06k
    let num_digits = bytes.take_while(|b| b.is_ascii_digit()).count();
742
5.06k
    if num_digits == 0 {
743
955
        return Ok(None);
744
4.10k
    }
745
4.10k
    let input = &input[..num_digits];
746
4.10k
    let number = try_parse(input)?.ok_or_else(|| Error::new_with_input("could not parse number", input))?;
747
4.06k
    Ok(Some((number, num_digits)))
748
5.09k
}
749
750
51.5k
fn try_parse_isize(input: &BStr) -> Result<Option<(isize, bool, usize)>, Error> {
751
51.5k
    let mut bytes = input.iter().peekable();
752
51.5k
    if bytes.peek().filter(|&&&b| b == b'+').is_some() {
gix_revision::spec::parse::function::try_parse_isize::{closure#0}
Line
Count
Source
752
17.5k
    if bytes.peek().filter(|&&&b| b == b'+').is_some() {
Unexecuted instantiation: gix_revision::spec::parse::function::try_parse_isize::{closure#0}
gix_revision::spec::parse::function::try_parse_isize::{closure#0}
Line
Count
Source
752
33.9k
    if bytes.peek().filter(|&&&b| b == b'+').is_some() {
753
72
        return Err(Error::new_with_input(
754
72
            "explicitly positive numbers are invalid here",
755
72
            input,
756
72
        ));
757
51.5k
    }
758
51.5k
    let negative = bytes.peek() == Some(&&b'-');
759
10.1M
    let num_digits = bytes.take_while(|b| b.is_ascii_digit() || *b == &b'-').count();
gix_revision::spec::parse::function::try_parse_isize::{closure#1}
Line
Count
Source
759
4.17M
    let num_digits = bytes.take_while(|b| b.is_ascii_digit() || *b == &b'-').count();
Unexecuted instantiation: gix_revision::spec::parse::function::try_parse_isize::{closure#1}
gix_revision::spec::parse::function::try_parse_isize::{closure#1}
Line
Count
Source
759
5.98M
    let num_digits = bytes.take_while(|b| b.is_ascii_digit() || *b == &b'-').count();
760
51.5k
    if num_digits == 0 {
761
39.6k
        return Ok(None);
762
11.8k
    } else if num_digits == 1 && negative {
763
228
        return Ok(Some((-1, negative, num_digits)));
764
11.6k
    }
765
11.6k
    let input = &input[..num_digits];
766
11.6k
    let number = try_parse(input)?.ok_or_else(|| Error::new_with_input("could not parse number", input))?;
gix_revision::spec::parse::function::try_parse_isize::{closure#2}
Line
Count
Source
766
73
    let number = try_parse(input)?.ok_or_else(|| Error::new_with_input("could not parse number", input))?;
Unexecuted instantiation: gix_revision::spec::parse::function::try_parse_isize::{closure#2}
gix_revision::spec::parse::function::try_parse_isize::{closure#2}
Line
Count
Source
766
82
    let number = try_parse(input)?.ok_or_else(|| Error::new_with_input("could not parse number", input))?;
767
11.4k
    Ok(Some((number, negative, num_digits)))
768
51.5k
}
gix_revision::spec::parse::function::try_parse_isize
Line
Count
Source
750
17.5k
fn try_parse_isize(input: &BStr) -> Result<Option<(isize, bool, usize)>, Error> {
751
17.5k
    let mut bytes = input.iter().peekable();
752
17.5k
    if bytes.peek().filter(|&&&b| b == b'+').is_some() {
753
34
        return Err(Error::new_with_input(
754
34
            "explicitly positive numbers are invalid here",
755
34
            input,
756
34
        ));
757
17.5k
    }
758
17.5k
    let negative = bytes.peek() == Some(&&b'-');
759
17.5k
    let num_digits = bytes.take_while(|b| b.is_ascii_digit() || *b == &b'-').count();
760
17.5k
    if num_digits == 0 {
761
13.7k
        return Ok(None);
762
3.77k
    } else if num_digits == 1 && negative {
763
114
        return Ok(Some((-1, negative, num_digits)));
764
3.65k
    }
765
3.65k
    let input = &input[..num_digits];
766
3.65k
    let number = try_parse(input)?.ok_or_else(|| Error::new_with_input("could not parse number", input))?;
767
3.55k
    Ok(Some((number, negative, num_digits)))
768
17.5k
}
Unexecuted instantiation: gix_revision::spec::parse::function::try_parse_isize
gix_revision::spec::parse::function::try_parse_isize
Line
Count
Source
750
34.0k
fn try_parse_isize(input: &BStr) -> Result<Option<(isize, bool, usize)>, Error> {
751
34.0k
    let mut bytes = input.iter().peekable();
752
34.0k
    if bytes.peek().filter(|&&&b| b == b'+').is_some() {
753
38
        return Err(Error::new_with_input(
754
38
            "explicitly positive numbers are invalid here",
755
38
            input,
756
38
        ));
757
33.9k
    }
758
33.9k
    let negative = bytes.peek() == Some(&&b'-');
759
33.9k
    let num_digits = bytes.take_while(|b| b.is_ascii_digit() || *b == &b'-').count();
760
33.9k
    if num_digits == 0 {
761
25.8k
        return Ok(None);
762
8.08k
    } else if num_digits == 1 && negative {
763
114
        return Ok(Some((-1, negative, num_digits)));
764
7.96k
    }
765
7.96k
    let input = &input[..num_digits];
766
7.96k
    let number = try_parse(input)?.ok_or_else(|| Error::new_with_input("could not parse number", input))?;
767
7.85k
    Ok(Some((number, negative, num_digits)))
768
34.0k
}
769
770
5.98k
fn try_range(input: &BStr) -> Option<(&[u8], spec::Kind)> {
771
5.98k
    input
772
5.98k
        .strip_prefix(b"...")
773
5.98k
        .map(|rest| (rest, spec::Kind::ReachableToMergeBase))
gix_revision::spec::parse::function::try_range::{closure#0}
Line
Count
Source
773
40
        .map(|rest| (rest, spec::Kind::ReachableToMergeBase))
Unexecuted instantiation: gix_revision::spec::parse::function::try_range::{closure#0}
gix_revision::spec::parse::function::try_range::{closure#0}
Line
Count
Source
773
60
        .map(|rest| (rest, spec::Kind::ReachableToMergeBase))
774
5.98k
        .or_else(|| input.strip_prefix(b"..").map(|rest| (rest, spec::Kind::RangeBetween)))
gix_revision::spec::parse::function::try_range::{closure#1}
Line
Count
Source
774
2.67k
        .or_else(|| input.strip_prefix(b"..").map(|rest| (rest, spec::Kind::RangeBetween)))
Unexecuted instantiation: gix_revision::spec::parse::function::try_range::{closure#1}
gix_revision::spec::parse::function::try_range::{closure#1}
Line
Count
Source
774
3.20k
        .or_else(|| input.strip_prefix(b"..").map(|rest| (rest, spec::Kind::RangeBetween)))
gix_revision::spec::parse::function::try_range::{closure#1}::{closure#0}
Line
Count
Source
774
534
        .or_else(|| input.strip_prefix(b"..").map(|rest| (rest, spec::Kind::RangeBetween)))
Unexecuted instantiation: gix_revision::spec::parse::function::try_range::{closure#1}::{closure#0}
gix_revision::spec::parse::function::try_range::{closure#1}::{closure#0}
Line
Count
Source
774
828
        .or_else(|| input.strip_prefix(b"..").map(|rest| (rest, spec::Kind::RangeBetween)))
775
5.98k
}
gix_revision::spec::parse::function::try_range
Line
Count
Source
770
2.71k
fn try_range(input: &BStr) -> Option<(&[u8], spec::Kind)> {
771
2.71k
    input
772
2.71k
        .strip_prefix(b"...")
773
2.71k
        .map(|rest| (rest, spec::Kind::ReachableToMergeBase))
774
2.71k
        .or_else(|| input.strip_prefix(b"..").map(|rest| (rest, spec::Kind::RangeBetween)))
775
2.71k
}
Unexecuted instantiation: gix_revision::spec::parse::function::try_range
gix_revision::spec::parse::function::try_range
Line
Count
Source
770
3.26k
fn try_range(input: &BStr) -> Option<(&[u8], spec::Kind)> {
771
3.26k
    input
772
3.26k
        .strip_prefix(b"...")
773
3.26k
        .map(|rest| (rest, spec::Kind::ReachableToMergeBase))
774
3.26k
        .or_else(|| input.strip_prefix(b"..").map(|rest| (rest, spec::Kind::RangeBetween)))
775
3.26k
}
776
777
114
fn next(i: &BStr) -> (u8, &BStr) {
778
114
    let b = i[0];
779
114
    (b, i[1..].as_bstr())
780
114
}
gix_revision::spec::parse::function::next
Line
Count
Source
777
14
fn next(i: &BStr) -> (u8, &BStr) {
778
14
    let b = i[0];
779
14
    (b, i[1..].as_bstr())
780
14
}
Unexecuted instantiation: gix_revision::spec::parse::function::next
gix_revision::spec::parse::function::next
Line
Count
Source
777
100
fn next(i: &BStr) -> (u8, &BStr) {
778
100
    let b = i[0];
779
100
    (b, i[1..].as_bstr())
780
100
}