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 as_str(&self) -> Option<&str>24 pub fn as_str(&self) -> Option<&str> { 25 match &self.0 { 26 RawStringInner::Empty => Some(""), 27 RawStringInner::Explicit(s) => Some(s.as_str()), 28 RawStringInner::Spanned(_) => None, 29 } 30 } 31 to_str<'s>(&'s self, input: &'s str) -> &'s str32 pub(crate) fn to_str<'s>(&'s self, input: &'s str) -> &'s str { 33 match &self.0 { 34 RawStringInner::Empty => "", 35 RawStringInner::Explicit(s) => s.as_str(), 36 RawStringInner::Spanned(span) => input.get(span.clone()).unwrap_or_else(|| { 37 panic!("span {:?} should be in input:\n```\n{}\n```", span, input) 38 }), 39 } 40 } 41 to_str_with_default<'s>( &'s self, input: Option<&'s str>, default: &'s str, ) -> &'s str42 pub(crate) fn to_str_with_default<'s>( 43 &'s self, 44 input: Option<&'s str>, 45 default: &'s str, 46 ) -> &'s str { 47 match &self.0 { 48 RawStringInner::Empty => "", 49 RawStringInner::Explicit(s) => s.as_str(), 50 RawStringInner::Spanned(span) => { 51 if let Some(input) = input { 52 input.get(span.clone()).unwrap_or_else(|| { 53 panic!("span {:?} should be in input:\n```\n{}\n```", span, input) 54 }) 55 } else { 56 default 57 } 58 } 59 } 60 } 61 62 /// Access the underlying span span(&self) -> Option<std::ops::Range<usize>>63 pub(crate) fn span(&self) -> Option<std::ops::Range<usize>> { 64 match &self.0 { 65 RawStringInner::Empty => None, 66 RawStringInner::Explicit(_) => None, 67 RawStringInner::Spanned(span) => Some(span.clone()), 68 } 69 } 70 despan(&mut self, input: &str)71 pub(crate) fn despan(&mut self, input: &str) { 72 match &self.0 { 73 RawStringInner::Empty => {} 74 RawStringInner::Explicit(_) => {} 75 RawStringInner::Spanned(span) => { 76 *self = Self::from(input.get(span.clone()).unwrap_or_else(|| { 77 panic!("span {:?} should be in input:\n```\n{}\n```", span, input) 78 })) 79 } 80 } 81 } 82 83 #[cfg(feature = "display")] encode(&self, buf: &mut dyn std::fmt::Write, input: &str) -> std::fmt::Result84 pub(crate) fn encode(&self, buf: &mut dyn std::fmt::Write, input: &str) -> std::fmt::Result { 85 let raw = self.to_str(input); 86 for part in raw.split('\r') { 87 write!(buf, "{}", part)?; 88 } 89 Ok(()) 90 } 91 92 #[cfg(feature = "display")] encode_with_default( &self, buf: &mut dyn std::fmt::Write, input: Option<&str>, default: &str, ) -> std::fmt::Result93 pub(crate) fn encode_with_default( 94 &self, 95 buf: &mut dyn std::fmt::Write, 96 input: Option<&str>, 97 default: &str, 98 ) -> std::fmt::Result { 99 let raw = self.to_str_with_default(input, default); 100 for part in raw.split('\r') { 101 write!(buf, "{}", part)?; 102 } 103 Ok(()) 104 } 105 } 106 107 impl Default for RawString { default() -> Self108 fn default() -> Self { 109 Self(RawStringInner::Empty) 110 } 111 } 112 113 impl std::fmt::Debug for RawString { 114 #[inline] fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error>115 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { 116 match &self.0 { 117 RawStringInner::Empty => write!(formatter, "empty"), 118 RawStringInner::Explicit(s) => write!(formatter, "{:?}", s), 119 RawStringInner::Spanned(s) => write!(formatter, "{:?}", s), 120 } 121 } 122 } 123 124 impl From<&str> for RawString { 125 #[inline] from(s: &str) -> Self126 fn from(s: &str) -> Self { 127 if s.is_empty() { 128 Self(RawStringInner::Empty) 129 } else { 130 InternalString::from(s).into() 131 } 132 } 133 } 134 135 impl From<String> for RawString { 136 #[inline] from(s: String) -> Self137 fn from(s: String) -> Self { 138 if s.is_empty() { 139 Self(RawStringInner::Empty) 140 } else { 141 InternalString::from(s).into() 142 } 143 } 144 } 145 146 impl From<&String> for RawString { 147 #[inline] from(s: &String) -> Self148 fn from(s: &String) -> Self { 149 if s.is_empty() { 150 Self(RawStringInner::Empty) 151 } else { 152 InternalString::from(s).into() 153 } 154 } 155 } 156 157 impl From<InternalString> for RawString { 158 #[inline] from(inner: InternalString) -> Self159 fn from(inner: InternalString) -> Self { 160 Self(RawStringInner::Explicit(inner)) 161 } 162 } 163 164 impl From<&InternalString> for RawString { 165 #[inline] from(s: &InternalString) -> Self166 fn from(s: &InternalString) -> Self { 167 if s.is_empty() { 168 Self(RawStringInner::Empty) 169 } else { 170 InternalString::from(s).into() 171 } 172 } 173 } 174 175 impl From<Box<str>> for RawString { 176 #[inline] from(s: Box<str>) -> Self177 fn from(s: Box<str>) -> Self { 178 if s.is_empty() { 179 Self(RawStringInner::Empty) 180 } else { 181 InternalString::from(s).into() 182 } 183 } 184 } 185