dairy/imp/compact/
convert.rs1use core::mem::ManuallyDrop;
4use core::ptr;
5use core::ptr::NonNull;
6
7use alloc::borrow::ToOwned;
8use alloc::string::String;
9use alloc::vec::Vec;
10
11#[cfg(all(feature = "std", unix))]
12use std::os::unix::ffi::{OsStrExt, OsStringExt};
13#[cfg(all(feature = "std", target_os = "wasi"))]
14use std::os::wasi::ffi::{OsStrExt, OsStringExt};
15
16use super::extent::Extent;
17
18pub trait IsOwned {
20 fn is_owned(&self) -> bool;
21}
22
23pub unsafe trait Convert: ToOwned {
25 type Ptr;
27
28 type Extent: Copy + Default + IsOwned;
31
32 fn unmake_borrowed(b: &Self) -> (NonNull<Self::Ptr>, Self::Extent);
34
35 fn unmake_owned(o: Self::Owned) -> (NonNull<Self::Ptr>, Self::Extent);
37
38 unsafe fn make_ptr(ptr: NonNull<Self::Ptr>, extra: Self::Extent) -> *const Self;
40
41 unsafe fn make_owned(ptr: NonNull<Self::Ptr>, extra: Self::Extent) -> Self::Owned;
43}
44
45impl IsOwned for bool {
46 #[inline]
47 fn is_owned(&self) -> bool {
48 *self
49 }
50}
51
52impl IsOwned for Extent {
53 #[inline]
54 fn is_owned(&self) -> bool {
55 self.capacity() != 0
56 }
57}
58
59unsafe impl Convert for str {
60 type Ptr = u8;
61 type Extent = Extent;
62
63 #[inline]
64 fn unmake_borrowed(b: &Self) -> (NonNull<Self::Ptr>, Self::Extent) {
65 unsafe { Extent::borrowed(b.as_ptr(), b.len()) }
66 }
67
68 #[inline]
69 fn unmake_owned(o: Self::Owned) -> (NonNull<Self::Ptr>, Self::Extent) {
70 let mut o = ManuallyDrop::new(o);
71 unsafe { Extent::owned(o.as_mut_ptr(), o.len(), o.capacity()) }
72 }
73
74 #[inline]
75 unsafe fn make_ptr(ptr: NonNull<Self::Ptr>, extra: Self::Extent) -> *const Self {
76 ptr::slice_from_raw_parts(ptr.as_ptr(), extra.len()) as *const Self
77 }
78
79 #[inline]
80 unsafe fn make_owned(ptr: NonNull<Self::Ptr>, extra: Self::Extent) -> Self::Owned {
81 unsafe { String::from_raw_parts(ptr.as_ptr(), extra.len(), extra.capacity()) }
82 }
83}
84
85unsafe impl<T: Clone> Convert for [T] {
86 type Ptr = T;
87 type Extent = Extent;
88
89 #[inline]
90 fn unmake_borrowed(b: &Self) -> (NonNull<Self::Ptr>, Self::Extent) {
91 unsafe { Extent::borrowed(b.as_ptr(), b.len()) }
92 }
93
94 #[inline]
95 fn unmake_owned(o: Self::Owned) -> (NonNull<Self::Ptr>, Self::Extent) {
96 let mut o = ManuallyDrop::new(o);
97 unsafe { Extent::owned(o.as_mut_ptr(), o.len(), o.capacity()) }
98 }
99
100 #[inline]
101 unsafe fn make_ptr(ptr: NonNull<Self::Ptr>, extra: Self::Extent) -> *const Self {
102 ptr::slice_from_raw_parts(ptr.as_ptr(), extra.len())
103 }
104
105 #[inline]
106 unsafe fn make_owned(ptr: NonNull<Self::Ptr>, extra: Self::Extent) -> Self::Owned {
107 unsafe { Vec::from_raw_parts(ptr.as_ptr(), extra.len(), extra.capacity()) }
108 }
109}
110
111#[cfg(feature = "std")]
112unsafe impl Convert for std::ffi::CStr {
113 type Ptr = std::os::raw::c_char;
114 type Extent = bool;
115
116 #[inline]
117 fn unmake_borrowed(b: &Self) -> (NonNull<Self::Ptr>, Self::Extent) {
118 let ptr = unsafe { NonNull::new_unchecked(b.as_ptr() as *mut Self::Ptr) };
119 (ptr, false)
120 }
121
122 #[inline]
123 fn unmake_owned(o: Self::Owned) -> (NonNull<Self::Ptr>, Self::Extent) {
124 let ptr = unsafe { NonNull::new_unchecked(o.into_raw()) };
125 (ptr, true)
126 }
127
128 #[inline]
129 unsafe fn make_ptr(ptr: NonNull<Self::Ptr>, _: Self::Extent) -> *const Self {
130 unsafe { Self::from_ptr(ptr.as_ptr()) as *const Self }
131 }
132
133 #[inline]
134 unsafe fn make_owned(ptr: NonNull<Self::Ptr>, _: Self::Extent) -> Self::Owned {
135 unsafe { std::ffi::CString::from_raw(ptr.as_ptr()) }
136 }
137}
138
139#[cfg(all(feature = "std", os_str_ext))]
140unsafe impl Convert for std::ffi::OsStr {
141 type Ptr = u8;
142 type Extent = Extent;
143
144 #[inline]
145 fn unmake_borrowed(b: &Self) -> (NonNull<Self::Ptr>, Self::Extent) {
146 <[u8]>::unmake_borrowed(b.as_bytes())
147 }
148
149 #[inline]
150 fn unmake_owned(o: Self::Owned) -> (NonNull<Self::Ptr>, Self::Extent) {
151 <[u8]>::unmake_owned(o.into_vec())
152 }
153
154 #[inline]
155 unsafe fn make_ptr(ptr: NonNull<Self::Ptr>, extra: Self::Extent) -> *const Self {
156 unsafe { <[u8]>::make_ptr(ptr, extra) as *const Self }
157 }
158
159 #[inline]
160 unsafe fn make_owned(ptr: NonNull<Self::Ptr>, extra: Self::Extent) -> Self::Owned {
161 unsafe { std::ffi::OsString::from_vec(<[u8]>::make_owned(ptr, extra)) }
162 }
163}
164
165#[cfg(all(feature = "std", os_str_ext))]
166unsafe impl Convert for std::path::Path {
167 type Ptr = u8;
168 type Extent = Extent;
169
170 #[inline]
171 fn unmake_borrowed(b: &Self) -> (NonNull<Self::Ptr>, Self::Extent) {
172 std::ffi::OsStr::unmake_borrowed(b.as_os_str())
173 }
174
175 #[inline]
176 fn unmake_owned(o: Self::Owned) -> (NonNull<Self::Ptr>, Self::Extent) {
177 std::ffi::OsStr::unmake_owned(o.into_os_string())
178 }
179
180 #[inline]
181 unsafe fn make_ptr(ptr: NonNull<Self::Ptr>, extra: Self::Extent) -> *const Self {
182 unsafe { std::ffi::OsStr::make_ptr(ptr, extra) as *const Self }
183 }
184
185 #[inline]
186 unsafe fn make_owned(ptr: NonNull<Self::Ptr>, extra: Self::Extent) -> Self::Owned {
187 unsafe { std::path::PathBuf::from(std::ffi::OsStr::make_owned(ptr, extra)) }
188 }
189}