Skip to main content

implicit_predicates_core/scratch/
span.rs

1//! Positions in an arena: spans of expansions and marks of the top.
2
3use core::ops::Range;
4
5/// The position of an expansion in a [`Scratch`](super::Scratch) arena.
6///
7/// Spans compare equal, and hash alike, when they have the same position and
8/// length, whatever their contents. A span is meaningful only for the arena that created it;
9/// see the [module documentation](crate::scratch).
10///
11/// # Examples
12///
13/// ```
14/// use implicit_predicates_core::Scratch;
15///
16/// let mut buf = [0.0; 4];
17/// let mut scratch = Scratch::borrowed(&mut buf);
18/// let span = scratch.push(&[1e-20, 1.0])?;
19/// assert_eq!(span.len(), 2);
20/// assert_eq!(scratch.get(span), &[1e-20, 1.0]);
21/// # Ok::<(), implicit_predicates_core::ScratchExhausted>(())
22/// ```
23#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
24pub struct Span {
25    pub(super) start: u32,
26    pub(super) len: u32,
27}
28
29/// A saved top of a [`Scratch`](super::Scratch) arena, to return to with
30/// [`Scratch::reset`](super::Scratch::reset). Marks compare equal when they
31/// save the same top.
32///
33/// # Examples
34///
35/// ```
36/// use implicit_predicates_core::Scratch;
37///
38/// let mut buf = [0.0; 4];
39/// let mut scratch = Scratch::borrowed(&mut buf);
40/// let mark = scratch.mark();
41/// scratch.push(&[1.0])?;
42/// assert_ne!(scratch.mark(), mark);
43/// scratch.reset(mark);
44/// assert_eq!(scratch.mark(), mark);
45/// assert_eq!(scratch.used(), 0);
46/// # Ok::<(), implicit_predicates_core::ScratchExhausted>(())
47/// ```
48#[derive(Clone, Copy, Debug, PartialEq, Eq)]
49pub struct Mark(pub(super) u32);
50
51impl Span {
52    /// Returns the number of components of the expansion.
53    ///
54    /// # Examples
55    ///
56    /// ```
57    /// use implicit_predicates_core::Scratch;
58    ///
59    /// let mut buf = [0.0; 2];
60    /// let mut scratch = Scratch::borrowed(&mut buf);
61    /// assert_eq!(scratch.push(&[1e-20, 1.0])?.len(), 2);
62    /// # Ok::<(), implicit_predicates_core::ScratchExhausted>(())
63    /// ```
64    #[must_use]
65    pub fn len(self) -> usize {
66        to_index(self.len)
67    }
68
69    /// Returns `true` if the expansion has no components, that is, if its
70    /// value is zero.
71    ///
72    /// # Examples
73    ///
74    /// ```
75    /// use implicit_predicates_core::Scratch;
76    ///
77    /// let mut buf = [0.0; 6];
78    /// let mut scratch = Scratch::borrowed(&mut buf);
79    /// let a = scratch.push(&[1e-20, 1.0])?;
80    /// assert!(scratch.diff(a, a)?.is_empty());
81    /// # Ok::<(), implicit_predicates_core::ScratchExhausted>(())
82    /// ```
83    #[must_use]
84    pub fn is_empty(self) -> bool {
85        self.len == 0
86    }
87
88    /// The indices of the components in the arena.
89    pub(super) fn range(self) -> Range<usize> {
90        let start = to_index(self.start);
91        start..start + to_index(self.len)
92    }
93}
94
95/// Converts an index within the arena, which never exceeds the length of
96/// its buffer, to `usize`.
97pub(super) fn to_index(i: u32) -> usize {
98    usize::try_from(i).expect("arena indices never exceed the buffer length")
99}