use std::marker::PhantomData;
use crate::measurement::{MeasurementType, WrappedMeasurementType};
use crate::units::PrefixedUnit;
use super::error::MetricTypeError;
use super::registry::MetricRegistry;
#[derive(Debug, Clone)]
pub struct Metric {
pub name: String,
pub description: String,
pub value_type: WrappedMeasurementType,
pub unit: PrefixedUnit,
}
pub trait MetricId {
fn untyped_id(&self) -> RawMetricId;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(C)]
pub struct RawMetricId(pub(crate) usize);
impl RawMetricId {
pub fn as_u64(&self) -> u64 {
self.0 as u64
}
pub fn from_u64(id: u64) -> RawMetricId {
RawMetricId(id as _)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(C)]
pub struct TypedMetricId<T: MeasurementType>(pub(crate) RawMetricId, pub(crate) PhantomData<T>);
impl MetricId for RawMetricId {
fn untyped_id(&self) -> RawMetricId {
*self
}
}
impl<T: MeasurementType> MetricId for TypedMetricId<T> {
fn untyped_id(&self) -> RawMetricId {
self.0
}
}
impl<T: MeasurementType> TypedMetricId<T> {
pub fn try_from(untyped: RawMetricId, registry: &MetricRegistry) -> Result<Self, MetricTypeError> {
let expected_type = T::wrapped_type();
let actual_type = registry
.by_id(&untyped)
.expect("the untyped metric should exist in the registry")
.value_type
.clone();
if expected_type != actual_type {
Err(MetricTypeError {
expected: expected_type,
actual: actual_type,
})
} else {
Ok(TypedMetricId(untyped, PhantomData))
}
}
}