movable_ref/offset/
integers.rs

1use super::delta::{Nullable, Offset};
2use crate::error::{IntegerOffsetError, IntegerOffsetErrorImpl};
3use crate::pointer::unreachable::{UncheckedOptionExt, OVERFLOW_SUB};
4
5macro_rules! impl_delta_zeroable {
6    ($($type:ty),* $(,)?) => {$(
7        unsafe impl Offset for $type {
8            type Error = IntegerOffsetError;
9
10            fn sub(a: *mut u8, b: *mut u8) -> Result<Self, Self::Error> {
11                let del = match isize::checked_sub(a as usize as _, b as usize as _) {
12                    Some(del) => del,
13                    None => return Err(IntegerOffsetError(IntegerOffsetErrorImpl::Sub(a as usize, b as usize)))
14                };
15
16                if std::mem::size_of::<Self>() < std::mem::size_of::<isize>() && (
17                    (Self::MIN as isize) > del ||
18                    (Self::MAX as isize) < del
19                )
20                {
21                    Err(IntegerOffsetError(IntegerOffsetErrorImpl::Conversion(del)))
22                } else {
23                    Ok(del as _)
24                }
25            }
26
27            unsafe fn sub_unchecked(a: *mut u8, b: *mut u8) -> Self {
28                isize::checked_sub(a as usize as _, b as usize as _).unchecked_unwrap(OVERFLOW_SUB) as _
29            }
30
31            unsafe fn add(self, a: *const u8) -> *mut u8 {
32                <*const u8>::offset(a, self as isize) as *mut u8
33            }
34        }
35
36        impl Nullable for $type {
37            const NULL: Self = 0;
38        }
39    )*};
40}
41
42impl_delta_zeroable! { i8, i16, i32, i64, i128, isize }