1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
use bc_components::DigestProvider;
use crate::{Envelope, EnvelopeError, EnvelopeEncodable};
use super::envelope::EnvelopeCase;
/// Support for adding assertions.
impl Envelope {
/// Returns the result of adding the given assertion to the envelope.
pub fn add_assertion(&self, predicate: impl EnvelopeEncodable, object: impl EnvelopeEncodable) -> Self {
let assertion = Self::new_assertion(predicate, object);
self.add_optional_assertion_envelope(Some(assertion)).unwrap()
}
/// Returns the result of adding the given assertion to the envelope.
///
/// The assertion envelope must be a valid assertion envelope, or an
/// obscured variant (elided, encrypted, compressed) of one.
pub fn add_assertion_envelope(&self, assertion_envelope: Self) -> Result<Self, EnvelopeError> {
self.add_optional_assertion_envelope(Some(assertion_envelope))
}
/// Returns the result of adding the given array of assertions to the envelope.
///
/// Each assertion envelope must be a valid assertion envelope, or an
/// obscured variant (elided, encrypted, compressed) of one.
pub fn add_assertion_envelopes(&self, assertions: &[Self]) -> Result<Self, EnvelopeError> {
let mut e = self.clone();
for assertion in assertions {
e = e.add_assertion_envelope(assertion.clone())?;
}
Ok(e.clone())
}
/// If the optional assertion is present, returns the result of adding it to
/// the envelope. Otherwise, returns the envelope unchanged.
///
/// The assertion envelope must be a valid assertion envelope, or an
/// obscured variant (elided, encrypted, compressed) of one.
pub fn add_optional_assertion_envelope(&self, assertion: Option<Self>) -> Result<Self, EnvelopeError> {
match assertion {
Some(assertion) => {
if !assertion.is_subject_assertion() && !assertion.is_subject_obscured() {
return Err(EnvelopeError::InvalidFormat)
}
match self.case() {
EnvelopeCase::Node { subject, assertions, .. } => {
if !assertions.iter().any(|a| a.digest() == assertion.digest()) {
let mut assertions = assertions.clone();
assertions.push(assertion);
Ok(Self::new_with_unchecked_assertions(subject.clone(), assertions))
} else {
Ok(self.clone())
}
},
_ => Ok(Self::new_with_unchecked_assertions(self.subject(), vec![assertion])),
}
},
None => Ok(self.clone()),
}
}
/// If the optional object is present, returns the result of adding the
/// assertion to the envelope. Otherwise, returns the envelope unchanged.
pub fn add_optional_assertion(&self, predicate: impl EnvelopeEncodable, object: Option<impl EnvelopeEncodable>) -> Self {
if let Some(object) = object {
self.add_assertion_envelope(Self::new_assertion(predicate, object)).unwrap()
} else {
self.clone()
}
}
/// Returns a new `Envelope` with the given array of assertions added.
///
/// - Parameter assertions: The assertions to add.
pub fn add_assertions(&self, envelopes: &[Self]) -> Self {
let mut e = self.clone();
for envelope in envelopes {
e = e.add_assertion_envelope(envelope.clone()).unwrap();
}
e.clone()
}
}
/// Support for adding conditional assertions.
impl Envelope {
/// If the condition is true, returns the result of adding the given assertion to the envelope.
/// Otherwise, returns the envelope unchanged.
pub fn add_assertion_if(&self, condition: bool, predicate: impl EnvelopeEncodable, object: impl EnvelopeEncodable) -> Self {
if condition {
self.add_assertion(predicate, object)
} else {
self.clone()
}
}
/// If the condition is true, returns the result of adding the given assertion to the envelope.
/// Otherwise, returns the envelope unchanged.
pub fn add_assertion_envelope_if(&self, condition: bool, assertion_envelope: Self) -> Result<Self, EnvelopeError> {
if condition {
self.add_assertion_envelope(assertion_envelope)
} else {
Ok(self.clone())
}
}
}
#[cfg(feature = "salt")]
/// Support for adding assertions with salt.
impl Envelope {
/// Returns the result of adding the given assertion to the envelope, optionally salting it.
pub fn add_assertion_salted<P, O>(&self, predicate: P, object: O, salted: bool) -> Self
where
P: EnvelopeEncodable,
O: EnvelopeEncodable,
{
let assertion = Self::new_assertion(predicate, object);
self.add_optional_assertion_envelope_salted(Some(assertion), salted).unwrap()
}
/// Returns the result of adding the given assertion to the envelope, optionally salting it.
///
/// The assertion envelope must be a valid assertion envelope, or an
/// obscured variant (elided, encrypted, compressed) of one.
pub fn add_assertion_envelope_salted(&self, assertion_envelope: Self, salted: bool) -> Result<Self, EnvelopeError> {
self.add_optional_assertion_envelope_salted(Some(assertion_envelope), salted)
}
/// If the optional assertion is present, returns the result of adding it to
/// the envelope, optionally salting it. Otherwise, returns the envelope unchanged.
///
/// The assertion envelope must be a valid assertion envelope, or an
/// obscured variant (elided, encrypted, compressed) of one.
pub fn add_optional_assertion_envelope_salted(&self, assertion: Option<Self>, salted: bool) -> Result<Self, EnvelopeError> {
match assertion {
Some(assertion) => {
if !assertion.is_subject_assertion() && !assertion.is_subject_obscured() {
return Err(EnvelopeError::InvalidFormat)
}
let envelope2 = if salted {
assertion.add_salt()
} else {
assertion
};
match self.case() {
EnvelopeCase::Node { subject, assertions, .. } => {
if !assertions.iter().any(|a| a.digest() == envelope2.digest()) {
let mut assertions = assertions.clone();
assertions.push(envelope2);
Ok(Self::new_with_unchecked_assertions(subject.clone(), assertions))
} else {
Ok(self.clone())
}
},
_ => Ok(Self::new_with_unchecked_assertions(self.subject(), vec![envelope2])),
}
},
None => Ok(self.clone()),
}
}
pub fn add_assertions_salted(&self, assertions: &[Self], salted: bool) -> Self {
let mut e = self.clone();
for assertion in assertions {
e = e.add_assertion_envelope_salted(assertion.clone(), salted).unwrap();
}
e.clone()
}
}
/// Support for removing or replacing assertions.
impl Envelope {
/// Returns a new envelope with the given assertion removed. If the assertion does
/// not exist, returns the same envelope.
pub fn remove_assertion(&self, target: Self) -> Self {
let assertions = self.clone().assertions();
let target = target.digest();
if let Some(index) = assertions.iter().position(|a| a.digest() == target) {
let mut assertions = assertions.clone();
assertions.remove(index);
if assertions.is_empty() {
self.subject()
} else {
Self::new_with_unchecked_assertions(self.subject(), assertions)
}
} else {
self.clone()
}
}
/// Returns a new envelope with the given assertion replaced by the provided one. If
/// the targeted assertion does not exist, returns the same envelope.
pub fn replace_assertion(&self, assertion: Self, new_assertion: Self) -> Result<Self, EnvelopeError> {
self.remove_assertion(assertion).add_assertion_envelope(new_assertion)
}
/// Returns a new envelope with its subject replaced by the provided one.
pub fn replace_subject(&self, subject: Self) -> Self {
self.assertions().iter().fold(subject, |e, a| e.add_assertion_envelope(a.clone()).unwrap())
}
}