use super::*;
use crate::const_utils::{min_u16, min_u8};
use std::ops::{Range, RangeInclusive};
#[repr(transparent)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, StableAbi)]
pub struct StartLen {
bits: u32,
}
pub type StartLenRepr = u32;
impl StartLen {
#[inline]
pub const fn new(start: u16, len: u16) -> Self {
Self {
bits: (start as u32) | ((len as u32) << 16),
}
}
#[inline]
pub const fn start(self) -> u16 {
self.bits as u16
}
#[inline]
pub const fn len(self) -> u16 {
(self.bits >> 16) as u16
}
pub const fn is_empty(self) -> bool {
self.len() == 0
}
#[inline]
pub const fn start_usize(self) -> usize {
(self.bits & 0xffff) as usize
}
#[inline]
pub const fn len_usize(self) -> usize {
(self.bits >> 16) as usize
}
#[inline]
pub const fn end_usize(self) -> usize {
self.start_usize() + self.len_usize()
}
#[inline]
pub const fn to_range(self) -> Range<usize> {
self.start_usize()..self.end_usize()
}
#[inline]
pub const fn from_u32(n: StartLenRepr) -> Self {
Self { bits: n }
}
pub const EMPTY: Self = Self::new(0, 0);
abi_stable_shared::declare_start_len_bit_methods! {}
}
pub struct StartLenConverter<T>(pub T);
#[allow(clippy::wrong_self_convention)]
impl StartLenConverter<()> {
pub const fn to_start_len(self) -> StartLen {
StartLen::EMPTY
}
}
#[allow(clippy::wrong_self_convention)]
impl StartLenConverter<usize> {
pub const fn to_start_len(self) -> StartLen {
StartLen::new(self.0 as u16, 1)
}
}
#[allow(clippy::wrong_self_convention)]
impl StartLenConverter<Range<usize>> {
pub const fn to_start_len(self) -> StartLen {
let start = self.0.start as u16;
let len = (self.0.end - self.0.start) as u16;
StartLen::new(start, len)
}
}
#[allow(clippy::wrong_self_convention)]
impl StartLenConverter<RangeInclusive<usize>> {
pub const fn to_start_len(self) -> StartLen {
let start = *self.0.start();
let end = *self.0.end() + 1;
StartLen::new(start as u16, (end - start) as u16)
}
}
#[allow(clippy::wrong_self_convention)]
impl StartLenConverter<StartLen> {
pub const fn to_start_len(self) -> StartLen {
self.0
}
}
#[repr(transparent)]
#[derive(Copy, Clone, PartialEq, Eq, Ord, PartialOrd, StableAbi)]
pub struct OptionU16(u16);
impl OptionU16 {
#[allow(non_upper_case_globals)]
pub const None: Self = OptionU16(!0);
const MAX_VAL: u16 = !0 - 1;
pub const fn some(value: u16) -> Self {
OptionU16(min_u16(value, Self::MAX_VAL))
}
pub const fn eq(self, other: Self) -> bool {
self.0 == other.0
}
pub const fn ne(self, other: Self) -> bool {
self.0 != other.0
}
pub const fn is_some(self) -> bool {
self.ne(Self::None)
}
pub const fn is_none(self) -> bool {
self.eq(Self::None)
}
pub const fn to_option(self) -> Option<u16> {
if self.is_some() {
Some(self.0)
} else {
None
}
}
}
impl Debug for OptionU16 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Debug::fmt(&self.to_option(), f)
}
}
impl Display for OptionU16 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.is_some() {
Display::fmt("None", f)
} else {
Display::fmt(&self.0, f)
}
}
}
#[repr(transparent)]
#[derive(Copy, Clone, PartialEq, Eq, Ord, PartialOrd, StableAbi)]
pub struct OptionU8(u8);
impl OptionU8 {
#[allow(non_upper_case_globals)]
pub const None: Self = OptionU8(!0);
const MAX_VAL: u8 = !0 - 1;
pub const fn some(value: u8) -> Self {
OptionU8(min_u8(value, Self::MAX_VAL))
}
pub const fn eq(self, other: Self) -> bool {
self.0 == other.0
}
pub const fn ne(self, other: Self) -> bool {
self.0 != other.0
}
pub const fn is_some(self) -> bool {
self.ne(Self::None)
}
pub const fn is_none(self) -> bool {
self.eq(Self::None)
}
pub const fn to_option(self) -> Option<u8> {
if self.is_some() {
Some(self.0)
} else {
None
}
}
}
impl Debug for OptionU8 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Debug::fmt(&self.to_option(), f)
}
}
impl Display for OptionU8 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.is_some() {
Display::fmt("None", f)
} else {
Display::fmt(&self.0, f)
}
}
}