Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions intid-core/src/trusted.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,12 @@ impl<T: IntegerId> TrustedRangeToken<T> {
}
}
}

/*
/// Indicates
pub struct TrustedContiguousToken<T> {

}
impl<T: IntegerId> TrustedContiguousToken<T> {
}
*/
28 changes: 28 additions & 0 deletions intid-core/src/uint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

use core::fmt::{Debug, Display, Formatter};
use core::hash::Hash;
use core::ops::{Add, Div, Mul, Sub};

mod sealed;

Expand Down Expand Up @@ -56,9 +57,36 @@ pub trait UnsignedPrimInt:
+ MaybeNumTrait
+ MaybePod
+ MaybeContiguous
+ Add<Output=Self>
+ Sub<Output=Self>
+ Mul<Output=Self>
+ Div<Output=Self>
{
}

/// Subtract the specified value from the integer,
/// triggering UB if the subtraction overflows.
///
/// # Safety
/// Undefined behavior if the subtraction overflows.
#[inline]
pub unsafe fn unchecked_sub<T: UnsignedPrimInt>(left: T, right: T) -> T {
// SAFETY: Delegates responsibility
unsafe { sealed::PrivateUnsignedInt::unchecked_sub(left, right) }
}


/// Add the specified values,
/// triggering UB if the addition overflows.
///
/// # Safety
/// Undefined behavior if the addition overflows.
#[inline]
pub unsafe fn unchecked_add<T: UnsignedPrimInt>(left: T, right: T) -> T {
// SAFETY: Delegates responsibility
unsafe { sealed::PrivateUnsignedInt::unchecked_add(left, right) }
}

/// Cast from one [`UnsignedPrimInt`] into another,
/// returning `None` if there is overflow.
#[inline]
Expand Down
12 changes: 12 additions & 0 deletions intid-core/src/uint/sealed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ pub trait PrivateUnsignedInt: Sized {
const TYPE_NAME: &'static str;
fn checked_add(self, other: Self) -> Option<Self>;
fn checked_sub(self, other: Self) -> Option<Self>;
unsafe fn unchecked_add(self, other: Self) -> Self;
unsafe fn unchecked_sub(self, other: Self) -> Self;
fn from_usize_checked(val: usize) -> Option<Self>;
fn from_usize_wrapping(val: usize) -> Self;
#[allow(clippy::wrong_self_convention)]
Expand Down Expand Up @@ -39,6 +41,16 @@ macro_rules! impl_primint {
<$target>::checked_sub(self, other)
}
#[inline]
unsafe fn unchecked_add(self, other: Self) -> Self {
// SAFETY: Simply delegates
unsafe { <$target>::unchecked_add(self, other) }
}
#[inline]
unsafe fn unchecked_sub(self, other: Self) -> Self {
// SAFETY: Simply delegates
unsafe { <$target>::unchecked_sub(self, other) }
}
#[inline]
fn from_usize_checked(val: usize) -> Option<Self> {
<$target>::try_from(val).ok()
}
Expand Down
1 change: 1 addition & 0 deletions intid-core/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Miscellaneous utilities relating to the [`IntegerId`](crate::IntegerId) trait.

mod order;
mod iter;

pub use self::order::OrderByInt;
82 changes: 82 additions & 0 deletions intid-core/src/utils/iter.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
use core::iter::StepBy;
use core::num::NonZero;
use crate::IntegerIdContiguous;

pub fn contiguous<T: IntegerIdContiguous>() -> IterContiguous<T> {
IterContiguous {
next: T::MIN_ID_INT,
}
}

/// Indicates that the result of [`IterContiguous::len`] overflowed a [`u64`].
#[derive(Copy, Clone, Debug)]
#[non_exhaustive]
pub struct IterLengthOverflowError;

pub struct IterContiguous<T: IntegerIdContiguous> {
/// The next value to be returned from the iterator.
///
/// Invariants:
/// - When not `None`, `T::MIN_ID_INT <= next.to_int <= T::MAX_ID_INT`
next: Option<T>,
}
impl<T: IntegerIdContiguous> IterContiguous<T> {
pub fn len(&self) -> Result<u64, IterLengthOverflowError> {
match self.next {
None => Ok(0),
Some(current) => {
// Cannot overflow because Some(next) <= T::MAX_ID
//
// We can make this addition unchecked only if we trust the range
let delta = if T::TRUSTED_RANGE.is_some() {
// SAFETY: We trust the range and our own invariants
unsafe {
crate::uint::unchecked_sub(
T::MAX_ID_INT.unwrap(),
current.to_int()
)
}
} else {
T::MAX_ID_INT.unwrap() - current.to_int()
};
u64::try_from(delta).ok_or(IterLengthOverflowError)
}
}
}
}

impl<T: IntegerIdContiguous> core::iter::FusedIterator for IterContiguous<T> {}
impl<T: IntegerIdContiguous> Iterator for IterContiguous<T> {
type Item = T;

fn next(&mut self) -> Option<Self::Item> {

}

fn nth(&mut self, n: usize) -> Option<Self::Item> {
todo!()
}

fn count(self) -> usize
where
Self: Sized,
{
todo!()
}

#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.next.unwrap().to_int();
}
}
impl<T: IntegerIdContiguous> ExactSizeIterator for IterContiguous<T> where T::Int: SmallerThanUsize {}

/// Implemented for integer types smaller than a [`usize`].
///
/// Not implemented for `u32` on 64-bit platforms because that would be a portability hazard.
/// It is implemented for `u16` on 32-bit/64-bit platforms,
/// because supporting 16-bit platforms is rare in modern codebases.
trait SmallerThanUsize {}
#[cfg(not(target_pointer_width = "16"))]
impl SmallerThanUsize for u16 {}
impl SmallerThanUsize for u8 {}
Loading