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}