1 use crate::{MietteError, MietteSpanContents, SourceCode, SpanContents}; 2 3 /// Utility struct for when you have a regular [`SourceCode`] type that doesn't 4 /// implement `name`. For example [`String`]. Or if you want to override the 5 /// `name` returned by the `SourceCode`. 6 pub struct NamedSource<S: SourceCode + 'static> { 7 source: S, 8 name: String, 9 language: Option<String>, 10 } 11 12 impl<S: SourceCode> std::fmt::Debug for NamedSource<S> { fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result13 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 14 f.debug_struct("NamedSource") 15 .field("name", &self.name) 16 .field("source", &"<redacted>") 17 .field("language", &self.language); 18 Ok(()) 19 } 20 } 21 22 impl<S: SourceCode + 'static> NamedSource<S> { 23 /// Create a new `NamedSource` using a regular [`SourceCode`] and giving 24 /// its returned [`SpanContents`] a name. new(name: impl AsRef<str>, source: S) -> Self where S: Send + Sync,25 pub fn new(name: impl AsRef<str>, source: S) -> Self 26 where 27 S: Send + Sync, 28 { 29 Self { 30 source, 31 name: name.as_ref().to_string(), 32 language: None, 33 } 34 } 35 36 /// Gets the name of this `NamedSource`. name(&self) -> &str37 pub fn name(&self) -> &str { 38 &self.name 39 } 40 41 /// Returns a reference the inner [`SourceCode`] type for this 42 /// `NamedSource`. inner(&self) -> &S43 pub fn inner(&self) -> &S { 44 &self.source 45 } 46 47 /// Sets the [`language`](SpanContents::language) for this source code. with_language(mut self, language: impl Into<String>) -> Self48 pub fn with_language(mut self, language: impl Into<String>) -> Self { 49 self.language = Some(language.into()); 50 self 51 } 52 } 53 54 impl<S: SourceCode + 'static> SourceCode for NamedSource<S> { read_span<'a>( &'a self, span: &crate::SourceSpan, context_lines_before: usize, context_lines_after: usize, ) -> Result<Box<dyn SpanContents<'a> + 'a>, MietteError>55 fn read_span<'a>( 56 &'a self, 57 span: &crate::SourceSpan, 58 context_lines_before: usize, 59 context_lines_after: usize, 60 ) -> Result<Box<dyn SpanContents<'a> + 'a>, MietteError> { 61 let inner_contents = 62 self.inner() 63 .read_span(span, context_lines_before, context_lines_after)?; 64 let mut contents = MietteSpanContents::new_named( 65 self.name.clone(), 66 inner_contents.data(), 67 *inner_contents.span(), 68 inner_contents.line(), 69 inner_contents.column(), 70 inner_contents.line_count(), 71 ); 72 if let Some(language) = &self.language { 73 contents = contents.with_language(language); 74 } 75 Ok(Box::new(contents)) 76 } 77 } 78