1#![cfg_attr(not(feature = "std"), no_std)]
2
3#[cfg(feature = "std")]
4extern crate core;
5
6#[cfg(feature = "alloc")]
7extern crate alloc;
8
9use core::cell::{Cell, RefCell};
10#[cfg(feature = "alloc")]
11use core::ops::Deref;
12use core::ptr::{self, NonNull};
13#[cfg(feature = "std")]
14use std::ffi::{CStr, CString};
15#[cfg(feature = "std")]
16use std::os::raw::c_char;
17
18#[cfg(feature = "alloc")]
19use alloc::boxed::Box;
20#[cfg(feature = "alloc")]
21use alloc::rc::Rc;
22#[cfg(feature = "alloc")]
23use alloc::sync::Arc;
24
25macro_rules! asptr_wrapper {
26 ($name:ident) => {
27 impl<T> AsPtr for $name<T> {
28 type Raw = T;
29 #[inline]
30 fn as_ptr(&self) -> *const T {
31 $name::as_ptr(self)
32 }
33 }
34 };
35}
36
37#[cfg(feature = "alloc")]
38macro_rules! owned_ptr_wrapper {
39 ($name:ident) => {
40 impl<T: ?Sized> IntoRaw for $name<T> {
41 type Raw = T;
42 fn into_raw(self) -> *mut T {
43 $name::into_raw(self) as *mut T
44 }
45 }
46 impl<T: ?Sized> FromRaw<T> for $name<T> {
47 unsafe fn from_raw(raw: *mut T) -> $name<T> {
48 $name::from_raw(raw)
49 }
50 }
51 };
52}
53
54pub trait AsPtr {
84 type Raw: ?Sized;
88
89 fn as_ptr(&self) -> *const Self::Raw;
98}
99
100impl<T> AsPtr for [T] {
101 type Raw = T;
102 #[inline]
103 fn as_ptr(&self) -> *const T {
104 <[T]>::as_ptr(self)
105 }
106}
107
108impl<'a, T: ?Sized> AsPtr for &'a T {
109 type Raw = T;
110 #[inline]
111 fn as_ptr(&self) -> *const T {
112 *self as *const T
113 }
114}
115
116impl<T: ?Sized> AsPtr for NonNull<T> {
117 type Raw = T;
118 #[inline]
119 fn as_ptr(&self) -> *const T {
120 NonNull::as_ptr(*self)
121 }
122}
123
124impl<T: ?Sized> AsPtr for *const T {
125 type Raw = T;
126 #[inline]
127 fn as_ptr(&self) -> *const T {
128 *self
129 }
130}
131
132#[cfg(feature = "std")]
133impl AsPtr for CStr {
134 type Raw = c_char;
135 #[inline]
136 fn as_ptr(&self) -> *const c_char {
137 CStr::as_ptr(self)
138 }
139}
140
141#[cfg(feature = "std")]
142impl AsPtr for CString {
143 type Raw = c_char;
144 #[inline]
145 fn as_ptr(&self) -> *const c_char {
146 CStr::as_ptr(self)
147 }
148}
149
150#[cfg(feature = "alloc")]
151impl<T: ?Sized> AsPtr for Box<T> {
152 type Raw = T;
153 #[inline]
154 fn as_ptr(&self) -> *const T {
155 self.deref().as_ptr()
156 }
157}
158
159impl<T> AsPtr for Option<T>
160where
161 T: AsPtr,
162 T::Raw: Sized,
163{
164 type Raw = T::Raw;
165 #[inline]
166 fn as_ptr(&self) -> *const T::Raw {
167 match self {
168 Some(ref v) => v.as_ptr(),
169 None => ptr::null(),
170 }
171 }
172}
173
174asptr_wrapper!(Cell);
175asptr_wrapper!(RefCell);
176#[cfg(feature = "alloc")]
177asptr_wrapper!(Rc);
178#[cfg(feature = "alloc")]
179asptr_wrapper!(Arc);
180
181pub trait IntoRaw {
220 type Raw: ?Sized;
224
225 fn into_raw(self) -> *mut Self::Raw;
234}
235
236#[cfg(feature = "std")]
237impl IntoRaw for CString {
238 type Raw = c_char;
239 #[inline]
240 fn into_raw(self) -> *mut c_char {
241 CString::into_raw(self)
242 }
243}
244
245impl<T: ?Sized> IntoRaw for *mut T {
246 type Raw = T;
247 #[inline]
248 fn into_raw(self) -> *mut T {
249 self
250 }
251}
252
253impl<T: ?Sized> IntoRaw for NonNull<T> {
254 type Raw = T;
255 #[inline]
256 fn into_raw(self) -> *mut T {
257 self.as_ptr()
258 }
259}
260
261impl<T> IntoRaw for Option<T>
262where
263 T: IntoRaw,
264 T::Raw: Sized,
265{
266 type Raw = T::Raw;
267 #[inline]
268 fn into_raw(self) -> *mut T::Raw {
269 match self {
270 Some(v) => v.into_raw(),
271 None => ptr::null_mut(),
272 }
273 }
274}
275
276pub trait FromRaw<T: ?Sized> {
290 unsafe fn from_raw(raw: *mut T) -> Self;
316}
317
318#[cfg(feature = "std")]
321impl FromRaw<c_char> for CString {
322 #[inline]
323 unsafe fn from_raw(raw: *mut c_char) -> CString {
324 CString::from_raw(raw)
325 }
326}
327
328impl<T: ?Sized> FromRaw<T> for *mut T {
330 #[inline]
331 unsafe fn from_raw(raw: *mut T) -> *mut T {
332 raw
333 }
334}
335
336impl<T: ?Sized> FromRaw<T> for *const T {
338 #[inline]
339 unsafe fn from_raw(raw: *mut T) -> *const T {
340 raw
341 }
342}
343
344impl<T: ?Sized> FromRaw<T> for NonNull<T> {
349 #[inline]
350 unsafe fn from_raw(raw: *mut T) -> NonNull<T> {
351 NonNull::new_unchecked(raw)
352 }
353}
354
355impl<T, U: ?Sized> FromRaw<U> for Option<T>
359where
360 T: FromRaw<U>,
361{
362 unsafe fn from_raw(raw: *mut U) -> Option<T> {
363 if raw.is_null() {
364 None
365 } else {
366 Some(T::from_raw(raw))
367 }
368 }
369}
370
371#[cfg(feature = "alloc")]
372owned_ptr_wrapper!(Box);
373#[cfg(feature = "alloc")]
374owned_ptr_wrapper!(Rc);
375#[cfg(feature = "alloc")]
376owned_ptr_wrapper!(Arc);
377
378pub trait FromRawFamily {
379 type Pointer<T: ?Sized>;
380
381 unsafe fn from_raw<T: ?Sized>(raw: *mut T) -> Self::Pointer<T>;
407}
408
409macro_rules! from_raw_family_impl {
410 ($family:ident($t:ty) $v:ident => $from_raw:expr) => {
411 pub struct $family;
412 impl FromRawFamily for $family {
413 type Pointer<T: ?Sized> = $t;
414 unsafe fn from_raw<T: ?Sized>($v: *mut T) -> Self::Pointer<T> {
415 $from_raw
416 }
417 }
418 };
419}
420
421from_raw_family_impl!(MutPtrFamily(*mut T) r => r);
422from_raw_family_impl!(ConstPtrFamily(*const T) r => r);
423from_raw_family_impl!(NonNullFamily(NonNull<T>) r => NonNull::new_unchecked(r));
424
425pub struct OptionFromRawFamily<P> {
427 _phantom: core::marker::PhantomData<P>,
428}
429impl<P: FromRawFamily> FromRawFamily for OptionFromRawFamily<P> {
433 type Pointer<T: ?Sized> = Option<P::Pointer<T>>;
434 unsafe fn from_raw<T: ?Sized>(raw: *mut T) -> Self::Pointer<T> {
435 if raw.is_null() {
436 None
437 } else {
438 Some(P::from_raw(raw))
439 }
440 }
441}
442
443macro_rules! owned_pointer_kind {
444 ($name:ident, $ptr_name:ident) => {
445 from_raw_family_impl!($name($ptr_name<T>) r => $ptr_name::from_raw(r));
446 };
447 }
448
449#[cfg(feature = "alloc")]
450owned_pointer_kind!(BoxFamily, Box);
451#[cfg(feature = "alloc")]
452owned_pointer_kind!(RcFamily, Rc);
453#[cfg(feature = "alloc")]
454owned_pointer_kind!(ArcFamily, Arc);
455
456#[cfg(test)]
457mod tests {
458 use super::*;
459
460 macro_rules! as_ptr_test {
461 ($name:ident, $t:ty, $init:expr, $compare:expr) => {
462 #[test]
463 fn $name() {
464 let x = $init;
465 let y: *const <$t as AsPtr>::Raw = <$t as AsPtr>::as_ptr(&x);
466 unsafe {
467 assert_eq!(*y, $compare);
468 }
469 }
470 };
471 }
472
473 as_ptr_test!(ref_as_ptr, &u32, &5, 5);
474 as_ptr_test!(nonnull_as_ptr, NonNull<u32>, NonNull::from(&5), 5);
476 as_ptr_test!(ptr_as_ptr, *const u32, &5u32 as *const u32, 5);
477 #[cfg(feature = "std")]
478 as_ptr_test!(
479 cstr_as_ptr,
480 CStr,
481 CStr::from_bytes_with_nul("abc\0".as_bytes()).unwrap(),
482 'a' as c_char
483 );
484 #[cfg(feature = "std")]
485 as_ptr_test!(
486 cstring_as_ptr,
487 CString,
488 CString::new("abc").unwrap(),
489 'a' as c_char
490 );
491 #[cfg(feature = "alloc")]
492 as_ptr_test!(box_as_ptr, Box<u16>, Box::new(3u16), 3);
493 as_ptr_test!(cell_as_ptr, Cell<u16>, Cell::new(7u16), 7);
494 as_ptr_test!(refcell_as_ptr, RefCell<u16>, RefCell::new(7u16), 7);
495 #[cfg(feature = "alloc")]
496 as_ptr_test!(rc_as_ptr, Rc<u16>, Rc::new(8u16), 8);
497 #[cfg(feature = "alloc")]
498 as_ptr_test!(arc_as_ptr, Arc<u16>, Arc::new(8u16), 8);
499
500 as_ptr_test!(some_as_ptr, Option<&u32>, Some(&1u32), 1);
501 #[test]
502 fn none_as_ptr() {
503 let x: Option<&u16> = None;
504 let y: *const u16 = <Option<&u16> as AsPtr>::as_ptr(&x);
505 assert!(y.is_null());
506 }
507
508 #[cfg(feature = "alloc")]
509 macro_rules! from_into_test {
510 ($name:ident, $t:ty, $init: expr, $cmp:expr) => {
511 #[test]
512 fn $name() {
513 let orig = $init;
514 let p = <$t as IntoRaw>::into_raw(orig);
515 let back = unsafe { <$t as FromRaw<_>>::from_raw(p) };
516 assert_eq!(*back, $cmp);
517 }
518 };
519 }
520
521 #[cfg(feature = "std")]
522 from_into_test!(
523 cstring_from_into,
524 CString,
525 CString::new("abc").unwrap(),
526 *CStr::from_bytes_with_nul("abc\0".as_bytes()).unwrap()
527 );
528 #[cfg(feature = "alloc")]
529 from_into_test!(box_from_into, Box<u16>, Box::new(4u16), 4);
530 #[cfg(feature = "alloc")]
531 from_into_test!(rc_from_into, Rc<u16>, Rc::new(4u16), 4);
532 #[cfg(feature = "alloc")]
533 from_into_test!(arc_from_into, Arc<u16>, Arc::new(4u16), 4);
534
535 #[test]
536 fn ptr_from_into() {
537 let mut data: u32 = 10;
538 let p = <*mut u32 as IntoRaw>::into_raw(&mut data);
539 unsafe {
540 let mptr: *mut u32 = <*mut u32 as FromRaw<_>>::from_raw(p);
541 *mptr = 54;
542 }
543 unsafe {
544 let cptr = <*const u32 as FromRaw<_>>::from_raw(p);
545 assert_eq!(*cptr, 54);
546 }
547 }
548
549 #[test]
550 fn nonnull_from_into() {
551 let mut data: u32 = 10;
552 let p = <NonNull<u32> as IntoRaw>::into_raw(NonNull::from(&mut data));
553 unsafe {
554 *p = 34;
555 let p = <NonNull<u32> as FromRaw<_>>::from_raw(p);
556 assert_eq!(p, NonNull::from(&data));
557 }
558 assert_eq!(data, 34);
559 }
560
561 #[test]
562 fn some_from_into() {
563 let mut data: u32 = 10;
564 let p = <Option<*mut u32> as IntoRaw>::into_raw(Some(&mut data));
565 unsafe {
566 *p = 54;
567 let p = <Option<*const u32> as FromRaw<_>>::from_raw(p);
568 assert_eq!(p, Some(&data as *const u32));
569 };
570 assert_eq!(data, 54);
571 }
572
573 #[test]
574 fn none_into() {
575 assert!(<Option<*mut u16> as IntoRaw>::into_raw(None).is_null());
576 }
577
578 #[test]
579 fn none_from() {
580 let p = unsafe { <Option<*mut u16> as FromRaw<_>>::from_raw(core::ptr::null_mut()) };
581 assert_eq!(p, None);
582 }
583
584 fn family_round_trip<F: FromRawFamily, V>(v: F::Pointer<V>) -> F::Pointer<V>
587 where
588 F::Pointer<V>: IntoRaw<Raw = V>,
589 {
590 let p = v.into_raw();
591 unsafe { F::from_raw(p) }
592 }
593
594 fn test_from_family<F: FromRawFamily, V>(p: F::Pointer<V>, cmp: &V)
595 where
596 F::Pointer<V>: IntoRaw<Raw = V> + Deref<Target = V>,
597 V: std::fmt::Debug + Eq,
598 {
599 let ptr = family_round_trip::<F, _>(p);
600 assert_eq!(&*ptr, cmp);
601 }
602
603 #[test]
604 fn mut_ptr_family() {
605 let mut x = 4;
606 let p = family_round_trip::<MutPtrFamily, _>(&mut x as *mut _);
607 assert_eq!(p, &mut x as *mut _);
608 assert_eq!(unsafe { *p }, 4);
609 }
610
611 #[test]
612 fn const_ptr_family() {
613 let mut x = 23;
614 let p = unsafe { ConstPtrFamily::from_raw(&mut x as *mut _) };
615 assert_eq!(p, &x as *const _);
616 assert_eq!(unsafe { *p }, 23);
617 }
618
619 #[test]
620 fn nonnull_family() {
621 let mut x = 23;
622 let p = unsafe { NonNull::from_raw(&mut x as *mut _) };
623 assert_eq!(p, (&x).into());
624 assert_eq!(unsafe { *p.as_ref() }, 23);
625 }
626
627 #[test]
628 fn option_family_none() {
629 let n = ptr::null_mut::<u8>();
630
631 assert!(unsafe { OptionFromRawFamily::<MutPtrFamily>::from_raw(n) }.is_none());
632 }
633
634 #[test]
635 fn option_family_some() {
636 let mut x = 89;
637
638 let p = unsafe { OptionFromRawFamily::<MutPtrFamily>::from_raw(&mut x as *mut _) };
639 assert!(p.is_some());
640 assert_eq!(p, Some(&mut x as *mut _));
641 assert_eq!(unsafe { *p.unwrap() }, 89);
642 }
643
644 #[test]
645 fn box_family() {
646 test_from_family::<BoxFamily, _>(Box::new(16), &16);
647 }
648
649 #[test]
650 fn rc_family() {
651 test_from_family::<RcFamily, _>(Rc::new(16), &16);
652 }
653
654 #[test]
655 fn arc_family() {
656 test_from_family::<ArcFamily, _>(Arc::new(16), &16);
657 }
658}