dairy/imp/compact/
convert.rs

1//! Convert a [`ToOwned`] type to and from parts.
2
3use 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
18/// Whether or not this extra data describes an owned type.
19pub trait IsOwned {
20    fn is_owned(&self) -> bool;
21}
22
23/// Convert a [`ToOwned`] type to and from parts.
24pub unsafe trait Convert: ToOwned {
25    /// The pointer type that will be used in the better `Cow`.
26    type Ptr;
27
28    /// Any extra data that is required to reconstruct an owned or borrowed
29    /// variant of this type. For example: length and capacity.
30    type Extent: Copy + Default + IsOwned;
31
32    /// Convert a borrowed version of self into parts.
33    fn unmake_borrowed(b: &Self) -> (NonNull<Self::Ptr>, Self::Extent);
34
35    /// Convert an owned version of self into parts.
36    fn unmake_owned(o: Self::Owned) -> (NonNull<Self::Ptr>, Self::Extent);
37
38    /// Returns a pointer to self constructed from parts.
39    unsafe fn make_ptr(ptr: NonNull<Self::Ptr>, extra: Self::Extent) -> *const Self;
40
41    /// Returns an owned version of self constructed from parts.
42    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}