ssi_status/impl/bitstring_status_list/syntax/
mod.rs

1use std::io::{Read, Write};
2
3use flate2::{read::GzDecoder, write::GzEncoder, Compression};
4use multibase::Base;
5use serde::{Deserialize, Serialize};
6
7mod status_list;
8pub use status_list::*;
9
10mod entry_set;
11pub use entry_set::*;
12
13/// Multibase-encoded base64url (with no padding) representation of the
14/// GZIP-compressed bitstring values for the associated range of a bitstring
15/// status list verifiable credential.
16#[derive(Debug, Serialize, Deserialize)]
17#[serde(transparent)]
18pub struct EncodedList(String);
19
20impl EncodedList {
21    /// Minimum bitstring size (16KB).
22    pub const MINIMUM_SIZE: usize = 16 * 1024;
23
24    /// Default maximum bitstring size allowed by the `decode` function.
25    ///
26    /// 16MB.
27    pub const DEFAULT_LIMIT: u64 = 16 * 1024 * 1024;
28
29    pub fn new(value: String) -> Self {
30        Self(value)
31    }
32
33    pub fn encode(bytes: &[u8]) -> Self {
34        let mut encoder = GzEncoder::new(Vec::new(), Compression::default());
35        encoder.write_all(bytes).unwrap();
36
37        // Add padding to satisfy the minimum bitstring size constraint.
38        const PADDING_BUFFER_LEN: usize = 1024;
39        let padding = [0; PADDING_BUFFER_LEN];
40        let mut it = (bytes.len()..Self::MINIMUM_SIZE)
41            .step_by(PADDING_BUFFER_LEN)
42            .peekable();
43        while let Some(start) = it.next() {
44            let end = it.peek().copied().unwrap_or(Self::MINIMUM_SIZE);
45            let len = end - start;
46            encoder.write_all(&padding[..len]).unwrap();
47        }
48
49        let compressed = encoder.finish().unwrap();
50        Self(multibase::encode(Base::Base64Url, compressed))
51    }
52
53    pub fn decode(&self, limit: Option<u64>) -> Result<Vec<u8>, DecodeError> {
54        let limit = limit.unwrap_or(Self::DEFAULT_LIMIT);
55        let (_base, compressed) = multibase::decode(&self.0)?;
56        let mut decoder = GzDecoder::new(compressed.as_slice()).take(limit);
57        let mut bytes = Vec::new();
58        decoder.read_to_end(&mut bytes).map_err(DecodeError::Gzip)?;
59        Ok(bytes)
60    }
61}