error_snippet/
source.rs

1use std::path::PathBuf;
2
3use crate::Result;
4
5/// Defines a source file, which can be used to provide context for diagnostics.
6///
7/// This trait represents some sort of source code, which will be reported to the user as
8/// part of the reporting process.
9pub trait Source: Send + Sync + std::fmt::Debug {
10    /// Defines the name of the source file.
11    fn name(&self) -> Option<&str> {
12        None
13    }
14
15    /// Gets the full content of the source file.
16    fn content(&self) -> Box<&str>;
17}
18
19impl Source for [u8] {
20    fn content(&self) -> Box<&str> {
21        Box::new(std::str::from_utf8(self).unwrap())
22    }
23}
24
25impl Source for &[u8] {
26    fn content(&self) -> Box<&str> {
27        <[u8] as Source>::content(self)
28    }
29}
30
31impl Source for Vec<u8> {
32    fn content(&self) -> Box<&str> {
33        <[u8] as Source>::content(self)
34    }
35}
36
37impl Source for str {
38    fn content(&self) -> Box<&str> {
39        <[u8] as Source>::content(self.as_bytes())
40    }
41}
42
43impl Source for &str {
44    fn content(&self) -> Box<&str> {
45        <str as Source>::content(self)
46    }
47}
48
49impl Source for String {
50    fn content(&self) -> Box<&str> {
51        <str as Source>::content(self)
52    }
53}
54
55impl Source for &String {
56    fn content(&self) -> Box<&str> {
57        <String as Source>::content(self)
58    }
59}
60
61/// Represents a simple source with only string-based content.
62#[derive(Debug, Clone, PartialEq, Eq)]
63pub struct StringSource {
64    /// Defines the content of the source file.
65    pub content: String,
66}
67
68impl StringSource {
69    /// Creates a new [`StringSource`] from the content.
70    pub fn new(content: String) -> Self {
71        Self { content }
72    }
73}
74
75impl Source for StringSource {
76    fn name(&self) -> Option<&str> {
77        None
78    }
79
80    fn content(&self) -> Box<&str> {
81        Box::new(self.content.as_str())
82    }
83}
84
85/// Represents a source file with a name and content.
86///
87/// This is the default implementation of the [`Source`] trait and is used
88/// internally to create diagnostics using derive-macros.
89#[derive(Debug, Clone, PartialEq, Eq)]
90pub struct NamedSource {
91    /// Defines the name of the source file.
92    pub name: String,
93
94    /// Defines the content of the source file.
95    pub content: String,
96}
97
98impl NamedSource {
99    /// Creates a new [`NamedSource`] from the given name and content.
100    pub fn new(name: impl Into<String>, content: impl Into<String>) -> Self {
101        Self {
102            name: name.into(),
103            content: content.into(),
104        }
105    }
106
107    /// Creates a new [`NamedSource`] instance from an existing file.
108    pub fn from_file(path: PathBuf) -> Result<NamedSource> {
109        let name = path.to_string_lossy().to_string();
110        let content = std::fs::read_to_string(path)?;
111
112        Ok(NamedSource { name, content })
113    }
114}
115
116impl Source for NamedSource {
117    fn name(&self) -> Option<&str> {
118        Some(self.name.as_str())
119    }
120
121    fn content(&self) -> Box<&str> {
122        Box::new(self.content.as_str())
123    }
124}