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 /// The location within the original document 64 /// 65 /// This generally requires an [`ImDocument`][crate::ImDocument]. span(&self) -> Option<std::ops::Range<usize>>66 pub fn span(&self) -> Option<std::ops::Range<usize>> { 67 self.repr.as_ref().and_then(|r| r.span()) 68 } 69 despan(&mut self, input: &str)70 pub(crate) fn despan(&mut self, input: &str) { 71 self.decor.despan(input); 72 if let Some(repr) = &mut self.repr { 73 repr.despan(input); 74 } 75 } 76 77 /// Returns the surrounding whitespace decor_mut(&mut self) -> &mut Decor78 pub fn decor_mut(&mut self) -> &mut Decor { 79 &mut self.decor 80 } 81 82 /// Returns the surrounding whitespace decor(&self) -> &Decor83 pub fn decor(&self) -> &Decor { 84 &self.decor 85 } 86 87 /// Auto formats the value. fmt(&mut self)88 pub fn fmt(&mut self) { 89 self.repr = None; 90 } 91 } 92 93 impl<T> std::fmt::Debug for Formatted<T> 94 where 95 T: std::fmt::Debug, 96 { 97 #[inline] fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error>98 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { 99 let mut d = formatter.debug_struct("Formatted"); 100 d.field("value", &self.value); 101 match &self.repr { 102 Some(r) => d.field("repr", r), 103 None => d.field("repr", &"default"), 104 }; 105 d.field("decor", &self.decor); 106 d.finish() 107 } 108 } 109 110 #[cfg(feature = "display")] 111 impl<T> std::fmt::Display for Formatted<T> 112 where 113 T: ValueRepr, 114 { fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result115 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 116 crate::encode::encode_formatted(self, f, None, ("", "")) 117 } 118 } 119 120 pub trait ValueRepr: crate::private::Sealed { 121 /// The TOML representation of the value 122 #[cfg(feature = "display")] to_repr(&self) -> Repr123 fn to_repr(&self) -> Repr; 124 } 125 126 #[cfg(not(feature = "display"))] 127 mod inner { 128 use super::ValueRepr; 129 130 impl ValueRepr for String {} 131 impl ValueRepr for i64 {} 132 impl ValueRepr for f64 {} 133 impl ValueRepr for bool {} 134 impl ValueRepr for toml_datetime::Datetime {} 135 } 136 137 /// TOML-encoded value 138 #[derive(Eq, PartialEq, Clone, Hash)] 139 pub struct Repr { 140 raw_value: RawString, 141 } 142 143 impl Repr { new_unchecked(raw: impl Into<RawString>) -> Self144 pub(crate) fn new_unchecked(raw: impl Into<RawString>) -> Self { 145 Repr { 146 raw_value: raw.into(), 147 } 148 } 149 150 /// Access the underlying value as_raw(&self) -> &RawString151 pub fn as_raw(&self) -> &RawString { 152 &self.raw_value 153 } 154 155 /// The location within the original document 156 /// 157 /// This generally requires an [`ImDocument`][crate::ImDocument]. span(&self) -> Option<std::ops::Range<usize>>158 pub fn span(&self) -> Option<std::ops::Range<usize>> { 159 self.raw_value.span() 160 } 161 despan(&mut self, input: &str)162 pub(crate) fn despan(&mut self, input: &str) { 163 self.raw_value.despan(input); 164 } 165 166 #[cfg(feature = "display")] encode(&self, buf: &mut dyn std::fmt::Write, input: &str) -> std::fmt::Result167 pub(crate) fn encode(&self, buf: &mut dyn std::fmt::Write, input: &str) -> std::fmt::Result { 168 self.as_raw().encode(buf, input) 169 } 170 } 171 172 impl std::fmt::Debug for Repr { 173 #[inline] fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error>174 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { 175 self.raw_value.fmt(formatter) 176 } 177 } 178 179 /// A prefix and suffix, 180 /// 181 /// Including comments, whitespaces and newlines. 182 #[derive(Eq, PartialEq, Clone, Default, Hash)] 183 pub struct Decor { 184 prefix: Option<RawString>, 185 suffix: Option<RawString>, 186 } 187 188 impl Decor { 189 /// Creates a new decor from the given prefix and suffix. new(prefix: impl Into<RawString>, suffix: impl Into<RawString>) -> Self190 pub fn new(prefix: impl Into<RawString>, suffix: impl Into<RawString>) -> Self { 191 Self { 192 prefix: Some(prefix.into()), 193 suffix: Some(suffix.into()), 194 } 195 } 196 197 /// Go back to default decor clear(&mut self)198 pub fn clear(&mut self) { 199 self.prefix = None; 200 self.suffix = None; 201 } 202 203 /// Get the prefix. prefix(&self) -> Option<&RawString>204 pub fn prefix(&self) -> Option<&RawString> { 205 self.prefix.as_ref() 206 } 207 208 #[cfg(feature = "display")] prefix_encode( &self, buf: &mut dyn std::fmt::Write, input: Option<&str>, default: &str, ) -> std::fmt::Result209 pub(crate) fn prefix_encode( 210 &self, 211 buf: &mut dyn std::fmt::Write, 212 input: Option<&str>, 213 default: &str, 214 ) -> std::fmt::Result { 215 if let Some(prefix) = self.prefix() { 216 prefix.encode_with_default(buf, input, default) 217 } else { 218 write!(buf, "{}", default) 219 } 220 } 221 222 /// Set the prefix. set_prefix(&mut self, prefix: impl Into<RawString>)223 pub fn set_prefix(&mut self, prefix: impl Into<RawString>) { 224 self.prefix = Some(prefix.into()); 225 } 226 227 /// Get the suffix. suffix(&self) -> Option<&RawString>228 pub fn suffix(&self) -> Option<&RawString> { 229 self.suffix.as_ref() 230 } 231 232 #[cfg(feature = "display")] suffix_encode( &self, buf: &mut dyn std::fmt::Write, input: Option<&str>, default: &str, ) -> std::fmt::Result233 pub(crate) fn suffix_encode( 234 &self, 235 buf: &mut dyn std::fmt::Write, 236 input: Option<&str>, 237 default: &str, 238 ) -> std::fmt::Result { 239 if let Some(suffix) = self.suffix() { 240 suffix.encode_with_default(buf, input, default) 241 } else { 242 write!(buf, "{}", default) 243 } 244 } 245 246 /// Set the suffix. set_suffix(&mut self, suffix: impl Into<RawString>)247 pub fn set_suffix(&mut self, suffix: impl Into<RawString>) { 248 self.suffix = Some(suffix.into()); 249 } 250 despan(&mut self, input: &str)251 pub(crate) fn despan(&mut self, input: &str) { 252 if let Some(prefix) = &mut self.prefix { 253 prefix.despan(input); 254 } 255 if let Some(suffix) = &mut self.suffix { 256 suffix.despan(input); 257 } 258 } 259 } 260 261 impl std::fmt::Debug for Decor { 262 #[inline] fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error>263 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { 264 let mut d = formatter.debug_struct("Decor"); 265 match &self.prefix { 266 Some(r) => d.field("prefix", r), 267 None => d.field("prefix", &"default"), 268 }; 269 match &self.suffix { 270 Some(r) => d.field("suffix", r), 271 None => d.field("suffix", &"default"), 272 }; 273 d.finish() 274 } 275 } 276