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
use anyhow::{bail, Result};
use bc_components::{Compressed, DigestProvider};
use dcbor::prelude::*;

use crate::{Envelope, EnvelopeError, base::envelope::EnvelopeCase};

/// Support for compressing and uncompressing envelopes.
impl Envelope {
    /// Returns the compressed variant of this envelope.
    ///
    /// Returns the same envelope if it is already compressed.
    pub fn compress(&self) -> Result<Self> {
        match self.case() {
            EnvelopeCase::Compressed(_) => Ok(self.clone()),
            #[cfg(feature = "encrypt")]
            EnvelopeCase::Encrypted(_) => bail!(EnvelopeError::AlreadyEncrypted),
            EnvelopeCase::Elided(_) => bail!(EnvelopeError::AlreadyElided),
            _ => {
                let compressed = Compressed::from_uncompressed_data(self.tagged_cbor().to_cbor_data(), Some(self.digest().into_owned()));
                Ok(compressed.try_into()?)
            },
        }
    }

    /// Returns the uncompressed variant of this envelope.
    ///
    /// Returns the same envelope if it is already uncompressed.
    pub fn uncompress(&self) -> Result<Self> {
        if let EnvelopeCase::Compressed(compressed) = self.case() {
            if let Some(digest) = compressed.digest_ref_opt() {
                if digest != self.digest().as_ref() {
                    bail!(EnvelopeError::InvalidDigest);
                }
                let a = compressed.uncompress()?;
                let envelope = Envelope::from_tagged_cbor_data(&a)?;
                if envelope.digest().as_ref() != digest {
                    bail!(EnvelopeError::InvalidDigest);
                }
                Ok(envelope)
            } else {
                bail!(EnvelopeError::MissingDigest)
            }
        } else {
            bail!(EnvelopeError::NotCompressed)
        }
    }

    /// Returns this envelope with its subject compressed.
    ///
    /// Returns the same envelope if its subject is already compressed.
    pub fn compress_subject(&self) -> Result<Self> {
        if self.subject().is_compressed() {
            Ok(self.clone())
        } else {
            let subject = self.subject().compress()?;
            Ok(self.replace_subject(subject))
        }
    }

    /// Returns this envelope with its subject uncompressed.
    ///
    /// Returns the same envelope if its subject is already uncompressed.
    pub fn uncompress_subject(&self) -> Result<Self> {
        if self.subject().is_compressed() {
            let subject = self.subject().uncompress()?;
            Ok(self.replace_subject(subject))
        } else {
            Ok(self.clone())
        }
    }
}