Skip to main content

miden_debug_types/
location.rs

1use core::{fmt, ops::Range};
2
3use miden_crypto::utils::{
4    ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable,
5};
6#[cfg(feature = "arbitrary")]
7use proptest::prelude::*;
8#[cfg(feature = "serde")]
9use serde::{Deserialize, Serialize};
10
11use super::{
12    ByteIndex, Uri,
13    source_file::{ColumnNumber, LineNumber},
14};
15
16/// A [Location] represents file and span information for portability across source managers
17#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
18#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
19#[cfg_attr(
20    all(feature = "arbitrary", test),
21    miden_test_serialization_macros::serialization_test
22)]
23pub struct Location {
24    /// The path to the source file in which the relevant source code can be found
25    pub uri: Uri,
26    /// The starting byte index (inclusive) of this location
27    pub start: ByteIndex,
28    /// The ending byte index (exclusive) of this location
29    pub end: ByteIndex,
30}
31
32impl Location {
33    /// Creates a new [Location].
34    pub const fn new(uri: Uri, start: ByteIndex, end: ByteIndex) -> Self {
35        Self { uri, start, end }
36    }
37
38    /// Get the name (or path) of the source file
39    pub fn uri(&self) -> &Uri {
40        &self.uri
41    }
42
43    /// Returns the byte range represented by this location
44    pub const fn range(&self) -> Range<ByteIndex> {
45        self.start..self.end
46    }
47}
48
49impl Serializable for Location {
50    fn write_into<W: ByteWriter>(&self, target: &mut W) {
51        self.uri.write_into(target);
52        self.start.to_u32().write_into(target);
53        self.end.to_u32().write_into(target);
54    }
55}
56
57impl Deserializable for Location {
58    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
59        let uri = Uri::read_from(source)?;
60        let start = ByteIndex::from(source.read_u32()?);
61        let end = ByteIndex::from(source.read_u32()?);
62        Ok(Self::new(uri, start, end))
63    }
64}
65
66/// A [FileLineCol] represents traditional file/line/column information for use in rendering.
67#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
68#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
69#[cfg_attr(
70    all(feature = "arbitrary", test),
71    miden_test_serialization_macros::serialization_test
72)]
73pub struct FileLineCol {
74    /// The path to the source file in which the relevant source code can be found
75    pub uri: Uri,
76    /// The one-indexed number of the line to which this location refers
77    pub line: LineNumber,
78    /// The one-indexed column of the line on which this location starts
79    pub column: ColumnNumber,
80}
81
82impl FileLineCol {
83    /// Creates a new [Location].
84    pub fn new(
85        uri: impl Into<Uri>,
86        line: impl Into<LineNumber>,
87        column: impl Into<ColumnNumber>,
88    ) -> Self {
89        Self {
90            uri: uri.into(),
91            line: line.into(),
92            column: column.into(),
93        }
94    }
95
96    /// Get the name (or path) of the source file
97    pub fn uri(&self) -> &Uri {
98        &self.uri
99    }
100
101    /// Returns the line of the location.
102    pub const fn line(&self) -> LineNumber {
103        self.line
104    }
105
106    /// Moves the column by the given offset.
107    pub fn move_column(&mut self, offset: i32) {
108        self.column += offset;
109    }
110}
111
112impl fmt::Display for FileLineCol {
113    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
114        write!(f, "[{}@{}:{}]", self.uri, self.line, self.column)
115    }
116}
117
118impl Serializable for FileLineCol {
119    fn write_into<W: ByteWriter>(&self, target: &mut W) {
120        self.uri.write_into(target);
121        self.line.write_into(target);
122        self.column.write_into(target);
123    }
124}
125
126impl Deserializable for FileLineCol {
127    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
128        let uri = Uri::read_from(source)?;
129        let line = LineNumber::read_from(source)?;
130        let column = ColumnNumber::read_from(source)?;
131        Ok(Self::new(uri, line, column))
132    }
133}
134
135#[cfg(feature = "arbitrary")]
136impl Arbitrary for Location {
137    type Parameters = ();
138    type Strategy = BoxedStrategy<Self>;
139
140    fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
141        (any::<Uri>(), any::<u32>(), any::<u32>())
142            .prop_map(|(uri, start, end)| {
143                let (start, end) = if start <= end { (start, end) } else { (end, start) };
144                Self::new(uri, ByteIndex::new(start), ByteIndex::new(end))
145            })
146            .boxed()
147    }
148}
149
150#[cfg(feature = "arbitrary")]
151impl Arbitrary for FileLineCol {
152    type Parameters = ();
153    type Strategy = BoxedStrategy<Self>;
154
155    fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
156        (any::<Uri>(), any::<LineNumber>(), any::<ColumnNumber>())
157            .prop_map(|(uri, line, column)| Self::new(uri, line, column))
158            .boxed()
159    }
160}