Skip to main content

snapbox/data/
source.rs

1/// Origin of a snapshot so it can be updated
2#[derive(Clone, Debug, PartialEq, Eq)]
3pub struct DataSource {
4    pub(crate) inner: DataSourceInner,
5}
6
7#[derive(Clone, Debug, PartialEq, Eq)]
8pub(crate) enum DataSourceInner {
9    Path(std::path::PathBuf),
10    Inline(Inline),
11}
12
13impl DataSource {
14    pub fn path(path: impl Into<std::path::PathBuf>) -> Self {
15        Self {
16            inner: DataSourceInner::Path(path.into()),
17        }
18    }
19
20    pub fn is_path(&self) -> bool {
21        self.as_path().is_some()
22    }
23
24    pub fn as_path(&self) -> Option<&std::path::Path> {
25        match &self.inner {
26            DataSourceInner::Path(value) => Some(value.as_ref()),
27            _ => None,
28        }
29    }
30
31    pub fn is_inline(&self) -> bool {
32        self.as_inline().is_some()
33    }
34
35    pub fn as_inline(&self) -> Option<&Inline> {
36        match &self.inner {
37            DataSourceInner::Inline(value) => Some(value),
38            _ => None,
39        }
40    }
41}
42
43impl From<&'_ std::path::Path> for DataSource {
44    fn from(value: &'_ std::path::Path) -> Self {
45        Self::path(value)
46    }
47}
48
49impl From<std::path::PathBuf> for DataSource {
50    fn from(value: std::path::PathBuf) -> Self {
51        Self::path(value)
52    }
53}
54
55impl From<Inline> for DataSource {
56    fn from(inline: Inline) -> Self {
57        Self {
58            inner: DataSourceInner::Inline(inline),
59        }
60    }
61}
62
63impl std::fmt::Display for DataSource {
64    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65        match &self.inner {
66            DataSourceInner::Path(value) => crate::dir::display_relpath(value).fmt(f),
67            DataSourceInner::Inline(value) => value.fmt(f),
68        }
69    }
70}
71
72/// Output of [`str!`][crate::str!]
73#[derive(Clone, Debug, PartialEq, Eq)]
74pub struct Inline {
75    #[doc(hidden)]
76    pub position: Position,
77    #[doc(hidden)]
78    pub data: &'static str,
79}
80
81impl Inline {
82    pub(crate) fn trimmed(&self) -> String {
83        let mut data = self.data;
84        if data.contains('\n') {
85            data = data.strip_prefix('\n').unwrap_or(data);
86            data = data.strip_suffix('\n').unwrap_or(data);
87        }
88        data.to_owned()
89    }
90}
91
92impl std::fmt::Display for Inline {
93    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
94        self.position.fmt(f)
95    }
96}
97
98/// Position within Rust source code, see [`Inline`]
99#[doc(hidden)]
100#[derive(Clone, Debug, PartialEq, Eq)]
101pub struct Position {
102    #[doc(hidden)]
103    pub file: std::path::PathBuf,
104    #[doc(hidden)]
105    pub line: u32,
106    #[doc(hidden)]
107    pub column: u32,
108}
109
110impl std::fmt::Display for Position {
111    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
112        write!(
113            f,
114            "{}:{}:{}",
115            crate::dir::display_relpath(&self.file),
116            self.line,
117            self.column
118        )
119    }
120}