movable_ref/offset/
integers.rs1use super::delta::{Nullable, Offset};
2use crate::error::{IntegerOffsetError, IntegerOffsetErrorImpl};
3use crate::pointer::unreachable::{UncheckedOptionExt, OVERFLOW_SUB};
4use core::num::*;
5
6macro_rules! impl_delta_zeroable {
7 ($($type:ty),* $(,)?) => {$(
8 unsafe impl Offset for $type {
9 type Error = IntegerOffsetError;
10
11 fn sub(a: *mut u8, b: *mut u8) -> Result<Self, Self::Error> {
12 let del = match isize::checked_sub(a as usize as _, b as usize as _) {
13 Some(del) => del,
14 None => return Err(IntegerOffsetError(IntegerOffsetErrorImpl::Sub(a as usize, b as usize)))
15 };
16
17 if std::mem::size_of::<Self>() < std::mem::size_of::<isize>() && (
18 (Self::MIN as isize) > del ||
19 (Self::MAX as isize) < del
20 )
21 {
22 Err(IntegerOffsetError(IntegerOffsetErrorImpl::Conversion(del)))
23 } else {
24 Ok(del as _)
25 }
26 }
27
28 unsafe fn sub_unchecked(a: *mut u8, b: *mut u8) -> Self {
29 isize::checked_sub(a as usize as _, b as usize as _).unchecked_unwrap(OVERFLOW_SUB) as _
30 }
31
32 unsafe fn add(self, a: *const u8) -> *mut u8 {
33 <*const u8>::offset(a, self as isize) as *mut u8
34 }
35 }
36
37 impl Nullable for $type {
38 const NULL: Self = 0;
39 }
40 )*};
41}
42
43impl_delta_zeroable! { i8, i16, i32, i64, i128, isize }
44
45macro_rules! impl_delta_nonzero {
46 ($($type:ident $base:ident),* $(,)?) => {$(
47 unsafe impl Offset for $type {
48 type Error = IntegerOffsetError;
49
50 fn sub(a: *mut u8, b: *mut u8) -> Result<Self, Self::Error> {
51 let del = match isize::checked_sub(a as usize as _, b as usize as _) {
52 None => return Err(IntegerOffsetError(IntegerOffsetErrorImpl::Sub(a as usize, b as usize))),
53 Some(0) => return Err(IntegerOffsetError(IntegerOffsetErrorImpl::InvalidNonZero)),
54 Some(del) => del,
55 };
56
57 if std::mem::size_of::<Self>() < std::mem::size_of::<isize>() && (
58 ($base::MIN as isize) > del ||
59 ($base::MAX as isize) < del
60 )
61 {
62 Err(IntegerOffsetError(IntegerOffsetErrorImpl::Conversion(del)))
63 } else {
64 unsafe { Ok(Self::new_unchecked(del as _)) }
66 }
67 }
68
69 unsafe fn sub_unchecked(a: *mut u8, b: *mut u8) -> Self {
70 Self::new_unchecked(isize::checked_sub(a as usize as _, b as usize as _).unchecked_unwrap(OVERFLOW_SUB) as _)
71 }
72
73 unsafe fn add(self, a: *const u8) -> *mut u8 {
74 <*mut u8>::offset(a as _, self.get() as isize) as *mut u8
75 }
76 }
77 )*};
78}
79
80impl_delta_nonzero! { NonZeroI8 i8, NonZeroI16 i16, NonZeroI32 i32, NonZeroI64 i64, NonZeroI128 i128, NonZeroIsize isize }