1use std::borrow::Cow;
2
3use crate::RawString;
4
5#[derive(Eq, PartialEq, Clone, Hash)]
9pub struct Formatted<T> {
10 value: T,
11 repr: Option<Repr>,
12 decor: Decor,
13}
14
15impl<T> Formatted<T>
16where
17 T: ValueRepr,
18{
19 pub fn new(value: T) -> Self {
21 Self {
22 value,
23 repr: None,
24 decor: Default::default(),
25 }
26 }
27
28 pub(crate) fn set_repr_unchecked(&mut self, repr: Repr) {
29 self.repr = Some(repr);
30 }
31
32 pub fn value(&self) -> &T {
34 &self.value
35 }
36
37 pub fn into_value(self) -> T {
39 self.value
40 }
41
42 pub fn as_repr(&self) -> Option<&Repr> {
44 self.repr.as_ref()
45 }
46
47 #[cfg(feature = "display")]
49 pub fn default_repr(&self) -> Repr {
50 self.value.to_repr()
51 }
52
53 #[cfg(feature = "display")]
55 pub fn display_repr(&self) -> Cow<'_, str> {
56 self.as_repr()
57 .and_then(|r| r.as_raw().as_str())
58 .map(Cow::Borrowed)
59 .unwrap_or_else(|| Cow::Owned(self.default_repr().into_raw().into_string().unwrap()))
60 }
61
62 pub fn span(&self) -> Option<std::ops::Range<usize>> {
66 self.repr.as_ref().and_then(|r| r.span())
67 }
68
69 pub(crate) fn despan(&mut self, input: &str) {
70 self.decor.despan(input);
71 if let Some(repr) = &mut self.repr {
72 repr.despan(input);
73 }
74 }
75
76 pub fn decor_mut(&mut self) -> &mut Decor {
78 &mut self.decor
79 }
80
81 pub fn decor(&self) -> &Decor {
83 &self.decor
84 }
85
86 pub fn fmt(&mut self) {
88 self.repr = None;
89 }
90}
91
92impl<T> std::fmt::Debug for Formatted<T>
93where
94 T: std::fmt::Debug,
95{
96 #[inline]
97 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
98 let mut d = formatter.debug_struct("Formatted");
99 d.field("value", &self.value);
100 match &self.repr {
101 Some(r) => d.field("repr", r),
102 None => d.field("repr", &"default"),
103 };
104 d.field("decor", &self.decor);
105 d.finish()
106 }
107}
108
109#[cfg(feature = "display")]
110impl<T> std::fmt::Display for Formatted<T>
111where
112 T: ValueRepr,
113{
114 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
115 crate::encode::encode_formatted(self, f, None, ("", ""))
116 }
117}
118
119pub trait ValueRepr: crate::private::Sealed {
120 #[cfg(feature = "display")]
122 fn to_repr(&self) -> Repr;
123}
124
125#[cfg(not(feature = "display"))]
126mod inner {
127 use super::ValueRepr;
128
129 impl ValueRepr for String {}
130 impl ValueRepr for i64 {}
131 impl ValueRepr for f64 {}
132 impl ValueRepr for bool {}
133 impl ValueRepr for toml_datetime::Datetime {}
134}
135
136#[derive(Eq, PartialEq, Clone, Hash)]
138pub struct Repr {
139 raw_value: RawString,
140}
141
142impl Repr {
143 pub(crate) fn new_unchecked(raw: impl Into<RawString>) -> Self {
144 Self {
145 raw_value: raw.into(),
146 }
147 }
148
149 pub fn as_raw(&self) -> &RawString {
151 &self.raw_value
152 }
153
154 #[cfg(feature = "display")]
155 pub(crate) fn into_raw(self) -> RawString {
156 self.raw_value
157 }
158
159 pub fn span(&self) -> Option<std::ops::Range<usize>> {
163 self.raw_value.span()
164 }
165
166 pub(crate) fn despan(&mut self, input: &str) {
167 self.raw_value.despan(input);
168 }
169
170 #[cfg(feature = "display")]
171 pub(crate) fn encode(&self, buf: &mut dyn std::fmt::Write, input: &str) -> std::fmt::Result {
172 self.as_raw().encode(buf, input)
173 }
174}
175
176impl std::fmt::Debug for Repr {
177 #[inline]
178 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
179 self.raw_value.fmt(formatter)
180 }
181}
182
183#[derive(Eq, PartialEq, Clone, Default, Hash)]
187pub struct Decor {
188 prefix: Option<RawString>,
189 suffix: Option<RawString>,
190}
191
192impl Decor {
193 pub(crate) const EMPTY: Self = Self {
194 prefix: None,
195 suffix: None,
196 };
197
198 pub fn new(prefix: impl Into<RawString>, suffix: impl Into<RawString>) -> Self {
200 Self {
201 prefix: Some(prefix.into()),
202 suffix: Some(suffix.into()),
203 }
204 }
205
206 pub fn clear(&mut self) {
208 self.prefix = None;
209 self.suffix = None;
210 }
211
212 pub fn prefix(&self) -> Option<&RawString> {
214 self.prefix.as_ref()
215 }
216
217 #[cfg(feature = "display")]
218 pub(crate) fn prefix_encode(
219 &self,
220 buf: &mut dyn std::fmt::Write,
221 input: Option<&str>,
222 default: &str,
223 ) -> std::fmt::Result {
224 if let Some(prefix) = self.prefix() {
225 prefix.encode_with_default(buf, input, default)
226 } else {
227 buf.write_str(default)
228 }
229 }
230
231 pub fn set_prefix(&mut self, prefix: impl Into<RawString>) {
233 self.prefix = Some(prefix.into());
234 }
235
236 pub fn suffix(&self) -> Option<&RawString> {
238 self.suffix.as_ref()
239 }
240
241 #[cfg(feature = "display")]
242 pub(crate) fn suffix_encode(
243 &self,
244 buf: &mut dyn std::fmt::Write,
245 input: Option<&str>,
246 default: &str,
247 ) -> std::fmt::Result {
248 if let Some(suffix) = self.suffix() {
249 suffix.encode_with_default(buf, input, default)
250 } else {
251 buf.write_str(default)
252 }
253 }
254
255 pub fn set_suffix(&mut self, suffix: impl Into<RawString>) {
257 self.suffix = Some(suffix.into());
258 }
259
260 pub(crate) fn despan(&mut self, input: &str) {
261 if let Some(prefix) = &mut self.prefix {
262 prefix.despan(input);
263 }
264 if let Some(suffix) = &mut self.suffix {
265 suffix.despan(input);
266 }
267 }
268}
269
270impl std::fmt::Debug for Decor {
271 #[inline]
272 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
273 let mut d = formatter.debug_struct("Decor");
274 match &self.prefix {
275 Some(r) => d.field("prefix", r),
276 None => d.field("prefix", &"default"),
277 };
278 match &self.suffix {
279 Some(r) => d.field("suffix", r),
280 None => d.field("suffix", &"default"),
281 };
282 d.finish()
283 }
284}