1use crate::{MietteError, MietteSpanContents, SourceCode, SpanContents};
2
3#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
7pub struct NamedSource<S: SourceCode + 'static> {
8 source: S,
9 name: String,
10 language: Option<String>,
11}
12
13impl<S: SourceCode> std::fmt::Debug for NamedSource<S> {
14 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
15 f.debug_struct("NamedSource")
16 .field("name", &self.name)
17 .field("source", &"<redacted>")
18 .field("language", &self.language);
19 Ok(())
20 }
21}
22
23impl<S: SourceCode + 'static> NamedSource<S> {
24 pub fn new(name: impl AsRef<str>, source: S) -> Self
27 where
28 S: Send + Sync,
29 {
30 Self {
31 source,
32 name: name.as_ref().to_string(),
33 language: None,
34 }
35 }
36
37 pub fn name(&self) -> &str {
39 &self.name
40 }
41
42 pub fn inner(&self) -> &S {
45 &self.source
46 }
47
48 pub fn with_language(mut self, language: impl Into<String>) -> Self {
50 self.language = Some(language.into());
51 self
52 }
53}
54
55impl<S: SourceCode + 'static> SourceCode for NamedSource<S> {
56 fn read_span<'a>(
57 &'a self,
58 span: &crate::SourceSpan,
59 context_lines_before: usize,
60 context_lines_after: usize,
61 ) -> Result<Box<dyn SpanContents<'a> + 'a>, MietteError> {
62 let inner_contents =
63 self.inner()
64 .read_span(span, context_lines_before, context_lines_after)?;
65 let mut contents = MietteSpanContents::new_named(
66 self.name.clone(),
67 inner_contents.data(),
68 *inner_contents.span(),
69 inner_contents.line(),
70 inner_contents.column(),
71 inner_contents.line_count(),
72 );
73 if let Some(language) = &self.language {
74 contents = contents.with_language(language);
75 }
76 Ok(Box::new(contents))
77 }
78}