| Crates.io | unitx |
| lib.rs | unitx |
| version | 0.1.3 |
| created_at | 2025-12-07 04:59:37.421703+00 |
| updated_at | 2025-12-16 03:52:54.668394+00 |
| description | A general-purpose library for units and quantities |
| homepage | |
| repository | |
| max_upload_size | |
| id | 1971183 |
| size | 104,665 |
UnitX is a general-purpose Rust library for strongly-typed units and quantities. It provides a standard reference for abstract units across measurement categories including:
See CHANGELOG.md for a complete list of changes.
Add, Sub, Mul, Div, etc.).Delta<T> type for meaningful differences (e.g., temperature differences).Deref and Display support for ergonomic usage.⚠ Important Note on Temperature:
Operations like adding or multiplying cross-type temperatures (Celsius + Fahrenheit) are physically meaningless and are intentionally not implemented.
Operations between the same type are mathematically allowed for convenience but may not represent true thermodynamic operations. Subtraction is implemented for both cross-type and same-type temperatures and produces aDelta<T>representing temperature difference.
unitx::unit_value::digital_storageThis crate follows IEC binary unit definitions exactly. As a result, some results may differ from values shown by Google or other online converters.
Binary units such as KiB, MiB, GiB, TiB, PiB, EiB are defined as powers of two, not approximations:
1 EiB = 2^60 = 1_152_921_504_606_846_976 bytes (exact)
When multiplying large binary units by fractional values, this crate:
Online converters (including Google) typically:
double (f64)This leads to measurable errors at large scales.
15.9912132131111 EiB
| Source | Result (bytes) |
|---|---|
1.8436613598148942e+19 |
|
| This crate | 18_409_823_801_615_719_424 |
The Google value differs by ≈ 26.8 petabytes.
✔ The value returned by this crate is mathematically correct and spec-compliant.
This crate guarantees:
If correctness matters more than estimation, trust the crate — not the converter UI.
📦 Result Type & Error Semantics
All constructors in the digital_storage module return a Result<DataValue, DigitalStorageError> instead of panicking. This makes invalid input and overflow explicit, safe, and predictable.
Result<DataValue, DigitalStorageError> ❌ DigitalStorageError pub enum DigitalStorageError { /// Returned when the computed value exceeds the maximum /// representable range of the current backend. BeyondMax,
/// Returned when the input string cannot be parsed
/// as a valid numeric storage value.
ParseError,
} Error conditions 🔺 DigitalStorageError::BeyondMax
Returned when the parsed value exceeds the maximum representable size:
18_446_744_073_709_551_615 bytes = (16 EiB − 1 byte)
This limitation exists because the internal representation uses u64, guaranteeing:
Deterministic behavior
Zero panics from integer overflow
Stable performance across platforms
Future versions may provide a u128 backend behind a feature flag.
🔤 DigitalStorageError::ParseError
Returned when the input string is not a valid numeric storage value.
Examples of invalid input:
"abc" "1.2.3" "1e10" "--5"
Scientific notation is intentionally rejected to avoid hidden floating-point ambiguity.
Guarantee
By returning a Result instead of panicking, the digital_storage module guarantees:
No undefined behavior
No silent truncation
No rounding beyond 1-bit quantization
Users are always forced to handle precision limits explicitly.
use unitx::prelude::digital_storage::*;
fn main(){
//1234 in bytes + 123bit/8 in bytes + 123%8 in bit , any unit less than bit is ignored
let dt=DataValue::new("1234.123456711111", DataBinary::BinaryByte);
match dt {
Ok(dv)=>println!("{dv:?}"),
Err(ds)=>eprint!("{ds:?}"),
}
//Binary
let one_gib_one_bi=DataValue::new("1.00000000007", DataBinary::GiB);
match one_gib_one_bi {
Ok(dv)=>println!("{dv:?}"),
Err(ds)=>eprint!("{ds:?}"),
}
//decimal
let one_tb_one_b=DataValue::new("1.00000000007", DataDecimal::GB).unwrap();
assert_eq!(one_tb_one_b.bytes,1000000000);
assert_eq!(one_tb_one_b.bits,7);
//Adding one
let one_tb_one_byte=DataValue::new("1.00000000008", DataDecimal::GB).unwrap();
assert_eq!(one_tb_one_byte.bytes,1000000001);
assert_eq!(one_tb_one_byte.bits,0);
}
NotesNotes
Parsing is string-based to preserve precision.
Internally, values are stored as (bytes, bits).
Any fractional value smaller than 1 bit is discarded.
Binary (GiB, MiB, …) and decimal (GB, MB, …) units are handled strictly according to spec.
unitx::unit_value::temperatureSupports: Celsius, Fahrenheit, Kelvin, Rankine.
Examples:
use unitx::prelude::*;
let tc = TemperatureCelsius::new(100.0);
let tf = tc.to_fahrenheit();
let tk = tc.to_kelvin();
let delta = tc - TemperatureCelsius::new(50.0);
println!("Temperature difference: {}", delta);
let c_sum = TemperatureCelsius::from(1) + TemperatureCelsius::from(1);
assert_eq!(c_sum.get_temperature_degree(), 2.0);
let f_product = TemperatureFahrenheit::from(12) * TemperatureFahrenheit::from(12);
assert_eq!(f_product.get_temperature_degree(), 144.0);
unitx::unit_value::electricalSupports: Ampere, Volt, Watt, Farad, Henry, Coulomb, Tesla.
Examples:
use unitx::prelude::electrical::{Ampere, Coulomb, ElecSI, Farad, Volt};
fn main(){
let ma=Ampere::from_millis(120);
println!("{:?}",ma.as_millis());
let micr=Ampere::from_micros(1012);
println!("{:}",micr.as_millis());
let nano=Ampere::from_nanos(1119);
let nano_to_kilo=nano.as_kilos();
println!("{}",nano_to_kilo);
let def=Ampere::new();
println!("{def:?}");
let a_1=Ampere::from_base(1);
let v_1=Volt::from_base(1);
let w_1=v_1 * a_1 ;// Mul overload moves the values [1 Volt] X [ 1 Ampere] = [1 Watt]
assert_eq!(w_1.as_base(),1.0);
let a_1=Ampere::from_base(1);
let v_1=Volt::from_base(1);
let w_1=a_1 * v_1;
assert_eq!(w_1.as_base(),1.0);// [1 Ampere] X [ 1 Volt] = [1 Watt]
let v_1=Volt::from_base(1);
let a_1=Ampere::from_base(1);
if let Ok(r_1)=v_1 / a_1 { // produces Result<Ohm,ElecricalMathError>
println!("{} Volt / {} Ampere = {} Ohm",v_1.as_base(),a_1.as_base(),r_1.as_base());
}
let a_1=Ampere::from_base(0);
match v_1/a_1 {//Devide by Ampere(0) return Err(ElectricalMathError::DevideByZero)
Ok(_ohm)=>{},
Err(e)=>{
println!("{e:?}");
}
}
let v=Volt::from_base(1);
let f=Farad::from_base(1);
let c=v*f;//produces Columb
println!("Coulumb: {:?}",c.as_base());
assert_eq!(c.as_base(),1.0);
let v=c/v;//produces Result<Farad,ElecricalMathError>
}