5 stable releases

new 2.1.0 Apr 30, 2025
2.0.1 Apr 29, 2025
2.0.0 Mar 25, 2025
1.0.1 Jul 31, 2024

#322 in Encoding

Download history 220/week @ 2025-01-08 176/week @ 2025-01-15 196/week @ 2025-01-22 115/week @ 2025-01-29 250/week @ 2025-02-05 165/week @ 2025-02-12 220/week @ 2025-02-19 231/week @ 2025-02-26 159/week @ 2025-03-05 340/week @ 2025-03-12 552/week @ 2025-03-19 454/week @ 2025-03-26 631/week @ 2025-04-02 566/week @ 2025-04-09 245/week @ 2025-04-16 528/week @ 2025-04-23

2,013 downloads per month
Used in 7 crates (2 directly)

MIT license

1MB
1K SLoC

i24: A 24-bit Signed Integer Type for Rust

i24 Logo

Crates.ioDocs.rsMSRV: 1.70+

The i24 crate provides a 24-bit signed integer type for Rust, filling the gap between i16 and i32. This type is particularly useful in audio processing, certain embedded systems, and other scenarios where 24-bit precision is required but 32 bits would be excessive.

Features

  • Efficient 24-bit signed integer representation
  • Seamless conversion to and from i32
  • Support for basic arithmetic operations with overflow checking
  • Bitwise operations
  • Conversions from various byte representations (little-endian, big-endian, native)
  • Implements common traits likeDebug,Display,PartialEq,Eq,PartialOrd,Ord, andHash

This crate came about as a part of the Wavers project, which is a Wav file reader and writer for Rust. The i24 struct also has pyo3 bindings for use in Python. Enable thepyo3 feature to use the pyo3 bindings.

Usage

Add this to your`` Cargo.toml`:

 [dependencies]
 i24 = "2.1.0"

Then, in your Rust code:


# #[macro_use] extern crate i24

 let a = i24!(1000);
 let b = i24!(2000);
 let c = a + b;
 assert_eq!(c.to_i32(), 3000);
 assert_eq!(c, i24!(3000));

Thei24! macro allows you to createi24 values at compile time, ensuring that the value is within the valid range.

Then if working with 3-byte representations from disk or the network, you can use theI24DiskMethods trait to read and write i24 slices of ``i24`.

use i24::I24DiskMethods; // Bring extension trait into scope
use i24::i24 as I24; // Import the i24 type
let raw_data: &[u8] = &[0x00, 0x01, 0x02, 0x00, 0x01, 0xFF]; // 2 values
let values: Vec<I24> = I24::read_i24s_be(raw_data).expect("valid buffer");

let encoded: Vec<u8> = I24::write_i24s_be(&values);
assert_eq!(encoded, raw_data);

Safety and Limitations

Whilei24 strives to behave similarly to Rust's built-in integer types, there are some important considerations:

  • The valid range for i24 is [-8,388,608, 8,388,607].
  • Overflow behavior in arithmetic operations matches that of ``i32`.
  • Bitwise operations are performed on the 24-bit representation.

Always use checked arithmetic operations when dealing with untrusted input or when overflow/underflow is a concern.

i24 aligns with the safety requirements of bytemuck (NoUninit, Zeroable and AnyBitPattern), ensuring that it is safe to use for converting between valid bytes and a i24 value. Then when using the I24DiskMethods trait, it is safe to use (internally) the bytemuck::cast_slice function to convert between a slice of bytes and a slice of i24 values.

Feature Flags

  • pyo3: Enables the pyo3 bindings for the i24 type.
  • serde: Enables the Serialize and Deserialize traits for the i24 type.
  • alloc: Enables the I24DiskMethods trait for the i24 type.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under MIT - see the LICENSE file for details.

Benchmarks

The crate was tested using the code found in the i24_benches directory of the repo. The full benchmark data can be found in the benchmark report. Below is a figure which summarises the performance with repsect to the i32 type. From the figure it is clear that the i24 type mostly matches the performance of an i32 with some slight variations.

Durations overview per operation

This crate was developed as part of the Wavers project, a Wav file reader and writer for Rust.

Dependencies