use serde::{Deserialize, Serialize};
use validatrix::{Accumulator, Validate};
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(deny_unknown_fields)]
pub struct Axis {
pub name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub r#type: Option<AxisType>,
#[serde(skip_serializing_if = "Option::is_none")]
pub unit: Option<AxisUnit>,
}
impl Validate for Axis {
fn validate_inner(&self, accum: &mut Accumulator) {
let (Some(t), Some(u)) = (&self.r#type, &self.unit) else {
return;
};
match u {
AxisUnit::Space(_) => {
if t != &AxisType::Space {
accum.add_failure("got space unit for non-space axis");
}
}
AxisUnit::Time(_) => {
if t != &AxisType::Time {
accum.add_failure("got time unit for non-time axis");
}
}
AxisUnit::Custom(_) => (),
}
}
}
#[non_exhaustive]
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
#[serde(rename_all = "lowercase")]
pub enum AxisType {
Space,
Time,
Channel,
#[serde(untagged)]
Custom(String),
}
#[non_exhaustive]
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(untagged)]
pub enum AxisUnit {
Space(AxisUnitSpace),
Time(AxisUnitTime),
Custom(String),
}
impl From<AxisUnitSpace> for AxisUnit {
fn from(value: AxisUnitSpace) -> Self {
Self::Space(value)
}
}
impl From<AxisUnitTime> for AxisUnit {
fn from(value: AxisUnitTime) -> Self {
Self::Time(value)
}
}
#[non_exhaustive]
#[allow(missing_docs)]
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
#[serde(rename_all = "lowercase")]
pub enum AxisUnitSpace {
Angstrom,
Attometer,
Centimeter,
Decimeter,
Exameter,
Femtometer,
Foot,
Gigameter,
Hectometer,
Inch,
Kilometer,
Megameter,
Meter,
Micrometer,
Mile,
Millimeter,
Nanometer,
Parsec,
Petameter,
Picometer,
Terameter,
Yard,
Yoctometer,
Yottameter,
Zeptometer,
Zettameter,
}
#[non_exhaustive]
#[allow(missing_docs)]
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
#[serde(rename_all = "lowercase")]
pub enum AxisUnitTime {
Attosecond,
Centisecond,
Day,
Decisecond,
Exasecond,
Femtosecond,
Gigasecond,
Hectosecond,
Hour,
Kilosecond,
Megasecond,
Microsecond,
Millisecond,
Minute,
Nanosecond,
Petasecond,
Picosecond,
Second,
Terasecond,
Yoctosecond,
Yottasecond,
Zeptosecond,
Zettasecond,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn custom_axis() {
let space: AxisType = serde_json::from_str("\"space\"").unwrap();
assert_eq!(space, AxisType::Space);
let potato: AxisType = serde_json::from_str("\"potato\"").unwrap();
assert_eq!(potato, AxisType::Custom("potato".to_string()));
let custom: AxisType = serde_json::from_str("\"custom\"").unwrap();
assert_eq!(custom, AxisType::Custom("custom".to_string()));
}
}