use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum Gs1LinkType {
ProductInformationPage,
ElectronicLeaflet,
SustainabilityInfo,
RecyclingInfo,
MasterData,
CertificationInfo,
Instructions,
SafetyInfo,
Traceability,
DigitalProductPassport,
Custom(String),
}
impl Gs1LinkType {
pub fn parse(s: &str) -> Self {
match s {
"gs1:pip" | "https://ref.gs1.org/voc/pip" => Self::ProductInformationPage,
"gs1:epil" | "https://ref.gs1.org/voc/epil" => Self::ElectronicLeaflet,
"gs1:sustainabilityInfo" | "https://ref.gs1.org/voc/sustainabilityInfo" => {
Self::SustainabilityInfo
}
"gs1:recyclingInfo" | "https://ref.gs1.org/voc/recyclingInfo" => Self::RecyclingInfo,
"gs1:masterData" | "https://ref.gs1.org/voc/masterData" => Self::MasterData,
"gs1:certificationInfo" | "https://ref.gs1.org/voc/certificationInfo" => {
Self::CertificationInfo
}
"gs1:instructions" | "https://ref.gs1.org/voc/instructions" => Self::Instructions,
"gs1:safetyInfo" | "https://ref.gs1.org/voc/safetyInfo" => Self::SafetyInfo,
"gs1:traceability" | "https://ref.gs1.org/voc/traceability" => Self::Traceability,
"gs1:dpp" | "https://ref.gs1.org/voc/dpp" => Self::DigitalProductPassport,
other => Self::Custom(other.to_owned()),
}
}
pub fn as_gs1_uri(&self) -> &str {
match self {
Self::ProductInformationPage => "https://ref.gs1.org/voc/pip",
Self::ElectronicLeaflet => "https://ref.gs1.org/voc/epil",
Self::SustainabilityInfo => "https://ref.gs1.org/voc/sustainabilityInfo",
Self::RecyclingInfo => "https://ref.gs1.org/voc/recyclingInfo",
Self::MasterData => "https://ref.gs1.org/voc/masterData",
Self::CertificationInfo => "https://ref.gs1.org/voc/certificationInfo",
Self::Instructions => "https://ref.gs1.org/voc/instructions",
Self::SafetyInfo => "https://ref.gs1.org/voc/safetyInfo",
Self::Traceability => "https://ref.gs1.org/voc/traceability",
Self::DigitalProductPassport => "https://ref.gs1.org/voc/dpp",
Self::Custom(uri) => uri.as_str(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn every_known_link_type_round_trips_via_canonical_uri() {
let all = [
Gs1LinkType::ProductInformationPage,
Gs1LinkType::ElectronicLeaflet,
Gs1LinkType::SustainabilityInfo,
Gs1LinkType::RecyclingInfo,
Gs1LinkType::MasterData,
Gs1LinkType::CertificationInfo,
Gs1LinkType::Instructions,
Gs1LinkType::SafetyInfo,
Gs1LinkType::Traceability,
Gs1LinkType::DigitalProductPassport,
];
for lt in all {
let uri = lt.as_gs1_uri();
assert_eq!(Gs1LinkType::parse(uri), lt, "canonical URI must round-trip");
}
}
#[test]
fn shorthand_and_full_uris_parse_equivalently() {
assert_eq!(
Gs1LinkType::parse("gs1:dpp"),
Gs1LinkType::DigitalProductPassport
);
assert_eq!(
Gs1LinkType::parse("gs1:pip"),
Gs1LinkType::ProductInformationPage
);
assert_eq!(
Gs1LinkType::parse("gs1:safetyInfo"),
Gs1LinkType::SafetyInfo
);
}
#[test]
fn unknown_link_type_becomes_custom() {
let custom = Gs1LinkType::parse("https://example.com/voc/warranty");
assert_eq!(
custom,
Gs1LinkType::Custom("https://example.com/voc/warranty".to_owned())
);
assert_eq!(custom.as_gs1_uri(), "https://example.com/voc/warranty");
}
}