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