Skip to main content

ntex_bytes/
stext.rs

1use crate::{ByteString, Bytes, storage::Storage};
2
3/// External storage type vtable
4#[derive(Debug)]
5pub struct StorageVTable {
6    pub(crate) as_ptr: unsafe fn(*const u8, usize) -> *const u8,
7    pub(crate) len: unsafe fn(*const u8, usize) -> usize,
8    pub(crate) clone: unsafe fn(*const u8, usize) -> Option<(*const u8, usize)>,
9    pub(crate) drop: unsafe fn(*const u8, usize),
10}
11
12impl StorageVTable {
13    pub const fn new(
14        as_ptr: unsafe fn(*const u8, usize) -> *const u8,
15        len: unsafe fn(*const u8, usize) -> usize,
16        clone: unsafe fn(*const u8, usize) -> Option<(*const u8, usize)>,
17        drop: unsafe fn(*const u8, usize),
18    ) -> StorageVTable {
19        StorageVTable {
20            as_ptr,
21            len,
22            clone,
23            drop,
24        }
25    }
26}
27
28/// Types that could be used as external storage for Bytes
29pub trait StorageExt: Send + Sync {
30    fn create(self) -> (*const u8, usize, &'static StorageVTable);
31}
32
33/// Type's `as_ptr` must return ptr to valid string.
34///
35/// # Safety
36/// Only valid str could implement this trait
37pub unsafe trait StorageExtStr: StorageExt + Sized {
38    fn create(self) -> (*const u8, usize, &'static StorageVTable) {
39        StorageExt::create(self)
40    }
41}
42
43impl Bytes {
44    pub fn from_ext<T: StorageExt>(val: T) -> Bytes {
45        let (addr, len, vtable) = val.create();
46
47        Bytes {
48            storage: Storage::from_stext(addr, len, vtable),
49        }
50    }
51}
52
53impl ByteString {
54    pub fn from_ext<T: StorageExtStr>(val: T) -> ByteString {
55        let (addr, len, vtable) = StorageExtStr::create(val);
56
57        unsafe {
58            ByteString::from_bytes_unchecked(Bytes {
59                storage: Storage::from_stext(addr, len, vtable),
60            })
61        }
62    }
63}