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