Skip to main content

compression/
aea.rs

1use crate::{
2    aa_byte_stream::{ArchiveCompressionAlgorithm, ArchiveFlags, ByteStream, ByteStreamUpstream},
3    aa_entry_blob::NamedBlobEntry,
4    ffi, util, CompressionError, Result,
5};
6use std::ffi::{c_void, CStr};
7use std::ptr::{null, null_mut, NonNull};
8
9/// Wraps AEA profile identifiers.
10#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
11#[repr(u32)]
12pub enum AeaProfile {
13    /// Wraps the `HkdfSha256HmacNoneEcdsaP256` variant of `AeaProfile`.
14    HkdfSha256HmacNoneEcdsaP256 = 0,
15    /// Wraps the `HkdfSha256AesctrHmacSymmetricNone` variant of `AeaProfile`.
16    HkdfSha256AesctrHmacSymmetricNone = 1,
17    /// Wraps the `HkdfSha256AesctrHmacSymmetricEcdsaP256` variant of `AeaProfile`.
18    HkdfSha256AesctrHmacSymmetricEcdsaP256 = 2,
19    /// Wraps the `HkdfSha256AesctrHmacEcdheP256None` variant of `AeaProfile`.
20    HkdfSha256AesctrHmacEcdheP256None = 3,
21    /// Wraps the `HkdfSha256AesctrHmacEcdheP256EcdsaP256` variant of `AeaProfile`.
22    HkdfSha256AesctrHmacEcdheP256EcdsaP256 = 4,
23    /// Wraps the `HkdfSha256AesctrHmacScryptNone` variant of `AeaProfile`.
24    HkdfSha256AesctrHmacScryptNone = 5,
25}
26
27impl AeaProfile {
28    const fn from_raw(raw: u32) -> Option<Self> {
29        match raw {
30            x if x == Self::HkdfSha256HmacNoneEcdsaP256 as u32 => {
31                Some(Self::HkdfSha256HmacNoneEcdsaP256)
32            }
33            x if x == Self::HkdfSha256AesctrHmacSymmetricNone as u32 => {
34                Some(Self::HkdfSha256AesctrHmacSymmetricNone)
35            }
36            x if x == Self::HkdfSha256AesctrHmacSymmetricEcdsaP256 as u32 => {
37                Some(Self::HkdfSha256AesctrHmacSymmetricEcdsaP256)
38            }
39            x if x == Self::HkdfSha256AesctrHmacEcdheP256None as u32 => {
40                Some(Self::HkdfSha256AesctrHmacEcdheP256None)
41            }
42            x if x == Self::HkdfSha256AesctrHmacEcdheP256EcdsaP256 as u32 => {
43                Some(Self::HkdfSha256AesctrHmacEcdheP256EcdsaP256)
44            }
45            x if x == Self::HkdfSha256AesctrHmacScryptNone as u32 => {
46                Some(Self::HkdfSha256AesctrHmacScryptNone)
47            }
48            _ => None,
49        }
50    }
51
52    /// Wraps raw AEA profile identifiers.
53    pub const fn raw(self) -> u32 {
54        self as u32
55    }
56
57    /// Wraps the ciphersuite encoded by an AEA profile.
58    pub const fn ciphersuite(self) -> AeaCiphersuite {
59        match self {
60            Self::HkdfSha256HmacNoneEcdsaP256 => AeaCiphersuite::HkdfSha256Hmac,
61            Self::HkdfSha256AesctrHmacSymmetricNone
62            | Self::HkdfSha256AesctrHmacSymmetricEcdsaP256
63            | Self::HkdfSha256AesctrHmacEcdheP256None
64            | Self::HkdfSha256AesctrHmacEcdheP256EcdsaP256
65            | Self::HkdfSha256AesctrHmacScryptNone => AeaCiphersuite::HkdfSha256AesctrHmac,
66        }
67    }
68
69    /// Wraps the signature mode encoded by an AEA profile.
70    pub const fn signature_mode(self) -> AeaSignatureMode {
71        match self {
72            Self::HkdfSha256HmacNoneEcdsaP256
73            | Self::HkdfSha256AesctrHmacSymmetricEcdsaP256
74            | Self::HkdfSha256AesctrHmacEcdheP256EcdsaP256 => AeaSignatureMode::EcdsaP256,
75            Self::HkdfSha256AesctrHmacSymmetricNone
76            | Self::HkdfSha256AesctrHmacEcdheP256None
77            | Self::HkdfSha256AesctrHmacScryptNone => AeaSignatureMode::None,
78        }
79    }
80
81    /// Wraps the encryption mode encoded by an AEA profile.
82    pub const fn encryption_mode(self) -> AeaEncryptionMode {
83        match self {
84            Self::HkdfSha256HmacNoneEcdsaP256 => AeaEncryptionMode::None,
85            Self::HkdfSha256AesctrHmacSymmetricNone
86            | Self::HkdfSha256AesctrHmacSymmetricEcdsaP256 => AeaEncryptionMode::Symmetric,
87            Self::HkdfSha256AesctrHmacEcdheP256None
88            | Self::HkdfSha256AesctrHmacEcdheP256EcdsaP256 => AeaEncryptionMode::EcdheP256,
89            Self::HkdfSha256AesctrHmacScryptNone => AeaEncryptionMode::Scrypt,
90        }
91    }
92}
93
94/// Wraps AEA context field identifiers.
95#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
96#[repr(u32)]
97pub enum AeaContextField {
98    /// Wraps the `Profile` variant of `AeaContextField`.
99    Profile = 0,
100    /// Wraps the `PaddingSize` variant of `AeaContextField`.
101    PaddingSize = 1,
102    /// Wraps the `ChecksumMode` variant of `AeaContextField`.
103    ChecksumMode = 2,
104    /// Wraps the `CompressionAlgorithm` variant of `AeaContextField`.
105    CompressionAlgorithm = 3,
106    /// Wraps the `CompressionBlockSize` variant of `AeaContextField`.
107    CompressionBlockSize = 4,
108    /// Wraps the `AuthData` variant of `AeaContextField`.
109    AuthData = 5,
110    /// Wraps the `MainKey` variant of `AeaContextField`.
111    MainKey = 6,
112    /// Wraps the `SigningPublicKey` variant of `AeaContextField`.
113    SigningPublicKey = 7,
114    /// Wraps the `SigningPrivateKey` variant of `AeaContextField`.
115    SigningPrivateKey = 8,
116    /// Wraps the `SymmetricKey` variant of `AeaContextField`.
117    SymmetricKey = 9,
118    /// Wraps the `RecipientPublicKey` variant of `AeaContextField`.
119    RecipientPublicKey = 10,
120    /// Wraps the `RecipientPrivateKey` variant of `AeaContextField`.
121    RecipientPrivateKey = 11,
122    /// Wraps the `SignatureEncryptionKey` variant of `AeaContextField`.
123    SignatureEncryptionKey = 12,
124    /// Wraps the `RawSize` variant of `AeaContextField`.
125    RawSize = 13,
126    /// Wraps the `ContainerSize` variant of `AeaContextField`.
127    ContainerSize = 14,
128    /// Wraps the `BlocksPerCluster` variant of `AeaContextField`.
129    BlocksPerCluster = 17,
130    /// Wraps the `ArchiveIdentifier` variant of `AeaContextField`.
131    ArchiveIdentifier = 18,
132    /// Wraps the `Password` variant of `AeaContextField`.
133    Password = 19,
134}
135
136impl AeaContextField {
137    /// Wraps raw AEA context field identifiers.
138    pub const fn raw(self) -> u32 {
139        self as u32
140    }
141}
142
143/// Wraps AEA context field representation identifiers.
144#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
145#[repr(u32)]
146pub enum AeaContextFieldRepresentation {
147    /// Wraps the `Raw` variant of `AeaContextFieldRepresentation`.
148    Raw = 0,
149    /// Wraps the `X963` variant of `AeaContextFieldRepresentation`.
150    X963 = 1,
151    /// Wraps the `Generate` variant of `AeaContextFieldRepresentation`.
152    Generate = 2,
153}
154
155impl AeaContextFieldRepresentation {
156    const fn raw(self) -> u32 {
157        self as u32
158    }
159}
160
161/// Wraps AEA ciphersuite identifiers.
162#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
163#[repr(u32)]
164pub enum AeaCiphersuite {
165    /// Wraps the `HkdfSha256Hmac` variant of `AeaCiphersuite`.
166    HkdfSha256Hmac = 0,
167    /// Wraps the `HkdfSha256AesctrHmac` variant of `AeaCiphersuite`.
168    HkdfSha256AesctrHmac = 1,
169}
170
171/// Wraps AEA signature mode identifiers.
172#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
173#[repr(u32)]
174pub enum AeaSignatureMode {
175    /// Wraps the `None` variant of `AeaSignatureMode`.
176    None = 0,
177    /// Wraps the `EcdsaP256` variant of `AeaSignatureMode`.
178    EcdsaP256 = 1,
179}
180
181/// Wraps AEA encryption mode identifiers.
182#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
183#[repr(u32)]
184pub enum AeaEncryptionMode {
185    /// Wraps the `None` variant of `AeaEncryptionMode`.
186    None = 0,
187    /// Wraps the `Symmetric` variant of `AeaEncryptionMode`.
188    Symmetric = 1,
189    /// Wraps the `EcdheP256` variant of `AeaEncryptionMode`.
190    EcdheP256 = 2,
191    /// Wraps the `Scrypt` variant of `AeaEncryptionMode`.
192    Scrypt = 3,
193}
194
195/// Wraps AEA checksum mode identifiers.
196#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
197#[repr(u32)]
198pub enum AeaChecksumMode {
199    /// Wraps the `None` variant of `AeaChecksumMode`.
200    None = 0,
201    /// Wraps the `MurmurHash64` variant of `AeaChecksumMode`.
202    MurmurHash64 = 1,
203    /// Wraps the `Sha256` variant of `AeaChecksumMode`.
204    Sha256 = 2,
205}
206
207impl AeaChecksumMode {
208    const fn from_raw(raw: u32) -> Option<Self> {
209        match raw {
210            x if x == Self::None as u32 => Some(Self::None),
211            x if x == Self::MurmurHash64 as u32 => Some(Self::MurmurHash64),
212            x if x == Self::Sha256 as u32 => Some(Self::Sha256),
213            _ => None,
214        }
215    }
216
217    const fn raw(self) -> u32 {
218        self as u32
219    }
220}
221
222/// Wraps AEA padding constants.
223#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash)]
224pub struct AeaPadding;
225
226impl AeaPadding {
227    /// Wraps the `NONE` AEA padding constant.
228    pub const NONE: u64 = 0;
229    /// Wraps the `ADAPTIVE` AEA padding constant.
230    pub const ADAPTIVE: u64 = 1;
231    /// Wraps the `MIN_SIZE` AEA padding constant.
232    pub const MIN_SIZE: u64 = 16;
233}
234
235/// Wraps an `AEAContext` handle.
236#[derive(Debug)]
237pub struct AeaContext {
238    handle: NonNull<c_void>,
239}
240
241impl AeaContext {
242    fn from_handle(handle: *mut c_void, operation: &'static str) -> Result<Self> {
243        Ok(Self {
244            handle: util::nonnull_handle(handle, operation)?,
245        })
246    }
247
248    fn open_byte_stream(
249        handle: *mut c_void,
250        operation: &'static str,
251        upstream: ByteStream,
252    ) -> Result<ByteStream> {
253        ByteStream::from_handle_with_upstream(
254            handle,
255            operation,
256            Some(ByteStreamUpstream::Stream(Box::new(upstream))),
257        )
258    }
259
260    /// Wraps `AEAContextCreateWithProfile`.
261    pub fn with_profile(profile: AeaProfile) -> Result<Self> {
262        let handle =
263            unsafe { ffi::aea::compression_rs_aea_context_create_with_profile(profile.raw()) };
264        Self::from_handle(handle, "AEAContextCreateWithProfile")
265    }
266
267    /// Wraps `AEAContextCreateWithEncryptedStream`.
268    pub fn from_encrypted_stream(stream: &mut ByteStream) -> Result<Self> {
269        let handle = unsafe {
270            ffi::aea::compression_rs_aea_context_create_with_encrypted_stream(stream.as_ptr())
271        };
272        Self::from_handle(handle, "AEAContextCreateWithEncryptedStream")
273    }
274
275    pub(crate) fn as_ptr(&self) -> *mut c_void {
276        self.handle.as_ptr()
277    }
278
279    /// Wraps `AEAContextGetFieldUInt`.
280    pub fn field_uint(&self, field: AeaContextField) -> Result<u64> {
281        let value = unsafe {
282            ffi::aea::compression_rs_aea_context_get_field_uint(self.as_ptr(), field.raw())
283        };
284        if value == u64::MAX {
285            Err(CompressionError::OperationFailed {
286                operation: "AEAContextGetFieldUInt",
287                code: -1,
288            })
289        } else {
290            Ok(value)
291        }
292    }
293
294    /// Wraps `AEAContextGetFieldBlob`.
295    pub fn field_blob(
296        &self,
297        field: AeaContextField,
298        representation: AeaContextFieldRepresentation,
299    ) -> Result<Vec<u8>> {
300        let mut size = 0_usize;
301        let status = unsafe {
302            ffi::aea::compression_rs_aea_context_get_field_blob(
303                self.as_ptr(),
304                field.raw(),
305                representation.raw(),
306                0,
307                null_mut(),
308                &mut size,
309            )
310        };
311        util::status_result("AEAContextGetFieldBlob", status)?;
312
313        let mut data = vec![0_u8; size];
314        let status = unsafe {
315            ffi::aea::compression_rs_aea_context_get_field_blob(
316                self.as_ptr(),
317                field.raw(),
318                representation.raw(),
319                data.len(),
320                if data.is_empty() {
321                    null_mut()
322                } else {
323                    data.as_mut_ptr()
324                },
325                &mut size,
326            )
327        };
328        util::status_result("AEAContextGetFieldBlob", status)?;
329        Ok(data)
330    }
331
332    /// Wraps `AEAContextSetFieldUInt`.
333    pub fn set_field_uint(&mut self, field: AeaContextField, value: u64) -> Result<()> {
334        let status = unsafe {
335            ffi::aea::compression_rs_aea_context_set_field_uint(self.as_ptr(), field.raw(), value)
336        };
337        util::status_result("AEAContextSetFieldUInt", status)
338    }
339
340    /// Wraps `AEAContextSetFieldBlob`.
341    pub fn set_field_blob(
342        &mut self,
343        field: AeaContextField,
344        representation: AeaContextFieldRepresentation,
345        value: &[u8],
346    ) -> Result<()> {
347        let value_ptr = if value.is_empty() {
348            null()
349        } else {
350            value.as_ptr()
351        };
352        let status = unsafe {
353            ffi::aea::compression_rs_aea_context_set_field_blob(
354                self.as_ptr(),
355                field.raw(),
356                representation.raw(),
357                value_ptr,
358                value.len(),
359            )
360        };
361        util::status_result("AEAContextSetFieldBlob", status)
362    }
363
364    /// Wraps `AEAContextGenerateFieldBlob`.
365    pub fn generate_field_blob(&mut self, field: AeaContextField) -> Result<()> {
366        let status = unsafe {
367            ffi::aea::compression_rs_aea_context_generate_field_blob(self.as_ptr(), field.raw())
368        };
369        util::status_result("AEAContextGenerateFieldBlob", status)
370    }
371
372    /// Wraps `AEAContextDecryptAttributes`.
373    pub fn decrypt_attributes(&mut self) -> Result<()> {
374        let status =
375            unsafe { ffi::aea::compression_rs_aea_context_decrypt_attributes(self.as_ptr()) };
376        util::status_result("AEAContextDecryptAttributes", status)
377    }
378
379    /// Wraps `AEAContextGetProfile`.
380    pub fn profile(&self) -> Result<AeaProfile> {
381        let raw = u32::try_from(self.field_uint(AeaContextField::Profile)?).unwrap_or(u32::MAX);
382        AeaProfile::from_raw(raw).ok_or_else(|| CompressionError::OperationFailed {
383            operation: "AEAContextGetProfile",
384            code: i32::try_from(raw).unwrap_or(i32::MAX),
385        })
386    }
387
388    /// Wraps `AEAContextGetChecksumMode`.
389    pub fn checksum_mode(&self) -> Result<AeaChecksumMode> {
390        let raw =
391            u32::try_from(self.field_uint(AeaContextField::ChecksumMode)?).unwrap_or(u32::MAX);
392        AeaChecksumMode::from_raw(raw).ok_or_else(|| CompressionError::OperationFailed {
393            operation: "AEAContextGetChecksumMode",
394            code: i32::try_from(raw).unwrap_or(i32::MAX),
395        })
396    }
397
398    /// Wraps `AEAContextGetCompressionAlgorithm`.
399    pub fn compression_algorithm(&self) -> Result<ArchiveCompressionAlgorithm> {
400        let raw = u32::try_from(self.field_uint(AeaContextField::CompressionAlgorithm)?)
401            .unwrap_or(u32::MAX);
402        ArchiveCompressionAlgorithm::from_raw(raw).ok_or_else(|| {
403            CompressionError::OperationFailed {
404                operation: "AEAContextGetCompressionAlgorithm",
405                code: i32::try_from(raw).unwrap_or(i32::MAX),
406            }
407        })
408    }
409
410    /// Wraps `AEAContextGetCompressionBlockSize`.
411    pub fn compression_block_size(&self) -> Result<usize> {
412        usize::try_from(self.field_uint(AeaContextField::CompressionBlockSize)?).map_err(|_| {
413            CompressionError::OperationFailed {
414                operation: "AEAContextGetCompressionBlockSize",
415                code: i32::MAX,
416            }
417        })
418    }
419
420    /// Wraps `AEAContextGetFieldUInt` for `RawSize`.
421    pub fn raw_size(&self) -> Result<u64> {
422        self.field_uint(AeaContextField::RawSize)
423    }
424
425    /// Wraps `AEAContextGetFieldUInt` for `ContainerSize`.
426    pub fn container_size(&self) -> Result<u64> {
427        self.field_uint(AeaContextField::ContainerSize)
428    }
429
430    /// Wraps the `auth_data` convenience for `AeaContext`.
431    pub fn auth_data(&self) -> Result<Vec<u8>> {
432        self.field_blob(
433            AeaContextField::AuthData,
434            AeaContextFieldRepresentation::Raw,
435        )
436    }
437
438    /// Wraps the `signature_encryption_key` convenience for `AeaContext`.
439    pub fn signature_encryption_key(&self) -> Result<Vec<u8>> {
440        self.field_blob(
441            AeaContextField::SignatureEncryptionKey,
442            AeaContextFieldRepresentation::Raw,
443        )
444    }
445
446    /// Wraps the `archive_identifier` convenience for `AeaContext`.
447    pub fn archive_identifier(&self) -> Result<Vec<u8>> {
448        self.field_blob(
449            AeaContextField::ArchiveIdentifier,
450            AeaContextFieldRepresentation::Raw,
451        )
452    }
453
454    /// Wraps the `main_key` convenience for `AeaContext`.
455    pub fn main_key(&self) -> Result<Vec<u8>> {
456        self.field_blob(AeaContextField::MainKey, AeaContextFieldRepresentation::Raw)
457    }
458
459    /// Wraps the `set_compression_algorithm` convenience for `AeaContext`.
460    pub fn set_compression_algorithm(
461        &mut self,
462        compression_algorithm: ArchiveCompressionAlgorithm,
463    ) -> Result<()> {
464        self.set_field_uint(
465            AeaContextField::CompressionAlgorithm,
466            u64::from(compression_algorithm.as_raw()),
467        )
468    }
469
470    /// Wraps the `set_compression_block_size` convenience for `AeaContext`.
471    pub fn set_compression_block_size(&mut self, compression_block_size: usize) -> Result<()> {
472        self.set_field_uint(
473            AeaContextField::CompressionBlockSize,
474            u64::try_from(compression_block_size).unwrap_or(u64::MAX),
475        )
476    }
477
478    /// Wraps the `set_checksum_mode` convenience for `AeaContext`.
479    pub fn set_checksum_mode(&mut self, checksum_mode: AeaChecksumMode) -> Result<()> {
480        self.set_field_uint(
481            AeaContextField::ChecksumMode,
482            u64::from(checksum_mode.raw()),
483        )
484    }
485
486    /// Wraps the `set_padding_size` convenience for `AeaContext`.
487    pub fn set_padding_size(&mut self, padding_size: u64) -> Result<()> {
488        self.set_field_uint(AeaContextField::PaddingSize, padding_size)
489    }
490
491    /// Wraps the `set_auth_data_bytes` convenience for `AeaContext`.
492    pub fn set_auth_data_bytes(&mut self, auth_data: &[u8]) -> Result<()> {
493        self.set_field_blob(
494            AeaContextField::AuthData,
495            AeaContextFieldRepresentation::Raw,
496            auth_data,
497        )
498    }
499
500    /// Wraps the `set_auth_data_blob` convenience for `AeaContext`.
501    pub fn set_auth_data_blob(&mut self, auth_data: &AeaAuthData) -> Result<()> {
502        self.set_auth_data_bytes(&auth_data.encoded_data()?)
503    }
504
505    /// Wraps the `set_signature_encryption_key` convenience for `AeaContext`.
506    pub fn set_signature_encryption_key(&mut self, key: &[u8]) -> Result<()> {
507        self.set_field_blob(
508            AeaContextField::SignatureEncryptionKey,
509            AeaContextFieldRepresentation::Raw,
510            key,
511        )
512    }
513
514    /// Wraps the `set_symmetric_key` convenience for `AeaContext`.
515    pub fn set_symmetric_key(&mut self, key: &[u8]) -> Result<()> {
516        self.set_field_blob(
517            AeaContextField::SymmetricKey,
518            AeaContextFieldRepresentation::Raw,
519            key,
520        )
521    }
522
523    /// Wraps the `set_password` convenience for `AeaContext`.
524    pub fn set_password(&mut self, password: &[u8]) -> Result<()> {
525        self.set_field_blob(
526            AeaContextField::Password,
527            AeaContextFieldRepresentation::Raw,
528            password,
529        )
530    }
531
532    /// Wraps the `set_signing_public_key` convenience for `AeaContext`.
533    pub fn set_signing_public_key(&mut self, key: &[u8]) -> Result<()> {
534        self.set_field_blob(
535            AeaContextField::SigningPublicKey,
536            AeaContextFieldRepresentation::X963,
537            key,
538        )
539    }
540
541    /// Wraps `AEAEncryptionOutputStreamOpen`.
542    pub fn set_signing_private_key(&mut self, key: &[u8]) -> Result<()> {
543        self.set_field_blob(
544            AeaContextField::SigningPrivateKey,
545            AeaContextFieldRepresentation::X963,
546            key,
547        )
548    }
549
550    /// Wraps `AEAEncryptionOutputStreamOpen`.
551    pub fn set_recipient_public_key(&mut self, key: &[u8]) -> Result<()> {
552        self.set_field_blob(
553            AeaContextField::RecipientPublicKey,
554            AeaContextFieldRepresentation::X963,
555            key,
556        )
557    }
558
559    /// Wraps `AEAEncryptionOutputStreamOpen`.
560    pub fn set_recipient_private_key(&mut self, key: &[u8]) -> Result<()> {
561        self.set_field_blob(
562            AeaContextField::RecipientPrivateKey,
563            AeaContextFieldRepresentation::X963,
564            key,
565        )
566    }
567
568    /// Wraps `AEAEncryptionOutputStreamOpen`.
569    pub fn set_main_key(&mut self, key: &[u8]) -> Result<()> {
570        self.set_field_blob(
571            AeaContextField::MainKey,
572            AeaContextFieldRepresentation::Raw,
573            key,
574        )
575    }
576
577    /// Wraps `AEAEncryptionOutputStreamOpen`.
578    pub fn encryption_output_stream(
579        &self,
580        encrypted_stream: ByteStream,
581        flags: ArchiveFlags,
582        n_threads: i32,
583    ) -> Result<ByteStream> {
584        let handle = unsafe {
585            ffi::aea::compression_rs_aea_encryption_output_stream_open(
586                encrypted_stream.as_ptr(),
587                self.as_ptr(),
588                flags.bits(),
589                n_threads,
590            )
591        };
592        Self::open_byte_stream(handle, "AEAEncryptionOutputStreamOpen", encrypted_stream)
593    }
594
595    /// Wraps `AEAEncryptionOutputStreamOpenExisting`.
596    pub fn encryption_output_stream_existing(
597        &self,
598        encrypted_stream: ByteStream,
599        flags: ArchiveFlags,
600        n_threads: i32,
601    ) -> Result<ByteStream> {
602        let handle = unsafe {
603            ffi::aea::compression_rs_aea_encryption_output_stream_open_existing(
604                encrypted_stream.as_ptr(),
605                self.as_ptr(),
606                flags.bits(),
607                n_threads,
608            )
609        };
610        Self::open_byte_stream(
611            handle,
612            "AEAEncryptionOutputStreamOpenExisting",
613            encrypted_stream,
614        )
615    }
616
617    /// Wraps `AEADecryptionInputStreamOpen`.
618    pub fn decryption_input_stream(
619        &mut self,
620        encrypted_stream: ByteStream,
621        flags: ArchiveFlags,
622        n_threads: i32,
623    ) -> Result<ByteStream> {
624        let handle = unsafe {
625            ffi::aea::compression_rs_aea_decryption_input_stream_open(
626                encrypted_stream.as_ptr(),
627                self.as_ptr(),
628                flags.bits(),
629                n_threads,
630            )
631        };
632        Self::open_byte_stream(handle, "AEADecryptionInputStreamOpen", encrypted_stream)
633    }
634
635    /// Wraps `AEADecryptionRandomAccessInputStreamOpen`.
636    pub fn decryption_random_access_input_stream(
637        &mut self,
638        encrypted_stream: ByteStream,
639        alloc_limit: usize,
640        flags: ArchiveFlags,
641        n_threads: i32,
642    ) -> Result<ByteStream> {
643        let handle = unsafe {
644            ffi::aea::compression_rs_aea_decryption_random_access_input_stream_open(
645                encrypted_stream.as_ptr(),
646                self.as_ptr(),
647                alloc_limit,
648                flags.bits(),
649                n_threads,
650            )
651        };
652        Self::open_byte_stream(
653            handle,
654            "AEADecryptionRandomAccessInputStreamOpen",
655            encrypted_stream,
656        )
657    }
658
659    /// Wraps `AEAEncryptionOutputStreamCloseAndUpdateContext`.
660    pub fn close_encryption_output_stream(&mut self, stream: &mut ByteStream) -> Result<()> {
661        let status = unsafe {
662            ffi::aea::compression_rs_aea_encryption_output_stream_close_and_update_context(
663                stream.as_ptr(),
664                self.as_ptr(),
665            )
666        };
667        util::status_result("AEAEncryptionOutputStreamCloseAndUpdateContext", status)?;
668        stream.mark_closed();
669        Ok(())
670    }
671
672    /// Wraps `AEAStreamSign`.
673    pub fn sign_stream(&self, stream: &mut ByteStream) -> Result<()> {
674        let status =
675            unsafe { ffi::aea::compression_rs_aea_stream_sign(stream.as_ptr(), self.as_ptr()) };
676        util::status_result("AEAStreamSign", status)
677    }
678}
679
680impl Drop for AeaContext {
681    fn drop(&mut self) {
682        unsafe { ffi::aea::compression_rs_aea_context_release(self.as_ptr()) };
683    }
684}
685
686/// Wraps an `AEAAuthData` handle.
687#[derive(Debug)]
688pub struct AeaAuthData {
689    handle: NonNull<c_void>,
690}
691
692impl AeaAuthData {
693    fn from_handle(handle: *mut c_void, operation: &'static str) -> Result<Self> {
694        Ok(Self {
695            handle: util::nonnull_handle(handle, operation)?,
696        })
697    }
698
699    /// Wraps `AEAAuthDataCreate`.
700    pub fn new() -> Result<Self> {
701        let handle = unsafe { ffi::aea::compression_rs_aea_auth_data_create() };
702        Self::from_handle(handle, "AEAAuthDataCreate")
703    }
704
705    /// Wraps `AEAAuthDataCreateWithContext`.
706    pub fn from_context(context: &AeaContext) -> Result<Self> {
707        let handle =
708            unsafe { ffi::aea::compression_rs_aea_auth_data_create_with_context(context.as_ptr()) };
709        Self::from_handle(handle, "AEAAuthDataCreateWithContext")
710    }
711
712    pub(crate) fn as_ptr(&self) -> *mut c_void {
713        self.handle.as_ptr()
714    }
715
716    /// Wraps `AEAAuthDataGetEntry`.
717    pub fn entry_count(&self) -> u32 {
718        unsafe { ffi::aea::compression_rs_aea_auth_data_get_entry_count(self.as_ptr()) }
719    }
720
721    /// Wraps `AEAAuthDataGetEntry`.
722    pub fn is_empty(&self) -> bool {
723        self.entry_count() == 0
724    }
725
726    /// Wraps `AEAAuthDataGetEntry`.
727    pub fn entry(&self, index: u32) -> Result<NamedBlobEntry> {
728        let mut key_length = 0_usize;
729        let mut data_size = 0_usize;
730        let status = unsafe {
731            ffi::aea::compression_rs_aea_auth_data_get_entry(
732                self.as_ptr(),
733                index,
734                0,
735                null_mut(),
736                &mut key_length,
737                0,
738                null_mut(),
739                &mut data_size,
740            )
741        };
742        util::status_result("AEAAuthDataGetEntry", status)?;
743
744        let mut key = vec![0_i8; key_length.saturating_add(1)];
745        let mut value = vec![0_u8; data_size];
746        let status = unsafe {
747            ffi::aea::compression_rs_aea_auth_data_get_entry(
748                self.as_ptr(),
749                index,
750                key.len(),
751                key.as_mut_ptr(),
752                &mut key_length,
753                value.len(),
754                if value.is_empty() {
755                    null_mut()
756                } else {
757                    value.as_mut_ptr()
758                },
759                &mut data_size,
760            )
761        };
762        util::status_result("AEAAuthDataGetEntry", status)?;
763
764        let key = unsafe { CStr::from_ptr(key.as_ptr()) }
765            .to_str()
766            .map_err(|_| CompressionError::Utf8Error {
767                operation: "AEAAuthDataGetEntry",
768            })?
769            .to_string();
770
771        Ok(NamedBlobEntry { key, value })
772    }
773
774    /// Wraps `AEAAuthDataAppendEntry`.
775    pub fn entries(&self) -> Result<Vec<NamedBlobEntry>> {
776        (0..self.entry_count())
777            .map(|index| self.entry(index))
778            .collect()
779    }
780
781    /// Wraps `AEAAuthDataAppendEntry`.
782    pub fn append_entry(&mut self, entry: &NamedBlobEntry) -> Result<()> {
783        let key = util::cstring("key", &entry.key)?;
784        let data_ptr = if entry.value.is_empty() {
785            null()
786        } else {
787            entry.value.as_ptr()
788        };
789        let status = unsafe {
790            ffi::aea::compression_rs_aea_auth_data_append_entry(
791                self.as_ptr(),
792                key.as_ptr(),
793                data_ptr,
794                entry.value.len(),
795            )
796        };
797        util::status_result("AEAAuthDataAppendEntry", status)
798    }
799
800    /// Wraps `AEAAuthDataSetEntry`.
801    pub fn set_entry(&mut self, index: u32, entry: &NamedBlobEntry) -> Result<()> {
802        let key = util::cstring("key", &entry.key)?;
803        let data_ptr = if entry.value.is_empty() {
804            null()
805        } else {
806            entry.value.as_ptr()
807        };
808        let status = unsafe {
809            ffi::aea::compression_rs_aea_auth_data_set_entry(
810                self.as_ptr(),
811                index,
812                key.as_ptr(),
813                data_ptr,
814                entry.value.len(),
815            )
816        };
817        util::status_result("AEAAuthDataSetEntry", status)
818    }
819
820    /// Wraps `AEAAuthDataClear`.
821    pub fn clear(&mut self) -> Result<()> {
822        let status = unsafe { ffi::aea::compression_rs_aea_auth_data_clear(self.as_ptr()) };
823        util::status_result("AEAAuthDataClear", status)
824    }
825
826    /// Wraps `AEAAuthDataRemoveEntry`.
827    pub fn remove_entry(&mut self, index: u32) -> Result<()> {
828        let status =
829            unsafe { ffi::aea::compression_rs_aea_auth_data_remove_entry(self.as_ptr(), index) };
830        util::status_result("AEAAuthDataRemoveEntry", status)
831    }
832
833    /// Wraps `AEAAuthDataGetEncodedData`.
834    pub fn encoded_size(&self) -> usize {
835        unsafe { ffi::aea::compression_rs_aea_auth_data_get_encoded_size(self.as_ptr()) }
836    }
837
838    /// Wraps `AEAAuthDataGetEncodedData`.
839    pub fn encoded_data(&self) -> Result<Vec<u8>> {
840        let size = self.encoded_size();
841        let mut data = vec![0_u8; size];
842        if size == 0 {
843            return Ok(data);
844        }
845        let copied = unsafe {
846            ffi::aea::compression_rs_aea_auth_data_copy_encoded_data(
847                self.as_ptr(),
848                data.as_mut_ptr(),
849            )
850        };
851        if copied {
852            Ok(data)
853        } else {
854            Err(CompressionError::OperationFailed {
855                operation: "AEAAuthDataGetEncodedData",
856                code: -1,
857            })
858        }
859    }
860}
861
862impl Clone for AeaAuthData {
863    fn clone(&self) -> Self {
864        let mut clone = Self::new().expect("AEAAuthDataCreate returned null");
865        for entry in self.entries().expect("AEAAuthDataGetEntry failed") {
866            clone
867                .append_entry(&entry)
868                .expect("AEAAuthDataAppendEntry failed");
869        }
870        clone
871    }
872}
873
874impl Drop for AeaAuthData {
875    fn drop(&mut self) {
876        unsafe { ffi::aea::compression_rs_aea_auth_data_release(self.as_ptr()) };
877    }
878}