1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use crate::{
std_types::RStr,
utils::ref_as_nonnull,
};
use std::{
cmp::{PartialEq,Eq},
fmt::{self, Debug, Display},
marker::PhantomData,
ptr::NonNull,
};
#[repr(transparent)]
#[derive(Copy,Clone,StableAbi)]
pub struct NulStr<'a>{
ptr:NonNull<u8>,
_marker:PhantomData<&'a u8>,
}
unsafe impl Sync for NulStr<'_>{}
unsafe impl Send for NulStr<'_>{}
impl NulStr<'static>{
pub const EMPTY: Self = NulStr{ptr: ref_as_nonnull(&0), _marker: PhantomData};
}
impl<'a> NulStr<'a>{
pub const unsafe fn from_str(str: &'a str) -> Self{
Self{
ptr: NonNull::new_unchecked(str.as_ptr() as *mut u8),
_marker:PhantomData,
}
}
pub const unsafe fn from_ptr(ptr: *const u8) -> Self{
Self{
ptr: NonNull::new_unchecked(ptr as *mut u8),
_marker:PhantomData,
}
}
pub fn to_str_with_nul(&self)->&'a str{
unsafe{
let bytes=std::ffi::CStr::from_ptr(self.ptr.as_ptr() as *const i8).to_bytes_with_nul();
std::str::from_utf8_unchecked(bytes)
}
}
pub fn to_rstr_with_nul(&self)->RStr<'a>{
self.to_str_with_nul().into()
}
pub fn to_str(self)->&'a str{
unsafe{
let bytes = std::ffi::CStr::from_ptr(self.ptr.as_ptr() as *const i8).to_bytes();
std::str::from_utf8_unchecked(bytes)
}
}
pub fn to_rstr(self)->RStr<'a>{
self.to_str().into()
}
}
impl<'a> PartialEq for NulStr<'a>{
fn eq(&self,other:&Self)->bool{
self.ptr==other.ptr ||
self.to_str()==other.to_str()
}
}
impl<'a> Eq for NulStr<'a>{}
impl Display for NulStr<'_> {
fn fmt(&self,f:&mut fmt::Formatter<'_>)->fmt::Result{
Display::fmt(self.to_str(),f)
}
}
impl Debug for NulStr<'_> {
fn fmt(&self,f:&mut fmt::Formatter<'_>)->fmt::Result{
Debug::fmt(self.to_str(),f)
}
}