pub fn with_encoding(self, encoding: &'static Encoding) -> EncodedString {
EncodedString {
- bytes: self.0,
+ bytes: self,
encoding,
}
}
self.0.borrow().len()
}
+ pub fn is_empty(&self) -> bool {
+ self.len() == 0
+ }
+
/// Returns true if this raw string can be resized to `len` bytes without
/// dropping non-space characters.
pub fn is_resizable(&self, new_len: usize) -> bool {
impl From<EncodedString> for OwnedRawString {
fn from(value: EncodedString) -> Self {
- Self(value.bytes)
+ value.bytes
}
}
/// A string value.
String(
/// The value, in the variable's encoding.
- EncodedStr<'a>,
+ EncodedString<&'a BorrowedRawString>,
),
}
/// Returns the string inside this datum, or `None` if this is a numeric
/// datum.
- pub fn as_string(&self) -> Option<&EncodedStr> {
+ pub fn as_string(&self) -> Option<EncodedString<&'a BorrowedRawString>> {
match self {
Self::Number(_) => None,
- Self::String(s) => Some(s),
+ Self::String(s) => Some(*s),
}
}
+ /*
/// Returns the string inside this datum as a mutable borrow, or `None` if
/// this is a numeric datum.
- pub fn as_string_mut(&'a mut self) -> Option<EncodedStr<'a>> {
+ pub fn as_string_mut(&'a mut self) -> Option<EncodedString<&'a mut BorrowedRawString>> {
match self {
Self::Number(_) => None,
Self::String(s) => Some(*s),
}
- }
+ }*/
pub fn eq_ignore_trailing_spaces<'b>(&self, other: EncodedDat<'b>) -> bool {
match (self, other) {
match &self.0 {
EncodedDat::Number(None) => write!(f, "SYSMIS"),
EncodedDat::Number(Some(number)) => number.display_plain().fmt(f),
- EncodedDat::String(string) => write!(f, "{}", string.quoted()),
+ EncodedDat::String(string) => write!(f, "\"{}\"", string.as_str()),
}
}
}
pub fn as_encoded<'a>(&'a self, encoding: &'static Encoding) -> EncodedDat<'a> {
match self {
Datum::Number(number) => EncodedDat::Number(*number),
- Datum::String(raw_string) => {
- EncodedDat::String(raw_string.borrow().as_encoded(encoding))
- }
+ Datum::String(raw_string) => EncodedDat::String(EncodedString {
+ encoding,
+ bytes: raw_string.borrow(),
+ }),
}
}
}
/// The string is not guaranteed to be valid in the encoding.
///
/// The borrowed form of such a string is [EncodedStr].
-#[derive(Clone, Debug)]
-pub struct EncodedString {
+#[derive(Copy, Clone, Debug)]
+pub struct EncodedString<R = OwnedRawString> {
/// The bytes of the string.
- bytes: Vec<u8>,
+ bytes: R,
/// The string's encoding.
encoding: &'static Encoding,
}
-impl EncodedString {
+impl<R> EncodedString<R>
+where
+ R: Borrow<BorrowedRawString>,
+{
pub fn len(&self) -> usize {
- self.bytes.len()
+ self.bytes.borrow().len()
}
/// Returns this string recoded in UTF-8. Invalid characters will be
///
/// [REPLACEMENT_CHARACTER]: std::char::REPLACEMENT_CHARACTER
pub fn as_str(&self) -> Cow<'_, str> {
- self.encoding.decode_without_bom_handling(&self.bytes).0
+ self.encoding.decode_without_bom_handling(self.as_bytes()).0
}
/// Returns the bytes in the string, in its encoding.
pub fn as_bytes(&self) -> &[u8] {
- &self.bytes
+ &self.bytes.borrow().0
}
/// Compares this string and `other` for equality, ignoring trailing ASCII
/// spaces in either string for the purpose of comparison. (This is
/// acceptable because we assume that the encoding is ASCII-compatible.)
- pub fn eq_ignore_trailing_spaces<'a>(&self, other: impl Into<EncodedStr<'a>>) -> bool {
- self.borrowed().eq_ignore_trailing_spaces(other.into())
+ pub fn eq_ignore_trailing_spaces<R2>(&self, other: impl Into<EncodedString<R2>>) -> bool
+ where
+ R2: Borrow<BorrowedRawString>,
+ {
+ self.borrowed()
+ .bytes
+ .eq_ignore_trailing_spaces(&other.into().borrowed().bytes)
+ }
+
+ /// Returns the string's [Encoding].
+ pub fn encoding(&self) -> &'static Encoding {
+ self.encoding
+ }
+
+ /// Returns a borrowed form of this string.
+ pub fn borrowed<'a>(&'a self) -> EncodedString<&'a BorrowedRawString> {
+ EncodedString {
+ encoding: self.encoding,
+ bytes: self.bytes.borrow(),
+ }
+ }
+
+ /// Returns true if this string is empty.
+ pub fn is_empty(&self) -> bool {
+ self.bytes.borrow().is_empty()
+ }
+
+ /// Returns a helper for displaying this string in double quotes.
+ pub fn quoted(&self) -> impl Display {
+ Quoted(self.as_str())
}
+}
+impl EncodedString {
pub fn resize(&mut self, new_len: usize) -> Result<(), ()> {
match new_len.cmp(&self.len()) {
Ordering::Less => {
if !self.as_bytes()[new_len..].iter().all(|b| *b == b' ') {
return Err(());
}
- self.bytes.truncate(new_len);
+ self.bytes.0.truncate(new_len);
}
Ordering::Equal => (),
- Ordering::Greater => self.bytes.extend((self.len()..new_len).map(|_| b' ')),
+ Ordering::Greater => self.bytes.0.extend((self.len()..new_len).map(|_| b' ')),
}
Ok(())
}
- /// Returns the string's [Encoding].
- pub fn encoding(&self) -> &'static Encoding {
- self.encoding
- }
-
- /// Returns a borrowed form of this string.
- pub fn borrowed(&self) -> EncodedStr<'_> {
- EncodedStr::new(&self.bytes, self.encoding)
- }
-
/// Removes any trailing ASCII spaces.
pub fn trim_end(&mut self) {
- while self.bytes.pop_if(|c| *c == b' ').is_some() {}
+ while self.bytes.0.pop_if(|c| *c == b' ').is_some() {}
}
}
impl From<&str> for EncodedString {
fn from(value: &str) -> Self {
Self {
- bytes: value.into(),
+ bytes: RawString(value.into()),
encoding: UTF_8,
}
}
}
-impl<'a> From<&'a EncodedString> for EncodedStr<'a> {
- fn from(value: &'a EncodedString) -> Self {
- value.borrowed()
- }
-}
-
impl<'a> From<EncodedStr<'a>> for EncodedString {
fn from(value: EncodedStr<'a>) -> Self {
Self {
where
S: serde::Serializer,
{
- self.borrowed().serialize(serializer)
+ self.as_str().serialize(serializer)
+ }
+}
+
+impl<R> Display for EncodedString<R>
+where
+ R: Borrow<BorrowedRawString>,
+{
+ fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
+ write!(f, "{}", self.as_str())
+ }
+}
+
+impl<R, R2> PartialEq<EncodedString<R2>> for EncodedString<R>
+where
+ R: Borrow<BorrowedRawString>,
+ R2: Borrow<BorrowedRawString>,
+{
+ fn eq(&self, other: &EncodedString<R2>) -> bool {
+ // XXX should this consider the encodings?
+ self.borrowed().bytes.eq(other.borrowed().bytes)
}
}
}
/// Returns a helper for displaying this string in double quotes.
- pub fn quoted(&self) -> QuotedEncodedStr {
- QuotedEncodedStr(self)
+ pub fn quoted(&self) -> impl Display {
+ Quoted(self.as_str())
}
}
}
}
-/// Helper struct for displaying a [QuotedEncodedStr] in double quotes.
-pub struct QuotedEncodedStr<'a>(&'a EncodedStr<'a>);
+/// Helper struct for displaying a value in double quotes.
+pub struct Quoted<T>(T)
+where
+ T: Display;
-impl Display for QuotedEncodedStr<'_> {
+impl<T> Display for Quoted<T>
+where
+ T: Display,
+{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- write!(f, "{:?}", self.0.as_str())
+ write!(f, "\"{}\"", &self.0)
}
}