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 =
207 unsafe { ffi::aea::compression_rs_aea_context_create_with_profile(profile.raw()) };
208 Self::from_handle(handle, "AEAContextCreateWithProfile")
209 }
210
211 pub fn from_encrypted_stream(stream: &mut ByteStream) -> Result<Self> {
212 let handle = unsafe {
213 ffi::aea::compression_rs_aea_context_create_with_encrypted_stream(stream.as_ptr())
214 };
215 Self::from_handle(handle, "AEAContextCreateWithEncryptedStream")
216 }
217
218 pub(crate) fn as_ptr(&self) -> *mut c_void {
219 self.handle.as_ptr()
220 }
221
222 pub fn field_uint(&self, field: AeaContextField) -> Result<u64> {
223 let value = unsafe {
224 ffi::aea::compression_rs_aea_context_get_field_uint(self.as_ptr(), field.raw())
225 };
226 if value == u64::MAX {
227 Err(CompressionError::OperationFailed {
228 operation: "AEAContextGetFieldUInt",
229 code: -1,
230 })
231 } else {
232 Ok(value)
233 }
234 }
235
236 pub fn field_blob(
237 &self,
238 field: AeaContextField,
239 representation: AeaContextFieldRepresentation,
240 ) -> Result<Vec<u8>> {
241 let mut size = 0_usize;
242 let status = unsafe {
243 ffi::aea::compression_rs_aea_context_get_field_blob(
244 self.as_ptr(),
245 field.raw(),
246 representation.raw(),
247 0,
248 null_mut(),
249 &mut size,
250 )
251 };
252 util::status_result("AEAContextGetFieldBlob", status)?;
253
254 let mut data = vec![0_u8; size];
255 let status = unsafe {
256 ffi::aea::compression_rs_aea_context_get_field_blob(
257 self.as_ptr(),
258 field.raw(),
259 representation.raw(),
260 data.len(),
261 if data.is_empty() {
262 null_mut()
263 } else {
264 data.as_mut_ptr()
265 },
266 &mut size,
267 )
268 };
269 util::status_result("AEAContextGetFieldBlob", status)?;
270 Ok(data)
271 }
272
273 pub fn set_field_uint(&mut self, field: AeaContextField, value: u64) -> Result<()> {
274 let status = unsafe {
275 ffi::aea::compression_rs_aea_context_set_field_uint(self.as_ptr(), field.raw(), value)
276 };
277 util::status_result("AEAContextSetFieldUInt", status)
278 }
279
280 pub fn set_field_blob(
281 &mut self,
282 field: AeaContextField,
283 representation: AeaContextFieldRepresentation,
284 value: &[u8],
285 ) -> Result<()> {
286 let value_ptr = if value.is_empty() {
287 null()
288 } else {
289 value.as_ptr()
290 };
291 let status = unsafe {
292 ffi::aea::compression_rs_aea_context_set_field_blob(
293 self.as_ptr(),
294 field.raw(),
295 representation.raw(),
296 value_ptr,
297 value.len(),
298 )
299 };
300 util::status_result("AEAContextSetFieldBlob", status)
301 }
302
303 pub fn generate_field_blob(&mut self, field: AeaContextField) -> Result<()> {
304 let status = unsafe {
305 ffi::aea::compression_rs_aea_context_generate_field_blob(self.as_ptr(), field.raw())
306 };
307 util::status_result("AEAContextGenerateFieldBlob", status)
308 }
309
310 pub fn decrypt_attributes(&mut self) -> Result<()> {
311 let status =
312 unsafe { ffi::aea::compression_rs_aea_context_decrypt_attributes(self.as_ptr()) };
313 util::status_result("AEAContextDecryptAttributes", status)
314 }
315
316 pub fn profile(&self) -> Result<AeaProfile> {
317 let raw = u32::try_from(self.field_uint(AeaContextField::Profile)?).unwrap_or(u32::MAX);
318 AeaProfile::from_raw(raw).ok_or_else(|| CompressionError::OperationFailed {
319 operation: "AEAContextGetProfile",
320 code: i32::try_from(raw).unwrap_or(i32::MAX),
321 })
322 }
323
324 pub fn checksum_mode(&self) -> Result<AeaChecksumMode> {
325 let raw =
326 u32::try_from(self.field_uint(AeaContextField::ChecksumMode)?).unwrap_or(u32::MAX);
327 AeaChecksumMode::from_raw(raw).ok_or_else(|| CompressionError::OperationFailed {
328 operation: "AEAContextGetChecksumMode",
329 code: i32::try_from(raw).unwrap_or(i32::MAX),
330 })
331 }
332
333 pub fn compression_algorithm(&self) -> Result<ArchiveCompressionAlgorithm> {
334 let raw = u32::try_from(self.field_uint(AeaContextField::CompressionAlgorithm)?)
335 .unwrap_or(u32::MAX);
336 ArchiveCompressionAlgorithm::from_raw(raw).ok_or_else(|| {
337 CompressionError::OperationFailed {
338 operation: "AEAContextGetCompressionAlgorithm",
339 code: i32::try_from(raw).unwrap_or(i32::MAX),
340 }
341 })
342 }
343
344 pub fn compression_block_size(&self) -> Result<usize> {
345 usize::try_from(self.field_uint(AeaContextField::CompressionBlockSize)?).map_err(|_| {
346 CompressionError::OperationFailed {
347 operation: "AEAContextGetCompressionBlockSize",
348 code: i32::MAX,
349 }
350 })
351 }
352
353 pub fn raw_size(&self) -> Result<u64> {
354 self.field_uint(AeaContextField::RawSize)
355 }
356
357 pub fn container_size(&self) -> Result<u64> {
358 self.field_uint(AeaContextField::ContainerSize)
359 }
360
361 pub fn auth_data(&self) -> Result<Vec<u8>> {
362 self.field_blob(
363 AeaContextField::AuthData,
364 AeaContextFieldRepresentation::Raw,
365 )
366 }
367
368 pub fn signature_encryption_key(&self) -> Result<Vec<u8>> {
369 self.field_blob(
370 AeaContextField::SignatureEncryptionKey,
371 AeaContextFieldRepresentation::Raw,
372 )
373 }
374
375 pub fn archive_identifier(&self) -> Result<Vec<u8>> {
376 self.field_blob(
377 AeaContextField::ArchiveIdentifier,
378 AeaContextFieldRepresentation::Raw,
379 )
380 }
381
382 pub fn main_key(&self) -> Result<Vec<u8>> {
383 self.field_blob(AeaContextField::MainKey, AeaContextFieldRepresentation::Raw)
384 }
385
386 pub fn set_compression_algorithm(
387 &mut self,
388 compression_algorithm: ArchiveCompressionAlgorithm,
389 ) -> Result<()> {
390 self.set_field_uint(
391 AeaContextField::CompressionAlgorithm,
392 u64::from(compression_algorithm.as_raw()),
393 )
394 }
395
396 pub fn set_compression_block_size(&mut self, compression_block_size: usize) -> Result<()> {
397 self.set_field_uint(
398 AeaContextField::CompressionBlockSize,
399 u64::try_from(compression_block_size).unwrap_or(u64::MAX),
400 )
401 }
402
403 pub fn set_checksum_mode(&mut self, checksum_mode: AeaChecksumMode) -> Result<()> {
404 self.set_field_uint(
405 AeaContextField::ChecksumMode,
406 u64::from(checksum_mode.raw()),
407 )
408 }
409
410 pub fn set_padding_size(&mut self, padding_size: u64) -> Result<()> {
411 self.set_field_uint(AeaContextField::PaddingSize, padding_size)
412 }
413
414 pub fn set_auth_data_bytes(&mut self, auth_data: &[u8]) -> Result<()> {
415 self.set_field_blob(
416 AeaContextField::AuthData,
417 AeaContextFieldRepresentation::Raw,
418 auth_data,
419 )
420 }
421
422 pub fn set_auth_data_blob(&mut self, auth_data: &AeaAuthData) -> Result<()> {
423 self.set_auth_data_bytes(&auth_data.encoded_data()?)
424 }
425
426 pub fn set_signature_encryption_key(&mut self, key: &[u8]) -> Result<()> {
427 self.set_field_blob(
428 AeaContextField::SignatureEncryptionKey,
429 AeaContextFieldRepresentation::Raw,
430 key,
431 )
432 }
433
434 pub fn set_symmetric_key(&mut self, key: &[u8]) -> Result<()> {
435 self.set_field_blob(
436 AeaContextField::SymmetricKey,
437 AeaContextFieldRepresentation::Raw,
438 key,
439 )
440 }
441
442 pub fn set_password(&mut self, password: &[u8]) -> Result<()> {
443 self.set_field_blob(
444 AeaContextField::Password,
445 AeaContextFieldRepresentation::Raw,
446 password,
447 )
448 }
449
450 pub fn set_signing_public_key(&mut self, key: &[u8]) -> Result<()> {
451 self.set_field_blob(
452 AeaContextField::SigningPublicKey,
453 AeaContextFieldRepresentation::X963,
454 key,
455 )
456 }
457
458 pub fn set_signing_private_key(&mut self, key: &[u8]) -> Result<()> {
459 self.set_field_blob(
460 AeaContextField::SigningPrivateKey,
461 AeaContextFieldRepresentation::X963,
462 key,
463 )
464 }
465
466 pub fn set_recipient_public_key(&mut self, key: &[u8]) -> Result<()> {
467 self.set_field_blob(
468 AeaContextField::RecipientPublicKey,
469 AeaContextFieldRepresentation::X963,
470 key,
471 )
472 }
473
474 pub fn set_recipient_private_key(&mut self, key: &[u8]) -> Result<()> {
475 self.set_field_blob(
476 AeaContextField::RecipientPrivateKey,
477 AeaContextFieldRepresentation::X963,
478 key,
479 )
480 }
481
482 pub fn set_main_key(&mut self, key: &[u8]) -> Result<()> {
483 self.set_field_blob(
484 AeaContextField::MainKey,
485 AeaContextFieldRepresentation::Raw,
486 key,
487 )
488 }
489
490 pub fn encryption_output_stream(
491 &self,
492 encrypted_stream: ByteStream,
493 flags: ArchiveFlags,
494 n_threads: i32,
495 ) -> Result<ByteStream> {
496 let handle = unsafe {
497 ffi::aea::compression_rs_aea_encryption_output_stream_open(
498 encrypted_stream.as_ptr(),
499 self.as_ptr(),
500 flags.bits(),
501 n_threads,
502 )
503 };
504 Self::open_byte_stream(handle, "AEAEncryptionOutputStreamOpen", encrypted_stream)
505 }
506
507 pub fn encryption_output_stream_existing(
508 &self,
509 encrypted_stream: ByteStream,
510 flags: ArchiveFlags,
511 n_threads: i32,
512 ) -> Result<ByteStream> {
513 let handle = unsafe {
514 ffi::aea::compression_rs_aea_encryption_output_stream_open_existing(
515 encrypted_stream.as_ptr(),
516 self.as_ptr(),
517 flags.bits(),
518 n_threads,
519 )
520 };
521 Self::open_byte_stream(
522 handle,
523 "AEAEncryptionOutputStreamOpenExisting",
524 encrypted_stream,
525 )
526 }
527
528 pub fn decryption_input_stream(
529 &mut self,
530 encrypted_stream: ByteStream,
531 flags: ArchiveFlags,
532 n_threads: i32,
533 ) -> Result<ByteStream> {
534 let handle = unsafe {
535 ffi::aea::compression_rs_aea_decryption_input_stream_open(
536 encrypted_stream.as_ptr(),
537 self.as_ptr(),
538 flags.bits(),
539 n_threads,
540 )
541 };
542 Self::open_byte_stream(handle, "AEADecryptionInputStreamOpen", encrypted_stream)
543 }
544
545 pub fn decryption_random_access_input_stream(
546 &mut self,
547 encrypted_stream: ByteStream,
548 alloc_limit: usize,
549 flags: ArchiveFlags,
550 n_threads: i32,
551 ) -> Result<ByteStream> {
552 let handle = unsafe {
553 ffi::aea::compression_rs_aea_decryption_random_access_input_stream_open(
554 encrypted_stream.as_ptr(),
555 self.as_ptr(),
556 alloc_limit,
557 flags.bits(),
558 n_threads,
559 )
560 };
561 Self::open_byte_stream(
562 handle,
563 "AEADecryptionRandomAccessInputStreamOpen",
564 encrypted_stream,
565 )
566 }
567
568 pub fn close_encryption_output_stream(&mut self, stream: &mut ByteStream) -> Result<()> {
569 let status = unsafe {
570 ffi::aea::compression_rs_aea_encryption_output_stream_close_and_update_context(
571 stream.as_ptr(),
572 self.as_ptr(),
573 )
574 };
575 util::status_result("AEAEncryptionOutputStreamCloseAndUpdateContext", status)?;
576 stream.mark_closed();
577 Ok(())
578 }
579
580 pub fn sign_stream(&self, stream: &mut ByteStream) -> Result<()> {
581 let status =
582 unsafe { ffi::aea::compression_rs_aea_stream_sign(stream.as_ptr(), self.as_ptr()) };
583 util::status_result("AEAStreamSign", status)
584 }
585}
586
587impl Drop for AeaContext {
588 fn drop(&mut self) {
589 unsafe { ffi::aea::compression_rs_aea_context_release(self.as_ptr()) };
590 }
591}
592
593#[derive(Debug)]
594pub struct AeaAuthData {
595 handle: NonNull<c_void>,
596}
597
598impl AeaAuthData {
599 fn from_handle(handle: *mut c_void, operation: &'static str) -> Result<Self> {
600 Ok(Self {
601 handle: util::nonnull_handle(handle, operation)?,
602 })
603 }
604
605 pub fn new() -> Result<Self> {
606 let handle = unsafe { ffi::aea::compression_rs_aea_auth_data_create() };
607 Self::from_handle(handle, "AEAAuthDataCreate")
608 }
609
610 pub fn from_context(context: &AeaContext) -> Result<Self> {
611 let handle =
612 unsafe { ffi::aea::compression_rs_aea_auth_data_create_with_context(context.as_ptr()) };
613 Self::from_handle(handle, "AEAAuthDataCreateWithContext")
614 }
615
616 pub(crate) fn as_ptr(&self) -> *mut c_void {
617 self.handle.as_ptr()
618 }
619
620 pub fn entry_count(&self) -> u32 {
621 unsafe { ffi::aea::compression_rs_aea_auth_data_get_entry_count(self.as_ptr()) }
622 }
623
624 pub fn is_empty(&self) -> bool {
625 self.entry_count() == 0
626 }
627
628 pub fn entry(&self, index: u32) -> Result<NamedBlobEntry> {
629 let mut key_length = 0_usize;
630 let mut data_size = 0_usize;
631 let status = unsafe {
632 ffi::aea::compression_rs_aea_auth_data_get_entry(
633 self.as_ptr(),
634 index,
635 0,
636 null_mut(),
637 &mut key_length,
638 0,
639 null_mut(),
640 &mut data_size,
641 )
642 };
643 util::status_result("AEAAuthDataGetEntry", status)?;
644
645 let mut key = vec![0_i8; key_length.saturating_add(1)];
646 let mut value = vec![0_u8; data_size];
647 let status = unsafe {
648 ffi::aea::compression_rs_aea_auth_data_get_entry(
649 self.as_ptr(),
650 index,
651 key.len(),
652 key.as_mut_ptr(),
653 &mut key_length,
654 value.len(),
655 if value.is_empty() {
656 null_mut()
657 } else {
658 value.as_mut_ptr()
659 },
660 &mut data_size,
661 )
662 };
663 util::status_result("AEAAuthDataGetEntry", status)?;
664
665 let key = unsafe { CStr::from_ptr(key.as_ptr()) }
666 .to_str()
667 .map_err(|_| CompressionError::Utf8Error {
668 operation: "AEAAuthDataGetEntry",
669 })?
670 .to_string();
671
672 Ok(NamedBlobEntry { key, value })
673 }
674
675 pub fn entries(&self) -> Result<Vec<NamedBlobEntry>> {
676 (0..self.entry_count())
677 .map(|index| self.entry(index))
678 .collect()
679 }
680
681 pub fn append_entry(&mut self, entry: &NamedBlobEntry) -> Result<()> {
682 let key = util::cstring("key", &entry.key)?;
683 let data_ptr = if entry.value.is_empty() {
684 null()
685 } else {
686 entry.value.as_ptr()
687 };
688 let status = unsafe {
689 ffi::aea::compression_rs_aea_auth_data_append_entry(
690 self.as_ptr(),
691 key.as_ptr(),
692 data_ptr,
693 entry.value.len(),
694 )
695 };
696 util::status_result("AEAAuthDataAppendEntry", status)
697 }
698
699 pub fn set_entry(&mut self, index: u32, entry: &NamedBlobEntry) -> Result<()> {
700 let key = util::cstring("key", &entry.key)?;
701 let data_ptr = if entry.value.is_empty() {
702 null()
703 } else {
704 entry.value.as_ptr()
705 };
706 let status = unsafe {
707 ffi::aea::compression_rs_aea_auth_data_set_entry(
708 self.as_ptr(),
709 index,
710 key.as_ptr(),
711 data_ptr,
712 entry.value.len(),
713 )
714 };
715 util::status_result("AEAAuthDataSetEntry", status)
716 }
717
718 pub fn clear(&mut self) -> Result<()> {
719 let status = unsafe { ffi::aea::compression_rs_aea_auth_data_clear(self.as_ptr()) };
720 util::status_result("AEAAuthDataClear", status)
721 }
722
723 pub fn remove_entry(&mut self, index: u32) -> Result<()> {
724 let status =
725 unsafe { ffi::aea::compression_rs_aea_auth_data_remove_entry(self.as_ptr(), index) };
726 util::status_result("AEAAuthDataRemoveEntry", status)
727 }
728
729 pub fn encoded_size(&self) -> usize {
730 unsafe { ffi::aea::compression_rs_aea_auth_data_get_encoded_size(self.as_ptr()) }
731 }
732
733 pub fn encoded_data(&self) -> Result<Vec<u8>> {
734 let size = self.encoded_size();
735 let mut data = vec![0_u8; size];
736 if size == 0 {
737 return Ok(data);
738 }
739 let copied = unsafe {
740 ffi::aea::compression_rs_aea_auth_data_copy_encoded_data(
741 self.as_ptr(),
742 data.as_mut_ptr(),
743 )
744 };
745 if copied {
746 Ok(data)
747 } else {
748 Err(CompressionError::OperationFailed {
749 operation: "AEAAuthDataGetEncodedData",
750 code: -1,
751 })
752 }
753 }
754}
755
756impl Clone for AeaAuthData {
757 fn clone(&self) -> Self {
758 let mut clone = Self::new().expect("AEAAuthDataCreate returned null");
759 for entry in self.entries().expect("AEAAuthDataGetEntry failed") {
760 clone
761 .append_entry(&entry)
762 .expect("AEAAuthDataAppendEntry failed");
763 }
764 clone
765 }
766}
767
768impl Drop for AeaAuthData {
769 fn drop(&mut self) {
770 unsafe { ffi::aea::compression_rs_aea_auth_data_release(self.as_ptr()) };
771 }
772}