use std::ops;
use crate::*;
#[repr(transparent)]
#[derive(Debug)]
pub struct CowStrPushGuard(CowStr, NotSync);
enum IsNotSync {}
#[derive(Default, Debug)]
struct NotSync(std::marker::PhantomData<*const IsNotSync>);
unsafe impl Send for NotSync {}
impl CowStrPushGuard {
pub fn from(cowstr: &CowStr) -> Result<CowStrPushGuard, Error> {
if let Some(rc) = cowstr.rcstring() {
if rc.acquire_guard() {
Ok(CowStrPushGuard(cowstr.clone(), Default::default()))
} else {
Err(Error::GuardAlreadyExists)
}
} else {
Err(Error::NoGuardOnStatic)
}
}
#[inline]
pub unsafe fn try_push(&self, c: char) -> Result<&str, Error> {
self.0.rcstring().unwrap_unchecked().try_push(c)
}
#[inline]
pub unsafe fn try_push_str(&self, s: &str) -> Result<&str, Error> {
self.0.rcstring().unwrap_unchecked().try_push_str(s)
}
}
impl Drop for CowStrPushGuard {
fn drop(&mut self) {
unsafe {
self.0.rcstring().unwrap_unchecked().release_guard();
}
}
}
impl ops::Deref for CowStrPushGuard {
type Target = CowStr;
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[test]
fn deref() {
let cowstr = CowStr::from("foobar").guard().unwrap();
assert_eq!(*cowstr, "foobar");
}
#[test]
fn try_push() {
let my_string = CowStr::with_capacity(100);
let cloned = my_string.clone();
let guard = my_string.guard().unwrap();
unsafe {
guard.try_push_str("try_push ").unwrap();
assert_eq!(guard.try_push('1').unwrap(), "1");
assert_eq!(guard.try_push('2').unwrap(), "2");
assert_eq!(guard.try_push('3').unwrap(), "3");
assert_eq!(guard.try_push('4').unwrap(), "4");
assert_eq!(guard.try_push('5').unwrap(), "5");
guard.try_push('6').unwrap();
guard.try_push('7').unwrap();
guard.try_push('8').unwrap();
}
assert_eq!(cloned, "try_push 12345678");
}
#[test]
fn try_push_str() {
let my_string = CowStr::with_capacity(100);
let cloned = my_string.clone();
let guard = my_string.guard().unwrap();
unsafe {
guard.try_push_str("try_push ").unwrap();
assert_eq!(guard.try_push_str("1234").unwrap(), "1234");
assert_eq!(guard.try_push_str("5678").unwrap(), "5678");
}
assert_eq!(cloned, "try_push 12345678");
}
#[test]
#[should_panic]
fn two_guard() {
let my_string = CowStr::with_capacity(100);
let _guard1 = my_string.guard().unwrap();
let _guard2 = my_string.guard().unwrap();
}
#[test]
fn drop_guard() {
let my_string = CowStr::with_capacity(100);
let guard = my_string.guard().unwrap();
drop(guard);
let guard = my_string.guard().unwrap();
drop(guard);
}