Expand description
§i24: Integer Types for Rust (i24, u24)
The i24 crate provides specialized integer types for Rust: i24 (24-bit signed) and u24 (24-bit unsigned).
These types fill precision gaps in Rust’s integer types
and are particularly useful in audio processing, embedded systems, network protocols, and other scenarios where
specific bit-width precision is required.
§Features
§Integer Types
- i24: 24-bit signed integer (range: -8,388,608 to 8,388,607)
- u24: 24-bit unsigned integer (range: 0 to 16,777,215)
§Core Functionality
- Seamless conversion to/from standard Rust integer types
- Complete arithmetic operations with overflow checking
- Bitwise operations
- Conversions from various byte representations (little-endian, big-endian, native)
- Wire/packed format support for binary protocols
- Compile-time macros:
i24!()andu24!()for checked construction - Implements standard traits:
Debug,Display,PartialEq,Eq,PartialOrd,Ord,Hash
This crate came about as a part of the Wavers project, which is a Wav file reader and writer for Rust.
All integer types have Python bindings available via the pyo3 feature.
§Usage
Add this to your Cargo.toml:
[dependencies]
i24 = "2.2.0"§Basic Usage
use i24::{i24, u24};
// Using macros for compile-time checked construction
let signed_24 = i24!(1000);
let unsigned_24 = u24!(2000);
// Arithmetic operations
let sum_24 = signed_24 + i24!(500);
assert_eq!(sum_24.to_i32(), 1500);
// Conversions
let as_i32: i32 = signed_24.into();
let as_u32: u32 = unsigned_24.into();The i24!() and u24!() macros allow you to create values at compile time, ensuring they’re within the valid range.
§Binary Data and Wire Formats
For working with binary data, all types support reading/writing from byte arrays:
use i24::{I24, U24};
// Reading from bytes (little-endian, big-endian, native)
let bytes_le = [0x00, 0x01, 0x02]; // 3-byte representation
let value = I24::from_le_bytes(bytes_le);
// Writing to bytes
let bytes: [u8; 3] = value.to_be_bytes();
// Bulk operations for slices
let raw_data: &[u8] = &[0x00, 0x01, 0x02, 0x00, 0x01, 0xFF];
let values: Vec<I24> = I24::read_i24s_be(raw_data).expect("valid buffer");
let encoded: Vec<u8> = I24::write_i24s_be(&values);§Safety and Limitations
All integer types strive to behave similarly to Rust’s built-in integer types, with some important considerations:
§Value Ranges
- i24: [-8,388,608, 8,388,607]
- u24: [0, 16,777,215]
§Overflow Behavior
- Arithmetic operations match the behavior of their closest standard Rust integer type
- Bitwise operations are performed on the actual bit-width representation
- Always use checked arithmetic operations when dealing with untrusted input
§Memory Safety
All types align with bytemuck safety requirements (NoUninit, Zeroable, AnyBitPattern), ensuring safe byte-to-value conversions.
The bulk I/O operations use bytemuck::cast_slice internally for efficient, safe conversions.
§Feature Flags
- pyo3: Enables Python bindings for all integer types (i24, u24)
- serde: Enables
SerializeandDeserializetraits for all integer types - alloc: Enables bulk I/O operations and
PackedStructfunctionality - ndarray: Enables
ScalarOperandtrait for use with ndarray operations - num-cast: Enables
NumCasttrait implementations for safe numeric type conversion
§Contributing
Contributions are welcome! Please feel free to submit a Pull Request. This really needs more testing and verification.
§License
This project is licensed under MIT - see the LICENSE file for details.
§Benchmarks
See the benchmark report.
Re-exports§
Modules§
- types
- Integer type implementations for 24-bit signed and unsigned integers.
Macros§
- i24
- creates an
i24from a constant expression will give a compile error if the expression overflows an i24 - u24
- creates an
u24from a constant expression will give a compile error if the expression overflows an u24
Traits§
- Packed
Struct - A trait for types that can be read from and written to packed byte representations.
Functions§
- cast_
native_ slice - Helper function to safely cast native types in mixed structures.