in_toto/models/predicate/
mod.rs

1//! in-toto link
2
3pub mod link_v02;
4pub mod slsa_provenance_v01;
5pub mod slsa_provenance_v02;
6use std::convert::TryFrom;
7
8pub use link_v02::LinkV02;
9use serde_json::Value;
10pub use slsa_provenance_v01::SLSAProvenanceV01;
11pub use slsa_provenance_v02::SLSAProvenanceV02;
12
13use serde::de::{Deserializer, Error as DeserializeError};
14use serde::ser::Serializer;
15use serde::{Deserialize, Serialize};
16use strum::IntoEnumIterator;
17use strum_macros::EnumIter;
18
19use crate::{Error, Result};
20
21#[derive(Debug, Hash, PartialEq, Eq, EnumIter, Clone, Copy)]
22pub enum PredicateVer {
23    LinkV0_2,
24    SLSAProvenanceV0_1,
25    SLSAProvenanceV0_2,
26}
27
28impl TryFrom<String> for PredicateVer {
29    type Error = crate::Error;
30
31    fn try_from(target: String) -> Result<Self> {
32        match target.as_str() {
33            "https://in-toto.io/Link/v0.2" => Ok(PredicateVer::LinkV0_2),
34            "https://slsa.dev/provenance/v0.1" => {
35                Ok(PredicateVer::SLSAProvenanceV0_1)
36            }
37            "https://slsa.dev/provenance/v0.2" => {
38                Ok(PredicateVer::SLSAProvenanceV0_2)
39            }
40            _ => Err(Error::StringConvertFailed(target)),
41        }
42    }
43}
44
45impl From<PredicateVer> for String {
46    fn from(value: PredicateVer) -> Self {
47        match value {
48            PredicateVer::LinkV0_2 => {
49                "https://in-toto.io/Link/v0.2".to_string()
50            }
51            PredicateVer::SLSAProvenanceV0_1 => {
52                "https://slsa.dev/provenance/v0.1".to_string()
53            }
54            PredicateVer::SLSAProvenanceV0_2 => {
55                "https://slsa.dev/provenance/v0.2".to_string()
56            }
57        }
58    }
59}
60
61impl Serialize for PredicateVer {
62    fn serialize<S>(&self, ser: S) -> ::std::result::Result<S::Ok, S::Error>
63    where
64        S: Serializer,
65    {
66        let target: String = (*self).into();
67        ser.serialize_str(&target)
68    }
69}
70
71impl<'de> Deserialize<'de> for PredicateVer {
72    fn deserialize<D: Deserializer<'de>>(
73        de: D,
74    ) -> ::std::result::Result<Self, D::Error> {
75        let target: String = Deserialize::deserialize(de)?;
76        PredicateVer::try_from(target)
77            .map_err(|e| DeserializeError::custom(format!("{:?}", e)))
78    }
79}
80
81#[derive(Debug, Serialize, PartialEq, Eq, Clone)]
82#[serde(untagged)]
83pub enum PredicateWrapper {
84    LinkV0_2(LinkV02),
85    SLSAProvenanceV0_1(SLSAProvenanceV01),
86    SLSAProvenanceV0_2(SLSAProvenanceV02),
87}
88
89impl<'de> Deserialize<'de> for PredicateWrapper {
90    fn deserialize<D: Deserializer<'de>>(
91        de: D,
92    ) -> ::std::result::Result<Self, D::Error> {
93        let value = Value::deserialize(de)?;
94        PredicateWrapper::try_from_value(value)
95            .map_err(|e| DeserializeError::custom(format!("{:?}", e)))
96    }
97}
98
99impl PredicateWrapper {
100    /// Convert from enum `PredicateWrapper` to trait `PredicateLayout`
101    pub fn into_trait(self) -> Box<dyn PredicateLayout> {
102        match self {
103            PredicateWrapper::LinkV0_2(link) => Box::new(link),
104            PredicateWrapper::SLSAProvenanceV0_1(proven) => Box::new(proven),
105            PredicateWrapper::SLSAProvenanceV0_2(proven) => Box::new(proven),
106        }
107    }
108
109    /// Deserialize method for `PredicateWrapper` from `serde:Value` by its version
110    fn from_value(value: Value, version: PredicateVer) -> Result<Self> {
111        match version {
112            PredicateVer::LinkV0_2 => serde_json::from_value(value)
113                .map(Self::LinkV0_2)
114                .map_err(|e| e.into()),
115            PredicateVer::SLSAProvenanceV0_1 => serde_json::from_value(value)
116                .map(Self::SLSAProvenanceV0_1)
117                .map_err(|e| e.into()),
118            PredicateVer::SLSAProvenanceV0_2 => serde_json::from_value(value)
119                .map(Self::SLSAProvenanceV0_2)
120                .map_err(|e| e.into()),
121        }
122    }
123
124    /// Auto judge the `PredicateWrapper` version from `serde:Value`
125    pub fn judge_from_value(value: &Value) -> Result<PredicateVer> {
126        println!("{:?}", value);
127        for version in PredicateVer::iter() {
128            let wrapper = PredicateWrapper::from_value(value.clone(), version);
129            if wrapper.is_ok() {
130                return Ok(version);
131            }
132        }
133        Err(Error::Programming("no available value parser".to_string()))
134    }
135
136    /// Auto deserialize for `PredicateWrapper` by any possible version.
137    pub fn try_from_value(value: Value) -> Result<Self> {
138        let version = Self::judge_from_value(&value)?;
139        PredicateWrapper::from_value(value, version)
140    }
141}
142
143pub trait PredicateLayout {
144    /// The version of predicate
145    fn version(&self) -> PredicateVer;
146    /// Convert from trait `PredicateLayout` to enum `PredicateWrapper`
147    fn into_enum(self: Box<Self>) -> PredicateWrapper;
148    /// Standard serialize for PredicateLayout
149    fn to_bytes(&self) -> Result<Vec<u8>>;
150}