consortium-cfg-common 0.5.0

Schema and configuration types for Consortium
Documentation
use super::{AcoreName, McoreName, RcoreName, RvCoreName};
use core::fmt;
use core::str::FromStr;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum VisibleCore {
    Ap,
    Mcore(McoreName),
    Rcore(RcoreName),
    Rvcore(RvCoreName),
}

impl FromStr for VisibleCore {
    type Err = String;

    fn from_str(value: &str) -> Result<Self, Self::Err> {
        if value == "ap" {
            return Ok(Self::Ap);
        }

        value
            .parse()
            .map(Self::Mcore)
            .or_else(|_| value.parse().map(Self::Rcore))
            .or_else(|_| value.parse().map(Self::Rvcore))
            .map_err(|_| format!("unknown visible core {value:?}"))
    }
}

impl fmt::Display for VisibleCore {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::Ap => f.write_str("ap"),
            Self::Mcore(name) => name.fmt(f),
            Self::Rcore(name) => name.fmt(f),
            Self::Rvcore(name) => name.fmt(f),
        }
    }
}

impl serde::Serialize for VisibleCore {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        serializer.serialize_str(&self.to_string())
    }
}

impl<'de> serde::Deserialize<'de> for VisibleCore {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        let value = String::deserialize(deserializer)?;
        value.parse().map_err(serde::de::Error::custom)
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Core {
    Acore(AcoreName),
    Mcore(McoreName),
    Rcore(RcoreName),
    Rvcore(RvCoreName),
}

impl FromStr for Core {
    type Err = String;

    fn from_str(value: &str) -> Result<Self, Self::Err> {
        value
            .parse()
            .map(Self::Acore)
            .or_else(|_| value.parse().map(Self::Mcore))
            .or_else(|_| value.parse().map(Self::Rcore))
            .or_else(|_| value.parse().map(Self::Rvcore))
            .map_err(|_| format!("unknown core {value:?}"))
    }
}

impl fmt::Display for Core {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::Acore(name) => name.fmt(f),
            Self::Mcore(name) => name.fmt(f),
            Self::Rcore(name) => name.fmt(f),
            Self::Rvcore(name) => name.fmt(f),
        }
    }
}

impl serde::Serialize for Core {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        serializer.serialize_str(&self.to_string())
    }
}

impl<'de> serde::Deserialize<'de> for Core {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        let value = String::deserialize(deserializer)?;
        value.parse().map_err(serde::de::Error::custom)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn parses_visible_core_names() {
        assert_eq!("ap".parse::<VisibleCore>(), Ok(VisibleCore::Ap));
        assert_eq!(
            "cm33".parse::<VisibleCore>(),
            Ok(VisibleCore::Mcore(McoreName::Cm33))
        );
        assert_eq!(
            "cr5f".parse::<VisibleCore>(),
            Ok(VisibleCore::Rcore(RcoreName::Cr5f))
        );
        assert_eq!(
            "rv32imac".parse::<VisibleCore>(),
            Ok(VisibleCore::Rvcore("rv32imac".parse().unwrap()))
        );
        assert!("ca55".parse::<VisibleCore>().is_err());
    }

    #[test]
    fn parses_concrete_core_names() {
        assert_eq!("ca55".parse::<Core>(), Ok(Core::Acore(AcoreName::Ca55)));
        assert_eq!("a55".parse::<Core>(), Ok(Core::Acore(AcoreName::Ca55)));
        assert_eq!("cm33".parse::<Core>(), Ok(Core::Mcore(McoreName::Cm33)));
        assert_eq!("cr5f".parse::<Core>(), Ok(Core::Rcore(RcoreName::Cr5f)));
        assert_eq!("r5f".parse::<Core>(), Ok(Core::Rcore(RcoreName::Cr5f)));
        assert_eq!(
            "rv32imac".parse::<Core>(),
            Ok(Core::Rvcore("rv32imac".parse().unwrap()))
        );
        assert!("ap".parse::<Core>().is_err());
    }
}