Skip to main content

macroonz_compiler/token/capture/
fragment.rs

1//! Borrowed exact fragments of one normalized captured-token sequence.
2//!
3//! A fragment never copies or reparses source.
4//! It retains the captured tokens and producer span handles already owned by its source boundary, while canonical bytes continue to exclude producer-local coordinates.
5
6use super::{CapturedFragment, CapturedInput, CapturedTokenTree, SpanHandle};
7
8impl CapturedInput {
9    /// Borrow this complete captured input as one exact fragment.
10    #[must_use]
11    pub fn fragment(&self) -> CapturedFragment<'_> {
12        CapturedFragment::over(self.trees(), None)
13    }
14}
15
16impl CapturedTokenTree {
17    /// Borrow this token's grouped members as one exact fragment when its delimiter matches.
18    #[must_use]
19    pub fn group_fragment(
20        &self,
21        expected: super::CapturedDelimiter,
22    ) -> Option<CapturedFragment<'_>> {
23        self.group().and_then(|(delimiter, members)| {
24            (delimiter == expected).then(|| CapturedFragment::over(members, Some(self.span())))
25        })
26    }
27}
28
29impl<'tokens> CapturedFragment<'tokens> {
30    /// Construct one fragment inside the capture owner.
31    #[must_use]
32    pub(super) const fn over(
33        tokens: &'tokens [CapturedTokenTree],
34        end: Option<SpanHandle>,
35    ) -> Self {
36        Self { tokens, end }
37    }
38
39    /// The exact captured tokens this fragment borrows.
40    #[must_use]
41    pub const fn tokens(self) -> &'tokens [CapturedTokenTree] {
42        self.tokens
43    }
44
45    /// How many tokens this fragment carries at its current level.
46    #[must_use]
47    pub const fn len(self) -> usize {
48        self.tokens.len()
49    }
50
51    /// Whether this fragment carries no token at its current level.
52    #[must_use]
53    pub const fn is_empty(self) -> bool {
54        self.tokens.is_empty()
55    }
56
57    /// The first token's producer span, where the fragment is nonempty.
58    #[must_use]
59    pub fn first_span(self) -> Option<SpanHandle> {
60        self.tokens.first().map(CapturedTokenTree::span)
61    }
62
63    /// The last token's producer span, where the fragment is nonempty.
64    #[must_use]
65    pub fn last_span(self) -> Option<SpanHandle> {
66        self.tokens.last().map(CapturedTokenTree::span)
67    }
68
69    /// The enclosing group span used when a read reaches this fragment's end.
70    ///
71    /// A top-level fragment has no enclosing group and therefore answers `None`.
72    #[must_use]
73    pub const fn enclosing_span(self) -> Option<SpanHandle> {
74        self.end
75    }
76
77    /// The canonical captured bytes of exactly this fragment.
78    ///
79    /// Producer spans remain excluded, so a span-only movement does not move these bytes.
80    #[must_use]
81    pub fn canonical_bytes(self) -> Vec<u8> {
82        let mut bytes = Vec::new();
83        for token in self.tokens {
84            super::encode::encode_captured(token, &mut bytes);
85        }
86        bytes
87    }
88}