Skip to main content

pedant_types/resolution/
span.rs

1//! Where a definition or reference sits in the snapshotted source.
2
3use std::sync::Arc;
4
5use serde::{Deserialize, Serialize};
6
7/// A zero-based point in one source file.
8///
9/// A column counts UTF-8 bytes from the first byte after the preceding `\n`, so
10/// a `\r` in a CRLF pair is an ordinary byte. Both coordinates are `u32` so a
11/// serialized report reads the same on every platform.
12#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
13#[serde(deny_unknown_fields)]
14pub struct SourcePosition {
15    line: u32,
16    column: u32,
17}
18
19impl SourcePosition {
20    /// A point at a zero-based line and UTF-8 byte column.
21    pub fn new(line: u32, column: u32) -> Self {
22        Self { line, column }
23    }
24
25    /// The zero-based line.
26    pub fn line(self) -> u32 {
27        self.line
28    }
29
30    /// The zero-based UTF-8 byte column.
31    pub fn column(self) -> u32 {
32        self.column
33    }
34}
35
36/// A half-open range in one normalized repository-relative file.
37///
38/// The derived ordering is the report's structural sort key for sites: file,
39/// then start, then end.
40#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
41#[serde(deny_unknown_fields)]
42pub struct SourceSpan {
43    file: Arc<str>,
44    start: SourcePosition,
45    end: SourcePosition,
46}
47
48impl SourceSpan {
49    /// A span over `file`, from `start` up to but excluding `end`.
50    ///
51    /// The path is validated when the report is constructed, so one file value
52    /// shared by many sites is checked once per site rather than at every clone.
53    pub fn new(file: Arc<str>, start: SourcePosition, end: SourcePosition) -> Self {
54        Self { file, start, end }
55    }
56
57    /// The normalized repository-relative path.
58    pub fn file(&self) -> &str {
59        &self.file
60    }
61
62    /// The shared path value itself, for a decoder pointing many spans at one.
63    pub(super) fn shared_file(&self) -> &Arc<str> {
64        &self.file
65    }
66
67    /// Adopt an equal path value that other spans already share.
68    ///
69    /// Serde allocates one path per span on the way in, which is the opposite
70    /// of what this type is for, so the decoder replaces each with the one
71    /// canonical value before the report exists.
72    pub(super) fn adopt_file(&mut self, file: Arc<str>) {
73        self.file = file;
74    }
75
76    /// The inclusive start point.
77    pub fn start(&self) -> SourcePosition {
78        self.start
79    }
80
81    /// The exclusive end point.
82    pub fn end(&self) -> SourcePosition {
83        self.end
84    }
85}