cedar_policy_core/parser/
loc.rs1use std::sync::Arc;
18
19#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
22pub struct Loc {
23 pub span: miette::SourceSpan,
25
26 pub src: Arc<str>,
28}
29
30impl Loc {
31 pub fn new(span: impl Into<miette::SourceSpan>, src: Arc<str>) -> Self {
33 Self {
34 span: span.into(),
35 src,
36 }
37 }
38
39 pub fn span(&self, span: impl Into<miette::SourceSpan>) -> Self {
41 Self {
42 span: span.into(),
43 src: Arc::clone(&self.src),
44 }
45 }
46
47 pub fn start(&self) -> usize {
49 self.span.offset()
50 }
51
52 pub fn end(&self) -> usize {
54 self.span.offset() + self.span.len()
55 }
56
57 pub fn snippet(&self) -> Option<&str> {
61 self.src.get(self.start()..self.end())
62 }
63}
64
65impl From<Loc> for miette::SourceSpan {
66 fn from(loc: Loc) -> Self {
67 loc.span
68 }
69}
70
71impl From<&Loc> for miette::SourceSpan {
72 fn from(loc: &Loc) -> Self {
73 loc.span
74 }
75}
76
77impl miette::SourceCode for Loc {
78 fn read_span<'a>(
79 &'a self,
80 span: &miette::SourceSpan,
81 context_lines_before: usize,
82 context_lines_after: usize,
83 ) -> Result<Box<dyn miette::SpanContents<'a> + 'a>, miette::MietteError> {
84 self.src
85 .read_span(span, context_lines_before, context_lines_after)
86 }
87}
88
89impl miette::SourceCode for &Loc {
90 fn read_span<'a>(
91 &'a self,
92 span: &miette::SourceSpan,
93 context_lines_before: usize,
94 context_lines_after: usize,
95 ) -> Result<Box<dyn miette::SpanContents<'a> + 'a>, miette::MietteError> {
96 self.src
97 .read_span(span, context_lines_before, context_lines_after)
98 }
99}
100
101impl std::fmt::Debug for Loc {
102 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
103 match self.snippet() {
104 Some(snippet) => write!(f, r#"Loc(`{snippet}`)"#),
105 None => write!(
106 f,
107 r#"Loc(span: {:?}, src: "{}")"#,
108 self.span,
109 self.src.escape_debug()
110 ),
111 }
112 }
113}
114
115mod test {
116 #[test]
117 fn test_loc_debug() {
118 let str: std::sync::Arc<str> =
119 r#"permit(principal, action, resource) when { a == b && b == "c" }"#.into();
120 let l = super::Loc::new(43..49, str.clone());
121 let l2 = super::Loc::new(53..61, str);
122 assert_eq!(format!("{l:?}"), r#"Loc(`a == b`)"#);
123 assert_eq!(format!("{l2:?}"), r#"Loc(`b == "c"`)"#);
124 }
125}