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}