Skip to main content

source_lang/
error.rs

1//! The error type returned when a source cannot be added to a map.
2
3use core::fmt;
4
5/// The reason a source could not be added to a [`SourceMap`](crate::SourceMap).
6///
7/// Every source in a map shares one 32-bit global position space, so the
8/// combined byte length of all sources cannot exceed `u32::MAX`, and the map can
9/// hold at most `u32::MAX` distinct sources. Adding a source that would cross
10/// either limit fails with this error rather than wrapping a base offset into a
11/// neighbour's range — the one way the coordinate bookkeeping could otherwise
12/// corrupt silently.
13///
14/// The enum is `#[non_exhaustive]`: later phases add file-loading failures
15/// (missing path, oversize file) alongside this variant, and a `match` on it
16/// must already account for that.
17///
18/// # Examples
19///
20/// ```
21/// use source_lang::{SourceMap, SourceMapError};
22///
23/// // A map whose global space is almost full rejects a source that overruns it.
24/// let mut map = SourceMap::new();
25/// # // (the boundary itself needs ~4 GiB to reach naturally; see the unit tests)
26/// let id = map.add("ok.txt", "fits fine").expect("plenty of room");
27/// assert_eq!(map.source(id).map(|f| f.name()), Some("ok.txt"));
28/// ```
29#[derive(Clone, Copy, Debug, PartialEq, Eq)]
30#[non_exhaustive]
31pub enum SourceMapError {
32    /// The source did not fit in what remained of the map's capacity.
33    ///
34    /// Returned when the new source is larger than the bytes left in the global
35    /// position space — either because the single source exceeds `u32::MAX`
36    /// bytes, or because earlier sources have consumed the remainder — or when
37    /// the map already holds the maximum number of sources. The caller cannot
38    /// retry the same source against the same map; it must split the input or
39    /// start a fresh map.
40    SpaceExhausted {
41        /// Byte length of the source that was rejected.
42        needed: u64,
43        /// Bytes of global position space that remained available.
44        available: u64,
45    },
46}
47
48impl fmt::Display for SourceMapError {
49    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50        match *self {
51            Self::SpaceExhausted { needed, available } => write!(
52                f,
53                "source of {needed} bytes does not fit in the {available} bytes \
54                 remaining in the global position space",
55            ),
56        }
57    }
58}
59
60impl core::error::Error for SourceMapError {}
61
62#[cfg(test)]
63mod tests {
64    extern crate alloc;
65    use alloc::string::ToString;
66
67    use super::*;
68
69    #[test]
70    fn test_space_exhausted_display_names_both_figures() {
71        let err = SourceMapError::SpaceExhausted {
72            needed: 10,
73            available: 4,
74        };
75        let text = err.to_string();
76        assert!(text.contains("10 bytes"), "{text}");
77        assert!(text.contains("4 bytes"), "{text}");
78    }
79
80    #[test]
81    fn test_error_is_copy_and_equatable() {
82        let a = SourceMapError::SpaceExhausted {
83            needed: 1,
84            available: 0,
85        };
86        let b = a;
87        assert_eq!(a, b);
88    }
89}