• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::InternalString;
2 
3 /// Opaque string storage for raw TOML; internal to `toml_edit`
4 #[derive(PartialEq, Eq, Clone, Hash)]
5 pub struct RawString(RawStringInner);
6 
7 #[derive(PartialEq, Eq, Clone, Hash)]
8 enum RawStringInner {
9     Empty,
10     Explicit(InternalString),
11     Spanned(std::ops::Range<usize>),
12 }
13 
14 impl RawString {
with_span(span: std::ops::Range<usize>) -> Self15     pub(crate) fn with_span(span: std::ops::Range<usize>) -> Self {
16         if span.start == span.end {
17             RawString(RawStringInner::Empty)
18         } else {
19             RawString(RawStringInner::Spanned(span))
20         }
21     }
22 
23     /// Access the underlying string
24     ///
25     /// This generally requires a [`DocumentMut`][crate::DocumentMut].
as_str(&self) -> Option<&str>26     pub fn as_str(&self) -> Option<&str> {
27         match &self.0 {
28             RawStringInner::Empty => Some(""),
29             RawStringInner::Explicit(s) => Some(s.as_str()),
30             RawStringInner::Spanned(_) => None,
31         }
32     }
33 
34     /// The location within the original document
35     ///
36     /// This generally requires an [`ImDocument`][crate::ImDocument].
span(&self) -> Option<std::ops::Range<usize>>37     pub fn span(&self) -> Option<std::ops::Range<usize>> {
38         match &self.0 {
39             RawStringInner::Empty => None,
40             RawStringInner::Explicit(_) => None,
41             RawStringInner::Spanned(span) => Some(span.clone()),
42         }
43     }
44 
to_str<'s>(&'s self, input: &'s str) -> &'s str45     pub(crate) fn to_str<'s>(&'s self, input: &'s str) -> &'s str {
46         match &self.0 {
47             RawStringInner::Empty => "",
48             RawStringInner::Explicit(s) => s.as_str(),
49             RawStringInner::Spanned(span) => input.get(span.clone()).unwrap_or_else(|| {
50                 panic!("span {:?} should be in input:\n```\n{}\n```", span, input)
51             }),
52         }
53     }
54 
to_str_with_default<'s>( &'s self, input: Option<&'s str>, default: &'s str, ) -> &'s str55     pub(crate) fn to_str_with_default<'s>(
56         &'s self,
57         input: Option<&'s str>,
58         default: &'s str,
59     ) -> &'s str {
60         match &self.0 {
61             RawStringInner::Empty => "",
62             RawStringInner::Explicit(s) => s.as_str(),
63             RawStringInner::Spanned(span) => {
64                 if let Some(input) = input {
65                     input.get(span.clone()).unwrap_or_else(|| {
66                         panic!("span {:?} should be in input:\n```\n{}\n```", span, input)
67                     })
68                 } else {
69                     default
70                 }
71             }
72         }
73     }
74 
despan(&mut self, input: &str)75     pub(crate) fn despan(&mut self, input: &str) {
76         match &self.0 {
77             RawStringInner::Empty => {}
78             RawStringInner::Explicit(_) => {}
79             RawStringInner::Spanned(span) => {
80                 *self = Self::from(input.get(span.clone()).unwrap_or_else(|| {
81                     panic!("span {:?} should be in input:\n```\n{}\n```", span, input)
82                 }));
83             }
84         }
85     }
86 
87     #[cfg(feature = "display")]
encode(&self, buf: &mut dyn std::fmt::Write, input: &str) -> std::fmt::Result88     pub(crate) fn encode(&self, buf: &mut dyn std::fmt::Write, input: &str) -> std::fmt::Result {
89         let raw = self.to_str(input);
90         for part in raw.split('\r') {
91             write!(buf, "{}", part)?;
92         }
93         Ok(())
94     }
95 
96     #[cfg(feature = "display")]
encode_with_default( &self, buf: &mut dyn std::fmt::Write, input: Option<&str>, default: &str, ) -> std::fmt::Result97     pub(crate) fn encode_with_default(
98         &self,
99         buf: &mut dyn std::fmt::Write,
100         input: Option<&str>,
101         default: &str,
102     ) -> std::fmt::Result {
103         let raw = self.to_str_with_default(input, default);
104         for part in raw.split('\r') {
105             write!(buf, "{}", part)?;
106         }
107         Ok(())
108     }
109 }
110 
111 impl Default for RawString {
default() -> Self112     fn default() -> Self {
113         Self(RawStringInner::Empty)
114     }
115 }
116 
117 impl std::fmt::Debug for RawString {
118     #[inline]
fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error>119     fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
120         match &self.0 {
121             RawStringInner::Empty => write!(formatter, "empty"),
122             RawStringInner::Explicit(s) => write!(formatter, "{:?}", s),
123             RawStringInner::Spanned(s) => write!(formatter, "{:?}", s),
124         }
125     }
126 }
127 
128 impl From<&str> for RawString {
129     #[inline]
from(s: &str) -> Self130     fn from(s: &str) -> Self {
131         if s.is_empty() {
132             Self(RawStringInner::Empty)
133         } else {
134             InternalString::from(s).into()
135         }
136     }
137 }
138 
139 impl From<String> for RawString {
140     #[inline]
from(s: String) -> Self141     fn from(s: String) -> Self {
142         if s.is_empty() {
143             Self(RawStringInner::Empty)
144         } else {
145             InternalString::from(s).into()
146         }
147     }
148 }
149 
150 impl From<&String> for RawString {
151     #[inline]
from(s: &String) -> Self152     fn from(s: &String) -> Self {
153         if s.is_empty() {
154             Self(RawStringInner::Empty)
155         } else {
156             InternalString::from(s).into()
157         }
158     }
159 }
160 
161 impl From<InternalString> for RawString {
162     #[inline]
from(inner: InternalString) -> Self163     fn from(inner: InternalString) -> Self {
164         Self(RawStringInner::Explicit(inner))
165     }
166 }
167 
168 impl From<&InternalString> for RawString {
169     #[inline]
from(s: &InternalString) -> Self170     fn from(s: &InternalString) -> Self {
171         if s.is_empty() {
172             Self(RawStringInner::Empty)
173         } else {
174             InternalString::from(s).into()
175         }
176     }
177 }
178 
179 impl From<Box<str>> for RawString {
180     #[inline]
from(s: Box<str>) -> Self181     fn from(s: Box<str>) -> Self {
182         if s.is_empty() {
183             Self(RawStringInner::Empty)
184         } else {
185             InternalString::from(s).into()
186         }
187     }
188 }
189