apple_codesign/
environment_constraints.rs1use {
8 crate::{
9 plist_der::{der_decode_plist, der_encode_plist},
10 AppleCodesignError, Result,
11 },
12 plist::{Dictionary, Value},
13 std::path::Path,
14};
15
16#[derive(Clone, Debug)]
20pub struct EncodedEnvironmentConstraints {
21 pub ccat: u64,
25
26 pub comp: u64,
32
33 pub requirements: Dictionary,
35
36 pub vers: u64,
42}
43
44impl Default for EncodedEnvironmentConstraints {
45 fn default() -> Self {
46 Self {
47 ccat: 0,
48 comp: 1,
49 requirements: Default::default(),
50 vers: 1,
51 }
52 }
53}
54
55impl From<EncodedEnvironmentConstraints> for Value {
56 fn from(value: EncodedEnvironmentConstraints) -> Self {
57 let mut dict = Dictionary::default();
58
59 dict.insert("ccat".into(), value.ccat.into());
60 dict.insert("comp".into(), value.comp.into());
61 dict.insert("reqs".into(), value.requirements.into());
62 dict.insert("vers".into(), value.vers.into());
63
64 dict.into()
65 }
66}
67
68impl TryFrom<Value> for EncodedEnvironmentConstraints {
69 type Error = AppleCodesignError;
70
71 fn try_from(value: Value) -> Result<Self, Self::Error> {
72 let mut res = Self::default();
73
74 match value {
75 Value::Dictionary(dict) => {
76 for (k, v) in dict {
77 match k.as_str() {
78 "ccat" => match v {
79 Value::Integer(v) => {
80 res.ccat = v.as_signed().ok_or_else(|| {
81 AppleCodesignError::EnvironmentConstraint(
82 "failed to convert ccat to i64".into(),
83 )
84 })? as u64;
85 }
86 _ => {
87 return Err(AppleCodesignError::EnvironmentConstraint(
88 "ccat is not an integer".into(),
89 ));
90 }
91 },
92 "comp" => match v {
93 Value::Integer(v) => {
94 res.comp = v.as_signed().ok_or_else(|| {
95 AppleCodesignError::EnvironmentConstraint(
96 "failed to convert comp to i64".into(),
97 )
98 })? as u64;
99 }
100 _ => {
101 return Err(AppleCodesignError::EnvironmentConstraint(
102 "comp is not an integer".into(),
103 ));
104 }
105 },
106 "reqs" => match v {
107 Value::Dictionary(v) => {
108 res.requirements = v;
109 }
110 _ => {
111 return Err(AppleCodesignError::EnvironmentConstraint(
112 "reqs is not a dictionary".into(),
113 ));
114 }
115 },
116 "vers" => match v {
117 Value::Integer(v) => {
118 res.vers = v.as_signed().ok_or_else(|| {
119 AppleCodesignError::EnvironmentConstraint(
120 "failed to convert vers to i64".into(),
121 )
122 })? as u64;
123 }
124 _ => {
125 return Err(AppleCodesignError::EnvironmentConstraint(
126 "vers is not an integer".into(),
127 ));
128 }
129 },
130 _ => {
131 return Err(AppleCodesignError::EnvironmentConstraint(format!(
132 "unknown key in plist: {}",
133 k
134 )));
135 }
136 }
137 }
138
139 Ok(res)
140 }
141 _ => Err(AppleCodesignError::EnvironmentConstraint(
142 "plist value is not a dictionary".to_string(),
143 )),
144 }
145 }
146}
147
148impl EncodedEnvironmentConstraints {
149 pub fn from_der(data: impl AsRef<[u8]>) -> Result<Self> {
151 let value = der_decode_plist(data)?;
152
153 Self::try_from(value)
154 }
155
156 pub fn from_requirements_plist(value: Value) -> Result<Self> {
158 match value {
159 Value::Dictionary(v) => Ok(Self {
160 requirements: v,
161 ..Default::default()
162 }),
163 _ => Err(AppleCodesignError::EnvironmentConstraint(
164 "supplied plist is not a dictionary".into(),
165 )),
166 }
167 }
168
169 pub fn from_requirements_plist_file(path: impl AsRef<Path>) -> Result<Self> {
173 let value = Value::from_file(path.as_ref())?;
174 Self::from_requirements_plist(value)
175 }
176
177 pub fn der_encode(&self) -> Result<Vec<u8>> {
179 let value = Value::from(self.clone());
180
181 der_encode_plist(&value)
182 }
183
184 pub fn requirements_plist(&self) -> Value {
186 Value::Dictionary(self.requirements.clone())
187 }
188}