space-units 0.1.2

Type-safe units of measure for aerospace quantities
Documentation
# space-units

**Type-safe units of measure for aerospace quantities.**

[![CI](https://github.com/stateruntime/space-units/actions/workflows/ci.yml/badge.svg)](https://github.com/stateruntime/space-units/actions/workflows/ci.yml)
[![Crates.io](https://img.shields.io/crates/v/space-units.svg)](https://crates.io/crates/space-units)
[![Documentation](https://docs.rs/space-units/badge.svg)](https://docs.rs/space-units)
[![MSRV](https://img.shields.io/badge/MSRV-1.75-blue.svg)](https://blog.rust-lang.org/2023/12/28/Rust-1.75.0.html)
[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE)

---

## The Problem

In 1999, NASA lost the Mars Climate Orbiter because one team produced **pound-force-seconds** and another expected **newton-seconds**. Cost: $327.6 million.

Most codebases still represent physical quantities as plain `f64`:

```rust
fn compute_orbit(radius: f64, velocity: f64, mass: f64) -> f64 {
    // Is radius in meters or km? Velocity in m/s or km/h?
    // The compiler has no idea. Neither does the next developer.
}
```

## The Solution

```rust
use space_units::prelude::*;

let distance = 384_400.km();           // reads like "384,400 kilometers"
let time     = 3.5.hours();            // reads like "3.5 hours"
let velocity = distance / time;         // Length / Time  Velocity

// Read back in any unit
velocity.in_mps()                       // 30_514.3...
velocity.in_kmps()                      // 30.514...

// Only meaningful arithmetic compiles
let force = 1000.kg() * 9.81.mps2();   // Mass * Acceleration  Force
let accel = force / 500.kg();          // Force / Mass  Acceleration
// let oops = force + 500.kg();        //  COMPILE ERROR: can't add Force + Mass
```

## Features

- **40 quantity types** covering mechanics, electromagnetics, thermodynamics, propulsion, radiation, and orbital mechanics
- **80+ typed arithmetic operations** so only physically valid math compiles
- **Zero dependencies** and sub-1s compile time
- **`no_std` compatible** for flight software
- **Const constructors** for compile-time initialization

### Why not uom?

| | space-units | uom |
|---|---|---|
| Error messages | `"expected Length, found Mass"` | `"PInt vs Z0"` (typenum internals) |
| Syntax | `384_400.km()` | `Length::new::<kilometer>(384400.0)` |
| Compile time | < 1s | ~6s |
| Const constructors | Yes | No (5+ years open) |
| nalgebra | Clean wrappers (planned) | Broken (4+ years open) |
| Dependencies | 0 | typenum, num-traits |

## Quick Start

```rust
use space_units::prelude::*;
use space_units::constants::*;

// Orbital velocity at ISS altitude
let r = 6_771.km();                         // Earth radius + 400 km
let v = (GM_EARTH / r).sqrt();              // sqrt(mu/r)  Velocity
println!("{:.2} km/s", v.in_kmps());        // "7.67 km/s"

// Propulsion
let isp = SpecificImpulse::from_s(311.0);   // Merlin 1D
let ve = isp.effective_exhaust_velocity();   // Isp * g0  Velocity
let mdot = 100.kgps();                      // mass flow rate
let thrust = mdot * ve;                     // MassFlowRate * Velocity  Force

// Electromagnetic
let v = 28.volts();
let i = 5.amperes();
let p = v * i;                              // Voltage * Current  Power

// All arithmetic works both ways
let scaled = 2.0 * distance;               // f64 * Quantity works
let ratio = distance / 100.km();           // Quantity / Quantity  f64
let mut d = distance;
d += 50.km();                               // compound assignment works
```

## Supported Quantities

### Mechanics
[`Length`](https://docs.rs/space-units/latest/space_units/struct.Length.html), [`Time`](https://docs.rs/space-units/latest/space_units/struct.Time.html), [`Mass`](https://docs.rs/space-units/latest/space_units/struct.Mass.html), [`Velocity`](https://docs.rs/space-units/latest/space_units/struct.Velocity.html), [`Acceleration`](https://docs.rs/space-units/latest/space_units/struct.Acceleration.html), [`Force`](https://docs.rs/space-units/latest/space_units/struct.Force.html), [`Impulse`](https://docs.rs/space-units/latest/space_units/struct.Impulse.html), [`Momentum`](https://docs.rs/space-units/latest/space_units/struct.Momentum.html)

### Angular Motion
[`Angle`](https://docs.rs/space-units/latest/space_units/struct.Angle.html) (with trig: sin/cos/tan/normalize), [`AngularVelocity`](https://docs.rs/space-units/latest/space_units/struct.AngularVelocity.html), [`AngularAcceleration`](https://docs.rs/space-units/latest/space_units/struct.AngularAcceleration.html), [`Torque`](https://docs.rs/space-units/latest/space_units/struct.Torque.html), [`AngularMomentum`](https://docs.rs/space-units/latest/space_units/struct.AngularMomentum.html), [`MomentOfInertia`](https://docs.rs/space-units/latest/space_units/struct.MomentOfInertia.html), [`SolidAngle`](https://docs.rs/space-units/latest/space_units/struct.SolidAngle.html)

### Geometry
[`Area`](https://docs.rs/space-units/latest/space_units/struct.Area.html), [`Volume`](https://docs.rs/space-units/latest/space_units/struct.Volume.html), [`Density`](https://docs.rs/space-units/latest/space_units/struct.Density.html)

### Energy & Thermodynamics
[`Energy`](https://docs.rs/space-units/latest/space_units/struct.Energy.html), [`Power`](https://docs.rs/space-units/latest/space_units/struct.Power.html), [`Pressure`](https://docs.rs/space-units/latest/space_units/struct.Pressure.html), [`SpecificEnergy`](https://docs.rs/space-units/latest/space_units/struct.SpecificEnergy.html), [`Temperature`](https://docs.rs/space-units/latest/space_units/struct.Temperature.html) (K/C/F/R), [`HeatFlux`](https://docs.rs/space-units/latest/space_units/struct.HeatFlux.html)

### Electromagnetic
[`Frequency`](https://docs.rs/space-units/latest/space_units/struct.Frequency.html) (with period/wavelength), [`ElectricCurrent`](https://docs.rs/space-units/latest/space_units/struct.ElectricCurrent.html), [`Voltage`](https://docs.rs/space-units/latest/space_units/struct.Voltage.html), [`Resistance`](https://docs.rs/space-units/latest/space_units/struct.Resistance.html), [`ElectricCharge`](https://docs.rs/space-units/latest/space_units/struct.ElectricCharge.html), [`MagneticFluxDensity`](https://docs.rs/space-units/latest/space_units/struct.MagneticFluxDensity.html), [`MagneticFlux`](https://docs.rs/space-units/latest/space_units/struct.MagneticFlux.html), [`Capacitance`](https://docs.rs/space-units/latest/space_units/struct.Capacitance.html), [`Inductance`](https://docs.rs/space-units/latest/space_units/struct.Inductance.html)

### Propulsion
[`SpecificImpulse`](https://docs.rs/space-units/latest/space_units/struct.SpecificImpulse.html), [`MassFlowRate`](https://docs.rs/space-units/latest/space_units/struct.MassFlowRate.html)

### Orbital Mechanics
[`GravitationalParameter`](https://docs.rs/space-units/latest/space_units/struct.GravitationalParameter.html), [`SpecificAngularMomentum`](https://docs.rs/space-units/latest/space_units/struct.SpecificAngularMomentum.html)

### Radiation
[`AbsorbedDose`](https://docs.rs/space-units/latest/space_units/struct.AbsorbedDose.html) (Gy/rad), [`DoseEquivalent`](https://docs.rs/space-units/latest/space_units/struct.DoseEquivalent.html) (Sv/rem)

### Communications
[`DataRate`](https://docs.rs/space-units/latest/space_units/struct.DataRate.html)

All types are accessible via `use space_units::prelude::*`. The [`NumericExt`](https://docs.rs/space-units/latest/space_units/trait.NumericExt.html) trait provides literal extensions on numeric types.

## Typed Constants

```rust
use space_units::constants::*;

C            // Speed of light: Velocity
AU           // Astronomical unit: Length
G0           // Standard gravity: Acceleration
GM_EARTH     // Earth gravitational parameter: GravitationalParameter
GM_SUN       // Sun gravitational parameter
R_EARTH      // Earth mean radius: Length
M_EARTH      // Earth mass: Mass
// ... 34 total (all planets, Moon, fundamental constants)
```

## Formatting

```rust
use space_units::prelude::*;

let d = 384_400.km();

// Default Display shows canonical unit
println!("{d}");                                        // "384400000 m"
println!("{d:.2}");                                     // "384400000.00 m"

// display_as() for specific units
println!("{}", d.display_as(LengthUnit::Kilometer));    // "384400 km"
println!("{:.1}", d.display_as(LengthUnit::AstronomicalUnit)); // "0.0 AU"
```

## Installation

```bash
cargo add space-units
```

Or add to your `Cargo.toml`:

```toml
[dependencies]
space-units = "0.1"
```

## Examples

Runnable examples in the [`examples/`](examples/) directory:

```bash
cargo run --example basics              # Construction, conversion, arithmetic
cargo run --example orbital_mechanics   # ISS orbit, Hohmann transfer, escape velocity
cargo run --example propulsion          # Isp, thrust, Tsiolkovsky equation
cargo run --example electromagnetic     # Ohm's law, power, frequency/wavelength
cargo run --example formatting          # Display, display_as(), precision
```

## Documentation

- [API Reference](https://docs.rs/space-units) — full docs on docs.rs
- [Design](docs/DESIGN.md) — architecture and design decisions
- [Roadmap](docs/ROADMAP.md) — planned features and milestones
- [Developer Experience](docs/DEVELOPER_EXPERIENCE.md) — DX philosophy
- [Contributing](CONTRIBUTING.md) — how to contribute

## Security

Please report vulnerabilities privately. See [SECURITY.md](SECURITY.md) for details.

## License

Licensed under the Apache License, Version 2.0. See [LICENSE](LICENSE).