浏览代码

feat(StringBuf): add `StringBuf` type

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
Eliza Weisman 3 年之前
父节点
当前提交
856c1f6c93
共有 4 个文件被更改,包括 97 次插入25 次删除
  1. 3 1
      Cargo.toml
  2. 46 23
      src/lib.rs
  3. 1 1
      src/loom.rs
  4. 47 0
      src/stringbuf.rs

+ 3 - 1
Cargo.toml

@@ -6,7 +6,9 @@ edition = "2021"
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [features]
-std = []
+std = ["alloc"]
+alloc = []
+default = ["std"]
 
 [dependencies]
 

+ 46 - 23
src/lib.rs

@@ -1,4 +1,10 @@
-use core::ops::{Deref, DerefMut};
+use core::{
+    fmt,
+    ops::{Deref, DerefMut},
+};
+
+#[cfg(feature = "alloc")]
+extern crate alloc;
 
 macro_rules! test_println {
     ($($arg:tt)*) => {
@@ -37,6 +43,9 @@ use crate::loom::{
     UnsafeCell,
 };
 
+#[cfg(feature = "alloc")]
+mod stringbuf;
+
 pub struct ThingBuf<T> {
     head: CachePadded<AtomicUsize>,
     tail: CachePadded<AtomicUsize>,
@@ -223,6 +232,14 @@ impl<T> ThingBuf<T> {
     }
 }
 
+impl<T> fmt::Debug for ThingBuf<T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("ThingBuf")
+            .field("capacity", &self.capacity())
+            .finish()
+    }
+}
+
 // === impl Ref ===
 
 impl<T> Ref<'_, T> {
@@ -250,28 +267,34 @@ impl<T> Drop for Ref<'_, T> {
     }
 }
 
-// impl<T> Deref for Writing<'_, T> {
-//     type Target = T;
-
-//     #[inline]
-//     fn deref(&self) -> &T {
-//         unsafe {
-//             // Safety: if a `Writing` exists, it must exclusively own the
-//             // slot it points at.
-//             self.slot.value.with()
-//         }
-//     }
-// }
-
-// impl<T> DerefMut for Writing<'_, T> {
-//     fn deref_mut(&mut self) -> &mut T {
-//         unsafe {
-//             // Safety: if a `Writing` exists, it must exclusively own the
-//             // slot it points at.
-//             self.slot.value.get_mut()
-//         }
-//     }
-// }
+impl<T: fmt::Debug> fmt::Debug for Ref<'_, T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.with(|val| fmt::Debug::fmt(val, f))
+    }
+}
+
+impl<T: fmt::Display> fmt::Display for Ref<'_, T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.with(|val| fmt::Display::fmt(val, f))
+    }
+}
+
+impl<T: fmt::Write> fmt::Write for Ref<'_, T> {
+    #[inline]
+    fn write_str(&mut self, s: &str) -> fmt::Result {
+        self.with_mut(|val| val.write_str(s))
+    }
+
+    #[inline]
+    fn write_char(&mut self, c: char) -> fmt::Result {
+        self.with_mut(|val| val.write_char(c))
+    }
+
+    #[inline]
+    fn write_fmt(&mut self, f: fmt::Arguments<'_>) -> fmt::Result {
+        self.with_mut(|val| val.write_fmt(f))
+    }
+}
 
 // === impl Backoff ===
 

+ 1 - 1
src/loom.rs

@@ -64,7 +64,7 @@ mod inner {
     pub(crate) use core::sync::atomic;
 
     #[cfg(feature = "std")]
-    use std::{sync, thread};
+    pub use std::thread;
 
     pub(crate) mod hint {
         #[inline(always)]

+ 47 - 0
src/stringbuf.rs

@@ -0,0 +1,47 @@
+use super::*;
+
+use alloc::string::String;
+
+#[derive(Debug)]
+pub struct StringBuf {
+    inner: ThingBuf<String>,
+    max_idle_capacity: usize,
+}
+
+impl StringBuf {
+    pub fn new(capacity: usize) -> Self {
+        Self {
+            inner: ThingBuf::new(capacity),
+            max_idle_capacity: usize::MAX,
+        }
+    }
+
+    pub fn with_max_idle_capacity(self, max_idle_capacity: usize) -> Self {
+        Self {
+            max_idle_capacity,
+            ..self
+        }
+    }
+
+    #[inline]
+    pub fn capacity(&self) -> usize {
+        self.inner.capacity()
+    }
+
+    #[inline]
+    pub fn write(&self) -> Result<Ref<'_, String>, AtCapacity> {
+        let mut string = self.inner.push_ref()?;
+        string.with_mut(String::clear);
+        Ok(string)
+    }
+
+    pub fn pop_ref(&self) -> Option<Ref<'_, String>> {
+        let mut string = self.inner.pop_ref()?;
+        string.with_mut(|string| {
+            if string.capacity() > self.max_idle_capacity {
+                string.shrink_to_fit();
+            }
+        });
+        Some(string)
+    }
+}