1 use std::borrow::Cow; 2 3 use crate::RawString; 4 5 /// A value together with its `to_string` representation, 6 /// including surrounding it whitespaces and comments. 7 #[derive(Eq, PartialEq, Clone, Hash)] 8 pub struct Formatted<T> { 9 value: T, 10 repr: Option<Repr>, 11 decor: Decor, 12 } 13 14 impl<T> Formatted<T> 15 where 16 T: ValueRepr, 17 { 18 /// Default-formatted value new(value: T) -> Self19 pub fn new(value: T) -> Self { 20 Self { 21 value, 22 repr: None, 23 decor: Default::default(), 24 } 25 } 26 set_repr_unchecked(&mut self, repr: Repr)27 pub(crate) fn set_repr_unchecked(&mut self, repr: Repr) { 28 self.repr = Some(repr); 29 } 30 31 /// The wrapped value value(&self) -> &T32 pub fn value(&self) -> &T { 33 &self.value 34 } 35 36 /// The wrapped value into_value(self) -> T37 pub fn into_value(self) -> T { 38 self.value 39 } 40 41 /// Returns the raw representation, if available. as_repr(&self) -> Option<&Repr>42 pub fn as_repr(&self) -> Option<&Repr> { 43 self.repr.as_ref() 44 } 45 46 /// Returns the default raw representation. 47 #[cfg(feature = "display")] default_repr(&self) -> Repr48 pub fn default_repr(&self) -> Repr { 49 self.value.to_repr() 50 } 51 52 /// Returns a raw representation. 53 #[cfg(feature = "display")] display_repr(&self) -> Cow<str>54 pub fn display_repr(&self) -> Cow<str> { 55 self.as_repr() 56 .and_then(|r| r.as_raw().as_str()) 57 .map(Cow::Borrowed) 58 .unwrap_or_else(|| { 59 Cow::Owned(self.default_repr().as_raw().as_str().unwrap().to_owned()) 60 }) 61 } 62 63 /// Returns the location within the original document span(&self) -> Option<std::ops::Range<usize>>64 pub(crate) fn span(&self) -> Option<std::ops::Range<usize>> { 65 self.repr.as_ref().and_then(|r| r.span()) 66 } 67 despan(&mut self, input: &str)68 pub(crate) fn despan(&mut self, input: &str) { 69 self.decor.despan(input); 70 if let Some(repr) = &mut self.repr { 71 repr.despan(input); 72 } 73 } 74 75 /// Returns the surrounding whitespace decor_mut(&mut self) -> &mut Decor76 pub fn decor_mut(&mut self) -> &mut Decor { 77 &mut self.decor 78 } 79 80 /// Returns the surrounding whitespace decor(&self) -> &Decor81 pub fn decor(&self) -> &Decor { 82 &self.decor 83 } 84 85 /// Auto formats the value. fmt(&mut self)86 pub fn fmt(&mut self) { 87 self.repr = None; 88 } 89 } 90 91 impl<T> std::fmt::Debug for Formatted<T> 92 where 93 T: std::fmt::Debug, 94 { 95 #[inline] fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error>96 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { 97 let mut d = formatter.debug_struct("Formatted"); 98 d.field("value", &self.value); 99 match &self.repr { 100 Some(r) => d.field("repr", r), 101 None => d.field("repr", &"default"), 102 }; 103 d.field("decor", &self.decor); 104 d.finish() 105 } 106 } 107 108 #[cfg(feature = "display")] 109 impl<T> std::fmt::Display for Formatted<T> 110 where 111 T: ValueRepr, 112 { fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result113 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 114 crate::encode::encode_formatted(self, f, None, ("", "")) 115 } 116 } 117 118 pub trait ValueRepr: crate::private::Sealed { 119 /// The TOML representation of the value 120 #[cfg(feature = "display")] to_repr(&self) -> Repr121 fn to_repr(&self) -> Repr; 122 } 123 124 #[cfg(not(feature = "display"))] 125 mod inner { 126 use super::ValueRepr; 127 128 impl ValueRepr for String {} 129 impl ValueRepr for i64 {} 130 impl ValueRepr for f64 {} 131 impl ValueRepr for bool {} 132 impl ValueRepr for toml_datetime::Datetime {} 133 } 134 135 /// TOML-encoded value 136 #[derive(Eq, PartialEq, Clone, Hash)] 137 pub struct Repr { 138 raw_value: RawString, 139 } 140 141 impl Repr { new_unchecked(raw: impl Into<RawString>) -> Self142 pub(crate) fn new_unchecked(raw: impl Into<RawString>) -> Self { 143 Repr { 144 raw_value: raw.into(), 145 } 146 } 147 148 /// Access the underlying value as_raw(&self) -> &RawString149 pub fn as_raw(&self) -> &RawString { 150 &self.raw_value 151 } 152 153 /// Returns the location within the original document span(&self) -> Option<std::ops::Range<usize>>154 pub(crate) fn span(&self) -> Option<std::ops::Range<usize>> { 155 self.raw_value.span() 156 } 157 despan(&mut self, input: &str)158 pub(crate) fn despan(&mut self, input: &str) { 159 self.raw_value.despan(input) 160 } 161 162 #[cfg(feature = "display")] encode(&self, buf: &mut dyn std::fmt::Write, input: &str) -> std::fmt::Result163 pub(crate) fn encode(&self, buf: &mut dyn std::fmt::Write, input: &str) -> std::fmt::Result { 164 self.as_raw().encode(buf, input) 165 } 166 } 167 168 impl std::fmt::Debug for Repr { 169 #[inline] fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error>170 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { 171 self.raw_value.fmt(formatter) 172 } 173 } 174 175 /// A prefix and suffix, 176 /// 177 /// Including comments, whitespaces and newlines. 178 #[derive(Eq, PartialEq, Clone, Default, Hash)] 179 pub struct Decor { 180 prefix: Option<RawString>, 181 suffix: Option<RawString>, 182 } 183 184 impl Decor { 185 /// Creates a new decor from the given prefix and suffix. new(prefix: impl Into<RawString>, suffix: impl Into<RawString>) -> Self186 pub fn new(prefix: impl Into<RawString>, suffix: impl Into<RawString>) -> Self { 187 Self { 188 prefix: Some(prefix.into()), 189 suffix: Some(suffix.into()), 190 } 191 } 192 193 /// Go back to default decor clear(&mut self)194 pub fn clear(&mut self) { 195 self.prefix = None; 196 self.suffix = None; 197 } 198 199 /// Get the prefix. prefix(&self) -> Option<&RawString>200 pub fn prefix(&self) -> Option<&RawString> { 201 self.prefix.as_ref() 202 } 203 204 #[cfg(feature = "display")] prefix_encode( &self, buf: &mut dyn std::fmt::Write, input: Option<&str>, default: &str, ) -> std::fmt::Result205 pub(crate) fn prefix_encode( 206 &self, 207 buf: &mut dyn std::fmt::Write, 208 input: Option<&str>, 209 default: &str, 210 ) -> std::fmt::Result { 211 if let Some(prefix) = self.prefix() { 212 prefix.encode_with_default(buf, input, default) 213 } else { 214 write!(buf, "{}", default) 215 } 216 } 217 218 /// Set the prefix. set_prefix(&mut self, prefix: impl Into<RawString>)219 pub fn set_prefix(&mut self, prefix: impl Into<RawString>) { 220 self.prefix = Some(prefix.into()); 221 } 222 223 /// Get the suffix. suffix(&self) -> Option<&RawString>224 pub fn suffix(&self) -> Option<&RawString> { 225 self.suffix.as_ref() 226 } 227 228 #[cfg(feature = "display")] suffix_encode( &self, buf: &mut dyn std::fmt::Write, input: Option<&str>, default: &str, ) -> std::fmt::Result229 pub(crate) fn suffix_encode( 230 &self, 231 buf: &mut dyn std::fmt::Write, 232 input: Option<&str>, 233 default: &str, 234 ) -> std::fmt::Result { 235 if let Some(suffix) = self.suffix() { 236 suffix.encode_with_default(buf, input, default) 237 } else { 238 write!(buf, "{}", default) 239 } 240 } 241 242 /// Set the suffix. set_suffix(&mut self, suffix: impl Into<RawString>)243 pub fn set_suffix(&mut self, suffix: impl Into<RawString>) { 244 self.suffix = Some(suffix.into()); 245 } 246 despan(&mut self, input: &str)247 pub(crate) fn despan(&mut self, input: &str) { 248 if let Some(prefix) = &mut self.prefix { 249 prefix.despan(input); 250 } 251 if let Some(suffix) = &mut self.suffix { 252 suffix.despan(input); 253 } 254 } 255 } 256 257 impl std::fmt::Debug for Decor { 258 #[inline] fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error>259 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { 260 let mut d = formatter.debug_struct("Decor"); 261 match &self.prefix { 262 Some(r) => d.field("prefix", r), 263 None => d.field("prefix", &"default"), 264 }; 265 match &self.suffix { 266 Some(r) => d.field("suffix", r), 267 None => d.field("suffix", &"default"), 268 }; 269 d.finish() 270 } 271 } 272