summaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/util')
-rw-r--r--src/util/eco_string.rs83
-rw-r--r--src/util/mod.rs1
2 files changed, 80 insertions, 4 deletions
diff --git a/src/util/eco_string.rs b/src/util/eco_string.rs
index ab8d5642..8cb83377 100644
--- a/src/util/eco_string.rs
+++ b/src/util/eco_string.rs
@@ -2,11 +2,21 @@ use std::borrow::Borrow;
use std::cmp::Ordering;
use std::fmt::{self, Debug, Display, Formatter, Write};
use std::hash::{Hash, Hasher};
-use std::ops::Deref;
+use std::ops::{Add, AddAssign, Deref};
use std::rc::Rc;
use super::RcExt;
+/// Create a new [`EcoString`] from a format string.
+macro_rules! format_eco {
+ ($($tts:tt)*) => {{
+ use std::fmt::Write;
+ let mut s = $crate::util::EcoString::new();
+ write!(s, $($tts)*).unwrap();
+ s
+ }};
+}
+
/// An economical string with inline storage and clone-on-write semantics.
#[derive(Clone)]
pub struct EcoString(Repr);
@@ -142,14 +152,38 @@ impl EcoString {
}
}
+ /// Convert the string to lowercase.
+ pub fn to_lowercase(&self) -> Self {
+ if let Repr::Small { mut buf, len } = self.0 {
+ if self.is_ascii() {
+ buf[.. usize::from(len)].make_ascii_lowercase();
+ return Self(Repr::Small { buf, len });
+ }
+ }
+
+ self.as_str().to_lowercase().into()
+ }
+
+ /// Convert the string to uppercase.
+ pub fn to_uppercase(&self) -> Self {
+ if let Repr::Small { mut buf, len } = self.0 {
+ if self.is_ascii() {
+ buf[.. usize::from(len)].make_ascii_uppercase();
+ return Self(Repr::Small { buf, len });
+ }
+ }
+
+ self.as_str().to_uppercase().into()
+ }
+
/// Repeat this string `n` times.
pub fn repeat(&self, n: usize) -> Self {
if n == 0 {
return Self::new();
}
- if let Repr::Small { buf, len } = &self.0 {
- let prev = usize::from(*len);
+ if let Repr::Small { buf, len } = self.0 {
+ let prev = usize::from(len);
let new = prev.saturating_mul(n);
if new <= LIMIT {
let src = &buf[.. prev];
@@ -193,7 +227,18 @@ impl Default for EcoString {
impl Debug for EcoString {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- Debug::fmt(self.as_str(), f)
+ f.write_char('"')?;
+ for c in self.chars() {
+ match c {
+ '\\' => f.write_str(r"\\")?,
+ '"' => f.write_str(r#"\""#)?,
+ '\n' => f.write_str(r"\n")?,
+ '\r' => f.write_str(r"\r")?,
+ '\t' => f.write_str(r"\t")?,
+ _ => f.write_char(c)?,
+ }
+ }
+ f.write_char('"')
}
}
@@ -253,6 +298,21 @@ impl Write for EcoString {
}
}
+impl Add for EcoString {
+ type Output = Self;
+
+ fn add(mut self, rhs: Self) -> Self::Output {
+ self += rhs;
+ self
+ }
+}
+
+impl AddAssign for EcoString {
+ fn add_assign(&mut self, rhs: Self) {
+ self.push_str(rhs.as_str());
+ }
+}
+
impl AsRef<str> for EcoString {
fn as_ref(&self) -> &str {
self
@@ -383,6 +443,21 @@ mod tests {
}
#[test]
+ fn test_str_case() {
+ assert_eq!(EcoString::new().to_uppercase(), "");
+ assert_eq!(EcoString::from("abc").to_uppercase(), "ABC");
+ assert_eq!(EcoString::from("AΣ").to_lowercase(), "aς");
+ assert_eq!(
+ EcoString::from("a").repeat(100).to_uppercase(),
+ EcoString::from("A").repeat(100)
+ );
+ assert_eq!(
+ EcoString::from("Ö").repeat(20).to_lowercase(),
+ EcoString::from("ö").repeat(20)
+ );
+ }
+
+ #[test]
fn test_str_repeat() {
// Test with empty string.
assert_eq!(EcoString::new().repeat(0), "");
diff --git a/src/util/mod.rs b/src/util/mod.rs
index c4272c55..8b74aed6 100644
--- a/src/util/mod.rs
+++ b/src/util/mod.rs
@@ -1,5 +1,6 @@
//! Utilities.
+#[macro_use]
mod eco_string;
mod mac_roman;