blob: fa3ba2b683f7c0ff6cbc16a1241c1852f975f588 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/// Below are definitions of newtypes corresponding to measurement units, including several that are
/// passed across node boundaries in Messages.
///
/// Functionality has been added opportunistically so far and is not at all complete. A fully
/// developed measurement unit library would probably require const generics, so the compiler can
/// interpret exponents applied to different unit types.
use std::ops;
/// Defines a new measurement unit, with an underlying scalar type. mul_scalar and div_scalar are
/// defined to eliminate some common needs for shedding the unit type.
macro_rules! define_unit {
( $unit_type:ident, $scalar_type: ident ) => {
#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
pub struct $unit_type(pub $scalar_type);
#[allow(dead_code)]
impl $unit_type {
pub fn mul_scalar(&self, other: $scalar_type) -> Self {
Self(self.0 * other)
}
pub fn div_scalar(&self, other: $scalar_type) -> Self {
Self(self.0 / other)
}
}
};
}
// Unit definitions
define_unit!(Celsius, f64);
define_unit!(Farads, f64);
define_unit!(Hertz, f64);
define_unit!(Seconds, f64);
define_unit!(Volts, f64);
define_unit!(Watts, f64);
define_unit!(Nanoseconds, i64);
// An unsigned integer in the range [0 - x], where x is an upper bound defined by the
// thermal_limiter crate.
define_unit!(ThermalLoad, u32);
// Addition and subtraction is implemented for types for which it is useful. Some, but not all,
// other unit types could reasonably support these operations.
macro_rules! define_arithmetic {
( $unit_type:ident ) => {
impl ops::Add for $unit_type {
type Output = Self;
fn add(self, other: Self) -> Self::Output {
Self(self.0 + other.0)
}
}
impl ops::AddAssign for $unit_type {
fn add_assign(&mut self, other: Self) {
self.0 += other.0;
}
}
impl ops::Sub for $unit_type {
type Output = Self;
fn sub(self, other: Self) -> Self::Output {
Self(self.0 - other.0)
}
}
};
( $unit_type:ident, $($more:ident),+) => {
define_arithmetic!($unit_type);
define_arithmetic!($($more),+);
};
}
define_arithmetic!(Seconds, Nanoseconds, Celsius, Watts);
// Convert Seconds to and from Nanoseconds.
impl Seconds {
pub fn from_nanos(nanos: i64) -> Seconds {
Seconds(nanos as f64 / 1e9)
}
pub fn into_nanos(self) -> i64 {
(self.0 * 1e9) as i64
}
}
// Define multiplication and division involving Seconds and Hertz.
impl ops::Mul<Hertz> for Seconds {
type Output = f64;
fn mul(self, rhs: Hertz) -> Self::Output {
self.0 * rhs.0
}
}
impl ops::Mul<Seconds> for Hertz {
type Output = f64;
fn mul(self, rhs: Seconds) -> Self::Output {
self.0 * rhs.0
}
}
impl ops::Div<Seconds> for f64 {
type Output = Hertz;
fn div(self, rhs: Seconds) -> Self::Output {
Hertz(self / rhs.0)
}
}
impl ops::Div<Hertz> for f64 {
type Output = Seconds;
fn div(self, rhs: Hertz) -> Self::Output {
Seconds(self / rhs.0)
}
}