Skip to main content

ntex_bytes/
stext_arc.rs

1use std::{mem, ptr, sync::Arc};
2
3use crate::{StorageExt, StorageExtStr, StorageVTable};
4
5// ======== Impl for Arc<str> ========
6
7fn as_ptr(addr: *const u8, _: usize) -> *const u8 {
8    addr
9}
10
11fn len(_: *const u8, len: usize) -> usize {
12    len
13}
14
15fn clone_str(addr: *const u8, len: usize) -> Option<(*const u8, usize)> {
16    let slice_ptr: *const [u8] = ptr::slice_from_raw_parts(addr, len);
17    let str_ptr = slice_ptr as *const str;
18    let arc = unsafe { Arc::from_raw(str_ptr) };
19    let arc2 = arc.clone();
20    mem::forget(arc);
21    mem::forget(arc2);
22
23    Some((addr, len))
24}
25
26fn drop_str(addr: *const u8, len: usize) {
27    let slice_ptr: *const [u8] = ptr::slice_from_raw_parts(addr, len);
28    let str_ptr = slice_ptr as *const str;
29    let arc = unsafe { Arc::from_raw(str_ptr) };
30    drop(arc);
31}
32
33const ARC_STR_VTABLE: StorageVTable = StorageVTable::new(as_ptr, len, clone_str, drop_str);
34
35// SAFETY: the vtable shares and releases the `Arc<str>` allocation, which
36// stays valid and immutable until the last handle is dropped
37unsafe impl StorageExt for Arc<str> {
38    fn create(self) -> (*const u8, usize, &'static StorageVTable) {
39        let ptr = Arc::into_raw(self) as *const [u8];
40
41        // Extract address and length
42        let addr = ptr.cast::<()>().cast::<u8>();
43        let len = ptr.len();
44        (addr, len, &ARC_STR_VTABLE)
45    }
46}
47
48// SAFETY: `Arc<str>` always holds valid UTF-8
49unsafe impl StorageExtStr for Arc<str> {}
50
51#[cfg(test)]
52#[allow(unused_must_use)]
53mod tests {
54    use super::*;
55    use crate::{ByteString, Bytes, buf::Buf};
56
57    #[test]
58    fn test_arc_str() {
59        let test: Arc<str> = Arc::from("test".to_string());
60
61        let b = Bytes::from_ext(test.clone());
62        assert_eq!(&b, b"test");
63        assert_eq!(b.storage.capacity(), 4);
64        assert_eq!(Arc::strong_count(&test), 2);
65
66        let b2 = b.clone();
67        assert_eq!(&b2, b"test");
68        assert_eq!(Arc::strong_count(&test), 3);
69
70        drop(b2);
71        assert_eq!(&b, b"test");
72        assert_eq!(Arc::strong_count(&test), 2);
73
74        drop(b);
75        assert_eq!(Arc::strong_count(&test), 1);
76
77        let b = ByteString::from_ext(test.clone());
78        assert_eq!(&b, "test");
79        assert_eq!(Arc::strong_count(&test), 2);
80
81        drop(b);
82        assert_eq!(Arc::strong_count(&test), 1);
83
84        let mut b = Bytes::from_ext(test.clone());
85        assert_eq!(Arc::strong_count(&test), 2);
86        assert_eq!(b.get_u8(), b't');
87        assert_eq!(&b, b"est");
88        assert_eq!(Arc::strong_count(&test), 1);
89
90        let mut b = Bytes::from_ext(test.clone());
91        b.truncate(2);
92        assert_eq!(&b, b"te");
93        assert_eq!(Arc::strong_count(&test), 1);
94
95        let mut b = Bytes::from_ext(test.clone());
96        unsafe { b.storage.set_start(2) };
97        assert_eq!(&b, b"st");
98        assert_eq!(Arc::strong_count(&test), 1);
99
100        let mut b = Bytes::from_ext(test.clone());
101        unsafe { b.storage.set_end(2) };
102        assert_eq!(&b, b"te");
103        assert_eq!(Arc::strong_count(&test), 1);
104    }
105}