A comprehensive Rust library providing essential utilities for encoding, bit manipulation, and data validation. This crate offers high-performance implementations of commonly needed functionality with both direct conversion methods and efficient iterator-based approaches.
- π Base64 Encoding/Decoding - Complete Base64 support with string conversion and streaming iterators
- π’ Hexadecimal Encoding/Decoding - Full hex support with uppercase/lowercase options and iterator interfaces
- β‘ Bit Manipulation - Efficient bit-level operations with get/set functionality and bit iteration
- π Range Validation - Flexible in-set checking for values within ranges, slices, and collections
- π High Performance - Optimized implementations with zero-copy iterators where possible
- π§ Easy Integration - Simple prelude module for importing all functionality
Add this to your Cargo.toml
:
[dependencies]
cj_common = "1.1.0"
For async channel functionality, enable the channel
feature:
[dependencies]
cj_common = { version = "1.1.0", features = ["channel"] }
The easiest way to get started is by importing the prelude module:
use cj_common::prelude::*;
fn quick_start_example() {
// Base64 encoding
let encoded = "Hello, World!".to_b64_string();
println!("Encoded: {}", encoded);
// Base64 decoding
if let Some(decoded_bytes) = b64_to_bytes(&encoded) {
let decoded = String::from_utf8_lossy(&decoded_bytes);
println!("Decoded: {}", decoded);
}
// Hex encoding
let mut hex_string = String::new();
for hex_pair in "Hello".iter_to_hex() {
hex_string.push_str(hex_pair);
}
println!("Hex: {}", hex_string);
// Bit manipulation
let mut value = 0u8;
value.set_bit(3, true); // Set bit 3
assert_eq!(value.get_bit(3), true);
// Range checking
assert_eq!('m'.in_range('a'..'z'), true);
}
Complete Base64 encoding and decoding with multiple approaches:
use cj_common::prelude::*;
fn base64_direct_conversion_example() {
// String to Base64
let encoded = "Many hands make light work.".to_b64_string();
assert_eq!(encoded, "TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsu");
// Base64 to bytes
if let Some(decoded) = b64_to_bytes("TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsu") {
let text = String::from_utf8_lossy(&decoded);
assert_eq!(text, "Many hands make light work.");
}
}
use cj_common::prelude::*;
fn base64_iterator_example() {
// Encode using iterator
let mut encoded = String::new();
for c in "Many hands make light work.".iter_to_b64() {
encoded.push(c);
}
assert_eq!(encoded, "TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsu");
// Decode using iterator
let mut decoded = Vec::new();
for byte in "TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsu".iter_b64_to_byte() {
decoded.push(byte);
}
let text = String::from_utf8_lossy(&decoded);
assert_eq!(text, "Many hands make light work.");
}
Flexible hexadecimal encoding and decoding with case options:
Note: Uppercase hex is the default output. Most methods have a corresponding
_low()
variant for lowercase output (e.g.,to_hex_be_low()
instead ofto_hex()
).
use cj_common::prelude::*;
fn hex_basic_usage_example() {
// String to hex
let mut hex = String::new();
for hex_pair in "Hello".iter_to_hex() {
hex.push_str(hex_pair);
}
println!("Hex: {}", hex);
// Numeric values
let value = 0x1F2i64;
let hex_be = value.to_hex_be(); // Big-endian
let hex_le = value.to_hex_le(); // Little-endian
let hex_be_low = value.to_hex_be_low(); // Lowercase
}
use cj_common::prelude::*;
fn hex_iterator_example() {
// Encode using iterator
let mut hex_string = String::new();
for hex_pair in "Many hands make light work.".iter_to_hex() {
hex_string.push_str(hex_pair);
}
assert_eq!(hex_string, "4D616E792068616E6473206D616B65206C6967687420776F726B2E");
// Decode using iterator
let mut decoded = Vec::new();
for byte in "4D616E792068616E6473206D616B65206C6967687420776F726B2E".iter_hex_to_byte() {
decoded.push(byte);
}
let text = String::from_utf8_lossy(&decoded);
assert_eq!(text, "Many hands make light work.");
}
Efficient bit-level operations with comprehensive functionality:
use cj_common::prelude::*;
fn basic_bit_operations_example() {
// Get and set individual bits
let x = 0b00000010u8;
assert_eq!(x.get_bit(1), true);
let mut x = 0b00000000u8;
x.set_bit(1, true);
assert_eq!(x, 0b00000010u8);
}
use cj_common::prelude::*;
fn bit_iteration_example() {
// Iterate over bits in a single value
let x = 0xABu8;
let mut bits = Vec::new();
for bit in x.bit_iter() {
bits.push(bit);
}
assert_eq!(bits, [true, true, false, true, false, true, false, true]);
// Iterate over bits in a collection
let data = vec![0xABu8, 0xAB, 0xAB];
let mut all_bits = Vec::new();
for bit in data.iter_to_bit() {
all_bits.push(bit);
}
// Results in 24 bits total (3 bytes Γ 8 bits each)
}
use cj_common::prelude::*;
fn advanced_bit_operations_example() {
// Work with different integer types
let x = [2u128, 2, 2];
for (index, bit) in x.as_slice().iter_to_bit().enumerate() {
match index {
1 | 129 | 257 => assert_eq!(bit, true), // Bit position 1 in each u128
_ => assert_eq!(bit, false),
}
}
}
Flexible validation for checking if values exist within specified ranges or collections:
use cj_common::prelude::*;
fn basic_range_checking_example() {
// Simple range checking
assert_eq!('m'.in_range('a'..'z'), true);
assert_eq!(15.in_range(10..20), true);
assert_eq!(25.in_range(10..20), false);
}
use cj_common::prelude::*;
fn complex_set_validation_example() {
// Character validation with multiple criteria
let test_chars = "lmnop";
for c in test_chars.chars() {
assert_eq!(c.in_range('k'..'q'), true);
// Check against multiple sets
assert_eq!(
c.in_set([
('k'..='l').into(), // RangeInclusive
('m'..'n').into(), // Range
('n'..='p').into(), // RangeInclusive
['a', 'b', 'c'].as_slice().into(), // Slice
"test123".into(), // str
].as_slice()),
true
);
}
// Numeric validation
let numbers = [1_000, 10_000, 100_000_000];
for n in numbers {
assert_eq!(n.in_range(1..200_000_000), true);
assert_eq!(
n.in_set([
(1..=10).into(), // RangeInclusive
(500..2_000).into(), // Range
(9_999..=100_000_000).into(), // RangeInclusive
[30, 90, 700].as_slice().into() // Slice
].as_slice()),
true
);
}
}
This crate is designed with performance in mind:
- Zero-copy iterators where possible to minimize memory allocations
- Optimized algorithms for encoding/decoding operations
- Efficient bit manipulation using native CPU instructions
- Minimal dependencies to reduce compilation time and binary size
This crate includes comprehensive benchmarks to measure performance across all major functionality. The benchmarks cover:
- Base64 encoding/decoding - Both direct conversion and iterator-based approaches
- Hex encoding/decoding - String and binary data with various sizes
- Bit manipulation - Get/set operations and bit iteration across different integer types
- Range validation - Simple range checks and complex set operations
To run the benchmarks:
cargo bench
This will generate detailed performance reports and HTML output (if available) showing timing comparisons across different operations and data sizes.
The benchmarks test various scenarios including:
- Small vs. large data sets
- String vs. binary data encoding
- Direct function calls vs. iterator-based processing
- Different integer types for bit operations
Results are displayed with statistical analysis including confidence intervals and outlier detection.
This project is licensed under either of
- Apache License, Version 2.0, (LICENSE_APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE_MIT or http://opensource.org/licenses/MIT)
at your option.
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.