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}