utf8_rune/
pointer.rs

1use core::fmt::Display;
2
3use crate::{layout, Result};
4
5//TODO: std::alloc => alloc::alloc
6/// allocates a new, zero-initialized, raw pointer (i.e.: `*mut u8`) of N contiguous bytes where N=`length`
7///
8/// Example
9///
10/// ```
11/// use utf8_rune::pointer::{self, from_slice};
12/// let (ptr, length) = from_slice(b"bytes").unwrap();
13/// pointer::destroy(ptr, length).unwrap();
14/// ```
15#[inline]
16pub fn create(length: usize) -> Result<*mut u8> {
17    let layout = layout(length)?;
18    let src = unsafe {
19        let src = std::alloc::alloc_zeroed(layout);
20        if src.is_null() {
21            std::alloc::handle_alloc_error(layout);
22        }
23        src
24    };
25    let src = src;
26    for a in 0..length {
27        unsafe {
28            src.add(a).write(0);
29        }
30    }
31    Ok(src)
32}
33
34/// deallocates a raw pointer (i.e.: `*mut u8`) of N contiguous bytes where N=`length`
35///
36/// See [utf8_rune::pointer::create](crate::pointer::create) for details.
37///
38/// Example
39///
40/// ```
41/// use utf8_rune::pointer::{self, from_display};
42/// let (ptr, length) = from_display("bytes").unwrap();
43/// pointer::destroy(ptr, length).unwrap();
44/// ```
45///
46#[inline]
47pub fn destroy(src: *mut u8, length: usize) -> Result<()> {
48    if !src.is_null() {
49        let layout = layout(length)?;
50        unsafe {
51            std::alloc::dealloc(src, layout);
52        }
53    }
54    Ok(())
55}
56
57/// copies the memory contents of `src` into a newly allocated pointer
58///
59/// See [utf8_rune::pointer::create](crate::pointer::create) for details.
60///
61/// Example
62///
63/// ```
64/// use utf8_rune::pointer::{self, from_display, get_byte_at_index, copy};
65/// let (ptr, length) = from_display("bytes").unwrap();
66/// let other_ptr = copy(ptr, length).unwrap();
67/// assert_eq!(get_byte_at_index(ptr, 2), b't');
68/// pointer::destroy(ptr, length).unwrap();
69/// pointer::destroy(other_ptr, length).unwrap();
70/// ```
71///
72#[inline]
73pub fn copy(src: *const u8, length: usize) -> Result<*mut u8> {
74    let mut index = 0;
75    let alloc = create(length)?;
76    if length == 0 {
77        Ok(alloc)
78    } else {
79        while index < length {
80            unsafe {
81                alloc.add(index).write(src.add(index).read());
82            }
83            index += 1;
84        }
85        Ok(alloc)
86    }
87}
88
89/// copies the memory from the given slice of bytes into a newly allocated pointer
90///
91/// See [utf8_rune::pointer::create](crate::pointer::create) for details.
92///
93/// Example
94///
95/// ```
96/// use utf8_rune::pointer::{self, from_slice, get_byte_at_index};
97/// let (ptr, length) = from_slice(b"bytes").unwrap();
98/// assert_eq!(get_byte_at_index(ptr, 2), b't');
99/// pointer::destroy(ptr, length).unwrap();
100/// ```
101///
102#[inline]
103pub fn from_slice(bytes: &[u8]) -> Result<(*mut u8, usize)> {
104    let bytes = bytes.to_vec();
105
106    let src = create(bytes.len())?;
107    let length = bytes.len();
108    if length == 0 {
109        Ok((src, 0))
110    } else {
111        for (i, c) in bytes.iter().enumerate() {
112            unsafe {
113                src.add(i).write(*c);
114            }
115        }
116        Ok((src, length))
117    }
118}
119
120/// copies the memory from the underlying slice of bytes of the given
121/// `input` into a newly allocated pointer.
122///
123/// See [utf8_rune::pointer::create](crate::pointer::create) for details.
124///
125/// Example
126///
127/// ```
128/// use utf8_rune::pointer::{self, from_display, get_byte_at_index};
129/// let (ptr, length) = from_display("bytes").unwrap();
130/// assert_eq!(get_byte_at_index(ptr, 2), b't');
131/// pointer::destroy(ptr, length).unwrap();
132/// ```
133///
134#[inline]
135pub fn from_display<T: Display>(input: T) -> Result<(*mut u8, usize)> {
136    Ok(from_slice(input.to_string().as_bytes())?)
137}
138
139/// retrieves a byte from contiguous memory area
140///
141/// Example
142///
143/// ```
144/// use utf8_rune::pointer::get_byte_at_index;
145/// let ptr = "bytes".as_bytes().as_ptr();
146/// assert_eq!(get_byte_at_index(ptr, 2), b't');
147/// ```
148#[inline]
149pub fn get_byte_at_index<'g>(src: *const u8, index: usize) -> u8 {
150    let byte = unsafe { src.add(index).read() };
151    byte
152}
153
154/// retrieves a slice of N bytes from contiguous memory area where `N=count` starting at `index`
155///
156/// Example
157///
158/// ```
159/// use utf8_rune::pointer::get_byte_slice_of;
160/// let ptr = "UNICODE".as_bytes().as_ptr();
161/// assert_eq!(get_byte_slice_of(ptr, 2, 3), b"ICO");
162/// ```
163#[inline]
164pub fn get_byte_slice_of<'g>(src: *const u8, index: usize, count: usize) -> &'g [u8] {
165    let bytes = unsafe { std::slice::from_raw_parts(src.add(index), count) };
166    bytes
167}
168
169/// retrieves `Some()` valid str slice of N bytes from contiguous
170/// memory area or `None` if the resulting sequence of bytes is not
171/// valid UTF-8.
172///
173/// Example
174///
175/// ```
176/// use utf8_rune::pointer::get_valid_utf8_str_of;
177/// let ptr = "UNICODE".as_bytes().as_ptr();
178/// assert_eq!(get_valid_utf8_str_of(ptr, 2, 3), Some("ICO"));
179/// ```
180#[inline]
181pub fn get_valid_utf8_str_of<'g>(
182    src: *const u8,
183    index: usize,
184    count: usize,
185) -> Option<&'g str> {
186    std::str::from_utf8(get_byte_slice_of(src, index, count)).ok()
187}
188
189/// returns `true` if the sequence of `count` bytes from `index` is a
190/// valid UTF-8 sequence.
191///
192/// Example
193///
194/// ```
195/// use utf8_rune::pointer::is_valid_utf8_str_of;
196/// let ptr = "UNICODE".as_bytes().as_ptr();
197/// assert_eq!(is_valid_utf8_str_of(ptr, 2, 3), true);
198/// ```
199#[inline]
200pub fn is_valid_utf8_str_of<'g>(src: *const u8, index: usize, count: usize) -> bool {
201    get_valid_utf8_str_of(src, index, count).is_some()
202}