Skip to content

Make LenType opt-in #569

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

- `bytes::BufMut` is now implemented on `VecInner`.
- Removed generic from `history_buf::OldestOrdered`.
- Made `LenType` opt-in.

### Fixed

Expand All @@ -19,6 +20,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Removed

- Removed invalid `bytes::Buf` implementation.
- Removed `DefaultLenType` struct.

## [v0.9.0] - 2025-04-28 [YANKED]

Expand Down
4 changes: 2 additions & 2 deletions src/c_string.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! A fixed capacity [`CString`](https://doc.rust-lang.org/std/ffi/struct.CString.html).

use crate::{len_type::DefaultLenType, vec::Vec, CapacityError, LenType};
use crate::{vec::Vec, CapacityError, LenType};
use core::{
borrow::Borrow,
cmp::Ordering,
Expand All @@ -14,7 +14,7 @@ use core::{
///
/// It stores up to `N - 1` non-nul characters with a trailing nul terminator.
#[derive(Clone, Hash)]
pub struct CString<const N: usize, LenT: LenType = DefaultLenType<N>> {
pub struct CString<const N: usize, LenT: LenType = usize> {
inner: Vec<u8, N, LenT>,
}

Expand Down
180 changes: 0 additions & 180 deletions src/len_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,186 +85,6 @@ impl_lentype!(
usize
);

macro_rules! impl_lentodefault {
($LenT:ty: $($len:literal),*) => {$(
impl SmallestLenType for Const<$len> {
type Type = $LenT;
}
)*};
}

/// A struct to create individual types for mapping with [`SmallestLenType`].
///
/// See the documentation of [`DefaultLenType`] for a detailed explanation.
pub struct Const<const N: usize>;

/// A trait to map [`Const`] to it's respective [`LenType`].
///
/// See the documentation of [`DefaultLenType`] for a detailed explanation.
#[diagnostic::on_unimplemented(
message = "Length `N` does not have a default `LenType` mapping",
note = "Provide the `LenType` explicitly, such as `usize`"
)]
pub trait SmallestLenType {
type Type: LenType;
}

/// A type alias to perform the `const N: usize` -> `LenType` mapping.
///
/// This is impossible to perform directly, but it is possible to write a `const N: usize` -> related `Type` mapping via a const generic argument,
/// then map from that to an unrelated type via a trait with associated types.
///
/// [`Const`] is the "related type" in the above explaination, [`SmallestLenType`] is the mapping trait.
#[allow(rustdoc::private_intra_doc_links)] // Only publically exposed via `crate::_export`
pub type DefaultLenType<const N: usize> = <Const<N> as SmallestLenType>::Type;

impl_lentodefault!(ZeroLenType: 0);
impl_lentodefault!(u8: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255);
impl_lentodefault!(u16: 256, 300, 400, 500, 512, 600, 700, 800, 900, 1000, 1024, 2000, 2048, 4000, 4096, 8000, 8192, 16000, 16384, 32000, 32768, 65000, 65535);
#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
impl_lentodefault!(u32: 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824, 2147483648);

pub const fn check_capacity_fits<LenT: LenType, const N: usize>() {
assert!(LenT::MAX_USIZE >= N, "The capacity is larger than `LenT` can hold, increase the size of `LenT` or reduce the capacity");
}

/// Container with 0 capacity always has length 0, so there is no need to track length of such containers at all.
///
/// This type is used as a placeholder for length of container with 0 capacity. It allows optimizing total size of
/// containers like this to 0 bytes.
///
/// Logically, this type always stores value 0. Because of this ZeroLenType::one() panics and should never be called.
#[doc(hidden)]
#[derive(Copy, Clone, PartialEq, PartialOrd)]
pub struct ZeroLenType;

impl Debug for ZeroLenType {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "0")
}
}

impl Display for ZeroLenType {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "0")
}
}

impl Sealed for ZeroLenType {
const ZERO: Self = Self;

const MAX: Self = Self;
const MAX_USIZE: usize = 0;

#[inline]
fn one() -> Self {
panic!("ZeroLenType cannot represent value 1");
}
}

impl LenType for ZeroLenType {}

impl Add for ZeroLenType {
type Output = Self;

fn add(self, _rhs: Self) -> Self::Output {
Self::ZERO
}
}

impl AddAssign for ZeroLenType {
fn add_assign(&mut self, _rhs: Self) {}
}

impl Sub for ZeroLenType {
type Output = Self;

fn sub(self, _rhs: Self) -> Self::Output {
Self::ZERO
}
}

impl SubAssign for ZeroLenType {
fn sub_assign(&mut self, _rhs: Self) {}
}

#[doc(hidden)]
#[derive(Debug, PartialEq)]
pub struct ZeroLenTypeTryFromError;

impl TryFrom<usize> for ZeroLenType {
type Error = ZeroLenTypeTryFromError;

fn try_from(value: usize) -> Result<Self, Self::Error> {
if value > 0 {
return Err(ZeroLenTypeTryFromError);
}

Ok(Self::ZERO)
}
}

impl TryInto<usize> for ZeroLenType {
type Error = ();

fn try_into(self) -> Result<usize, Self::Error> {
Ok(0)
}
}

#[cfg(test)]
mod tests {
use crate::len_type::{Sealed, ZeroLenType, ZeroLenTypeTryFromError};

#[test]
pub fn test_zero_len_type_conversions() {
assert_eq!(ZeroLenType::into_usize(ZeroLenType::ZERO), 0_usize);
assert_eq!(ZeroLenType::from_usize(0_usize), ZeroLenType::ZERO);

assert_eq!(ZeroLenType::ZERO.try_into(), Ok(0_usize));
assert_eq!(ZeroLenType::try_from(0_usize), Ok(ZeroLenType::ZERO));
assert_eq!(ZeroLenType::try_from(1_usize), Err(ZeroLenTypeTryFromError));
}

#[test]
#[should_panic]
pub fn test_zero_len_type_one() {
ZeroLenType::one();
}

#[test]
#[should_panic]
pub fn test_zero_len_type_one_usize() {
ZeroLenType::from_usize(1);
}

#[test]
pub fn test_zero_len_type_constants() {
assert_eq!(ZeroLenType::ZERO, ZeroLenType);
assert_eq!(ZeroLenType::MAX, ZeroLenType);
assert_eq!(ZeroLenType::MAX_USIZE, 0_usize);
}

#[test]
pub fn test_zero_len_type_size() {
assert_eq!(core::mem::size_of::<ZeroLenType>(), 0);
}

#[test]
pub fn test_zero_len_type_ops() {
assert_eq!(ZeroLenType::ZERO + ZeroLenType::ZERO, ZeroLenType::ZERO);
assert_eq!(ZeroLenType::ZERO - ZeroLenType::ZERO, ZeroLenType::ZERO);

let mut zero = ZeroLenType::ZERO;
zero += ZeroLenType::ZERO;
assert_eq!(zero, ZeroLenType::ZERO);
zero -= ZeroLenType::ZERO;
assert_eq!(zero, ZeroLenType::ZERO);
}

#[test]
pub fn test_zero_len_type_debug() {
assert_eq!(format!("{}", ZeroLenType), "0");
assert_eq!(format!("{:?}", ZeroLenType), "0");
}
}
1 change: 0 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,6 @@ mod ufmt;
/// Do not use. Used for macros only. Not covered by semver guarantees.
#[doc(hidden)]
pub mod _export {
pub use crate::len_type::DefaultLenType;
pub use crate::string::format;
}

Expand Down
Loading