1pub use static_assertions::const_assert_eq;
10
11use crate::endpoints::ProtocolMarker;
12use crate::handle::{HandleDisposition, HandleInfo, HandleOp, NullableHandle, ObjectType, Rights};
13use crate::time::{Instant, Ticks, Timeline};
14use crate::{Error, MethodType, Result};
15use bitflags::bitflags;
16pub use fidl_constants::*;
17use std::cell::RefCell;
18use std::marker::PhantomData;
19use std::{mem, ptr, str};
20
21pub trait ProxyChannelBox<D: ResourceDialect>: std::fmt::Debug + Send + Sync {
29 #[allow(clippy::type_complexity)]
32 fn recv_etc_from(
33 &self,
34 ctx: &mut std::task::Context<'_>,
35 buf: &mut D::MessageBufEtc,
36 ) -> std::task::Poll<Result<(), Option<<D::ProxyChannel as ProxyChannelFor<D>>::Error>>>;
37
38 #[cfg(not(target_os = "fuchsia"))]
39 fn closed_reason(&self) -> Option<String> {
41 None
42 }
43
44 fn as_channel(&self) -> &D::ProxyChannel;
46
47 fn write_etc(
49 &self,
50 bytes: &[u8],
51 handles: &mut [<D::ProxyChannel as ProxyChannelFor<D>>::HandleDisposition],
52 ) -> Result<(), Option<<D::ProxyChannel as ProxyChannelFor<D>>::Error>>;
53
54 fn is_closed(&self) -> bool;
56
57 fn unbox(self) -> D::ProxyChannel;
59}
60
61pub trait MessageBufFor<D: ResourceDialect>: std::fmt::Debug + Send + Sync {
63 fn new() -> Self;
65
66 fn shrink_bytes_to_fit(&mut self) {}
68
69 fn split_mut(&mut self) -> (&mut Vec<u8>, &mut Vec<<D::Handle as HandleFor<D>>::HandleInfo>);
71}
72
73pub trait ProxyChannelFor<D: ResourceDialect>:
75 std::fmt::Debug + crate::epitaph::ChannelLike
76{
77 type Boxed: ProxyChannelBox<D>;
79
80 type Error: Into<crate::TransportError>;
82
83 type HandleDisposition: HandleDispositionFor<D>;
87
88 fn boxed(self) -> Self::Boxed;
90
91 fn write_etc(
93 &self,
94 bytes: &[u8],
95 handles: &mut [Self::HandleDisposition],
96 ) -> Result<(), Option<Self::Error>>;
97}
98
99pub trait HandleDispositionFor<D: ResourceDialect>: std::fmt::Debug {
101 fn from_handle(
103 handle: D::Handle,
104 object_type: crate::ObjectType,
105 rights: crate::Rights,
106 ) -> Self;
107}
108
109pub trait HandleFor<D: ResourceDialect> {
111 type HandleInfo: HandleInfoFor<D>;
116
117 fn invalid() -> Self;
120
121 fn is_invalid(&self) -> bool;
123}
124
125pub trait HandleInfoFor<D: ResourceDialect>: std::fmt::Debug {
127 fn consume(
130 &mut self,
131 expected_object_type: crate::ObjectType,
132 expected_rights: crate::Rights,
133 ) -> Result<D::Handle>;
134
135 fn drop_in_place(&mut self);
137}
138
139pub trait ResourceDialect: 'static + Sized + Default + std::fmt::Debug + Copy + Clone {
141 type Handle: HandleFor<Self>;
143
144 type MessageBufEtc: MessageBufFor<Self>;
146
147 type ProxyChannel: ProxyChannelFor<Self>;
149
150 fn with_tls_buf<R>(f: impl FnOnce(&mut TlsBuf<Self>) -> R) -> R;
152}
153
154pub trait EncodableAsHandle: Into<<Self::Dialect as ResourceDialect>::Handle> {
156 type Dialect: ResourceDialect<Handle: Into<Self>>;
158}
159
160pub unsafe trait TypeMarker: 'static + Sized {
183 type Owned;
185
186 fn inline_align(context: Context) -> usize;
189
190 fn inline_size(context: Context) -> usize;
193
194 #[inline(always)]
202 fn encode_is_copy() -> bool {
203 false
204 }
205
206 #[inline(always)]
210 fn decode_is_copy() -> bool {
211 false
212 }
213}
214
215pub trait ValueTypeMarker: TypeMarker {
220 type Borrowed<'a>;
227
228 fn borrow(value: &Self::Owned) -> Self::Borrowed<'_>;
230}
231
232pub trait ResourceTypeMarker: TypeMarker {
237 type Borrowed<'a>;
244
245 fn take_or_borrow(value: &mut Self::Owned) -> Self::Borrowed<'_>;
250}
251
252pub unsafe trait Encode<T: TypeMarker, D: ResourceDialect>: Sized {
260 unsafe fn encode(self, encoder: &mut Encoder<'_, D>, offset: usize, depth: Depth)
270 -> Result<()>;
271}
272
273pub trait Decode<T: TypeMarker, D>: 'static + Sized {
275 fn new_empty() -> Self;
279
280 unsafe fn decode(
292 &mut self,
293 decoder: &mut Decoder<'_, D>,
294 offset: usize,
295 depth: Depth,
296 ) -> Result<()>
297 where
298 D: ResourceDialect;
299}
300
301#[derive(Debug)]
308pub struct FuchsiaProxyBox(crate::AsyncChannel);
309
310impl FuchsiaProxyBox {
311 pub fn on_closed(&self) -> crate::OnSignalsRef<'_> {
313 self.0.on_closed()
314 }
315
316 pub fn read_etc(
318 &self,
319 cx: &mut std::task::Context<'_>,
320 bytes: &mut Vec<u8>,
321 handles: &mut Vec<crate::HandleInfo>,
322 ) -> std::task::Poll<Result<(), crate::Status>> {
323 self.0.read_etc(cx, bytes, handles)
324 }
325
326 pub fn signal_peer(
328 &self,
329 clear: crate::Signals,
330 set: crate::Signals,
331 ) -> Result<(), zx_status::Status> {
332 use crate::Peered;
333 self.0.as_ref().signal_peer(clear, set)
334 }
335}
336
337impl ProxyChannelBox<DefaultFuchsiaResourceDialect> for FuchsiaProxyBox {
338 fn write_etc(
339 &self,
340 bytes: &[u8],
341 handles: &mut [HandleDisposition<'static>],
342 ) -> Result<(), Option<zx_status::Status>> {
343 self.0
344 .write_etc(bytes, handles)
345 .map_err(|x| Some(x).filter(|x| *x != zx_status::Status::PEER_CLOSED))
346 }
347
348 fn recv_etc_from(
349 &self,
350 ctx: &mut std::task::Context<'_>,
351 buf: &mut crate::MessageBufEtc,
352 ) -> std::task::Poll<Result<(), Option<zx_status::Status>>> {
353 self.0
354 .recv_etc_from(ctx, buf)
355 .map_err(|x| Some(x).filter(|x| *x != zx_status::Status::PEER_CLOSED))
356 }
357
358 fn is_closed(&self) -> bool {
359 self.0.is_closed()
360 }
361
362 #[cfg(not(target_os = "fuchsia"))]
363 fn closed_reason(&self) -> Option<String> {
364 self.0.closed_reason()
365 }
366
367 fn unbox(self) -> <DefaultFuchsiaResourceDialect as ResourceDialect>::ProxyChannel {
368 self.0
369 }
370
371 fn as_channel(&self) -> &<DefaultFuchsiaResourceDialect as ResourceDialect>::ProxyChannel {
372 &self.0
373 }
374}
375
376#[derive(Debug, Default, Copy, Clone)]
379pub struct DefaultFuchsiaResourceDialect;
380impl ResourceDialect for DefaultFuchsiaResourceDialect {
381 type Handle = NullableHandle;
382 type MessageBufEtc = crate::MessageBufEtc;
383 type ProxyChannel = crate::AsyncChannel;
384
385 #[inline]
386 fn with_tls_buf<R>(f: impl FnOnce(&mut TlsBuf<Self>) -> R) -> R {
387 thread_local!(static TLS_BUF: RefCell<TlsBuf<DefaultFuchsiaResourceDialect>> =
388 RefCell::new(TlsBuf::default()));
389 TLS_BUF.with(|buf| f(&mut buf.borrow_mut()))
390 }
391}
392
393impl MessageBufFor<DefaultFuchsiaResourceDialect> for crate::MessageBufEtc {
394 fn new() -> crate::MessageBufEtc {
395 let mut ret = crate::MessageBufEtc::new();
396 ret.ensure_capacity_bytes(MIN_BUF_BYTES_SIZE);
397 ret
398 }
399
400 fn shrink_bytes_to_fit(&mut self) {
401 self.shrink_bytes_to_fit();
402 }
403
404 fn split_mut(&mut self) -> (&mut Vec<u8>, &mut Vec<HandleInfo>) {
405 self.split_mut()
406 }
407}
408
409impl ProxyChannelFor<DefaultFuchsiaResourceDialect> for crate::AsyncChannel {
410 type Boxed = FuchsiaProxyBox;
411 type Error = zx_status::Status;
412 type HandleDisposition = HandleDisposition<'static>;
413
414 fn boxed(self) -> FuchsiaProxyBox {
415 FuchsiaProxyBox(self)
416 }
417
418 fn write_etc(
419 &self,
420 bytes: &[u8],
421 handles: &mut [HandleDisposition<'static>],
422 ) -> Result<(), Option<zx_status::Status>> {
423 self.write_etc(bytes, handles)
424 .map_err(|x| Some(x).filter(|x| *x != zx_status::Status::PEER_CLOSED))
425 }
426}
427
428impl HandleDispositionFor<DefaultFuchsiaResourceDialect> for HandleDisposition<'static> {
429 fn from_handle(handle: NullableHandle, object_type: ObjectType, rights: Rights) -> Self {
430 HandleDisposition::new(HandleOp::Move(handle), object_type, rights, Ok(()))
431 }
432}
433
434impl HandleFor<DefaultFuchsiaResourceDialect> for NullableHandle {
435 type HandleInfo = HandleInfo;
436
437 fn invalid() -> Self {
438 NullableHandle::invalid()
439 }
440
441 fn is_invalid(&self) -> bool {
442 self.is_invalid()
443 }
444}
445
446impl HandleInfoFor<DefaultFuchsiaResourceDialect> for HandleInfo {
447 fn consume(
448 &mut self,
449 expected_object_type: ObjectType,
450 expected_rights: Rights,
451 ) -> Result<NullableHandle> {
452 let handle_info = std::mem::replace(
453 self,
454 HandleInfo::new(NullableHandle::invalid(), ObjectType::NONE, Rights::NONE),
455 );
456 let received_object_type = handle_info.object_type;
457 if expected_object_type != ObjectType::NONE
458 && received_object_type != ObjectType::NONE
459 && expected_object_type != received_object_type
460 {
461 return Err(Error::IncorrectHandleSubtype {
462 expected: expected_object_type,
463 received: received_object_type,
464 });
465 }
466
467 let received_rights = handle_info.rights;
468 if expected_rights != Rights::SAME_RIGHTS
469 && received_rights != Rights::SAME_RIGHTS
470 && expected_rights != received_rights
471 {
472 if !received_rights.contains(expected_rights) {
473 return Err(Error::MissingExpectedHandleRights {
474 missing_rights: expected_rights - received_rights,
475 });
476 }
477 return match handle_info.handle.replace_handle(expected_rights) {
478 Ok(r) => Ok(r),
479 Err(status) => Err(Error::HandleReplace(status)),
480 };
481 }
482 Ok(handle_info.handle)
483 }
484
485 #[inline(always)]
486 fn drop_in_place(&mut self) {
487 *self = HandleInfo::new(NullableHandle::invalid(), ObjectType::NONE, Rights::NONE);
488 }
489}
490
491#[cfg(not(target_os = "fuchsia"))]
493#[derive(Debug)]
494pub enum NoHandles {}
495
496#[cfg(not(target_os = "fuchsia"))]
497impl ProxyChannelBox<NoHandleResourceDialect> for NoHandles {
498 fn recv_etc_from(
499 &self,
500 _ctx: &mut std::task::Context<'_>,
501 _buf: &mut <NoHandleResourceDialect as ResourceDialect>::MessageBufEtc,
502 ) -> std::task::Poll<Result<(), Option<zx_status::Status>>> {
503 unreachable!()
504 }
505
506 fn write_etc(
507 &self,
508 _bytes: &[u8],
509 _handles: &mut [
510 <<NoHandleResourceDialect as ResourceDialect>::ProxyChannel
511 as ProxyChannelFor<NoHandleResourceDialect>>::HandleDisposition],
512 ) -> Result<(), Option<zx_status::Status>> {
513 unreachable!()
514 }
515
516 fn is_closed(&self) -> bool {
517 unreachable!()
518 }
519
520 fn unbox(self) -> <NoHandleResourceDialect as ResourceDialect>::ProxyChannel {
521 unreachable!()
522 }
523
524 fn as_channel(&self) -> &<NoHandleResourceDialect as ResourceDialect>::ProxyChannel {
525 unreachable!()
526 }
527}
528
529#[cfg(not(target_os = "fuchsia"))]
531#[derive(Debug, Default, Copy, Clone)]
532pub struct NoHandleResourceDialect;
533
534#[cfg(not(target_os = "fuchsia"))]
535impl ResourceDialect for NoHandleResourceDialect {
536 type Handle = NoHandles;
537 type MessageBufEtc = NoHandles;
538 type ProxyChannel = NoHandles;
539
540 #[inline]
541 fn with_tls_buf<R>(f: impl FnOnce(&mut TlsBuf<Self>) -> R) -> R {
542 thread_local!(static TLS_BUF: RefCell<TlsBuf<NoHandleResourceDialect>> =
543 RefCell::new(TlsBuf::default()));
544 TLS_BUF.with(|buf| f(&mut buf.borrow_mut()))
545 }
546}
547
548#[cfg(not(target_os = "fuchsia"))]
549impl MessageBufFor<NoHandleResourceDialect> for NoHandles {
550 fn new() -> Self {
551 unreachable!()
552 }
553
554 fn split_mut(&mut self) -> (&mut Vec<u8>, &mut Vec<NoHandles>) {
555 unreachable!()
556 }
557}
558
559#[cfg(not(target_os = "fuchsia"))]
560impl ProxyChannelFor<NoHandleResourceDialect> for NoHandles {
561 type Boxed = NoHandles;
562 type Error = zx_status::Status;
563 type HandleDisposition = NoHandles;
564
565 fn boxed(self) -> NoHandles {
566 unreachable!()
567 }
568
569 fn write_etc(
570 &self,
571 _bytes: &[u8],
572 _handles: &mut [NoHandles],
573 ) -> Result<(), Option<zx_status::Status>> {
574 unreachable!()
575 }
576}
577
578#[cfg(not(target_os = "fuchsia"))]
579impl crate::epitaph::ChannelLike for NoHandles {
580 fn write_epitaph(&self, _bytes: &[u8]) -> std::result::Result<(), crate::TransportError> {
581 unreachable!()
582 }
583}
584
585#[cfg(not(target_os = "fuchsia"))]
586impl HandleFor<NoHandleResourceDialect> for NoHandles {
587 type HandleInfo = NoHandles;
588
589 fn invalid() -> Self {
590 unreachable!()
591 }
592
593 fn is_invalid(&self) -> bool {
594 unreachable!()
595 }
596}
597
598#[cfg(not(target_os = "fuchsia"))]
599impl HandleDispositionFor<NoHandleResourceDialect> for NoHandles {
600 fn from_handle(
601 _handle: <NoHandleResourceDialect as ResourceDialect>::Handle,
602 _object_type: crate::ObjectType,
603 _rights: crate::Rights,
604 ) -> Self {
605 unreachable!()
606 }
607}
608
609#[cfg(not(target_os = "fuchsia"))]
610impl HandleInfoFor<NoHandleResourceDialect> for NoHandles {
611 fn consume(
612 &mut self,
613 _expected_object_type: crate::ObjectType,
614 _expected_rights: crate::Rights,
615 ) -> Result<<NoHandleResourceDialect as ResourceDialect>::Handle> {
616 unreachable!()
617 }
618
619 fn drop_in_place(&mut self) {
620 unreachable!()
621 }
622}
623
624#[cfg(target_os = "fuchsia")]
626pub type NoHandleResourceDialect = DefaultFuchsiaResourceDialect;
627
628#[doc(hidden)] #[inline(always)]
637pub fn round_up_to_align(x: usize, align: usize) -> usize {
638 debug_assert_ne!(align, 0);
639 debug_assert_eq!(align & (align - 1), 0);
640 (x + align - 1) & !(align - 1)
642}
643
644#[inline]
662unsafe fn resize_vec_no_zeroing<T>(buf: &mut Vec<T>, new_len: usize) {
663 if new_len > buf.capacity() {
664 buf.reserve(new_len - buf.len());
665 }
666 unsafe { buf.set_len(new_len) };
672}
673
674#[doc(hidden)] #[derive(Debug, Copy, Clone)]
677#[repr(transparent)]
678pub struct Depth(usize);
679
680impl Depth {
681 #[inline(always)]
683 pub fn increment(&mut self) -> Result<()> {
684 self.0 += 1;
685 if self.0 > MAX_RECURSION {
686 return Err(Error::MaxRecursionDepth);
687 }
688 Ok(())
689 }
690}
691
692#[doc(hidden)] #[macro_export]
699macro_rules! new_empty {
700 ($ty:ty) => {
701 <<$ty as $crate::encoding::TypeMarker>::Owned as $crate::encoding::Decode<$ty, _>>::new_empty()
702 };
703 ($ty:ty, $d:path) => {
704 <<$ty as $crate::encoding::TypeMarker>::Owned as $crate::encoding::Decode<$ty, $d>>::new_empty()
705 };
706}
707
708#[doc(hidden)] #[macro_export]
711macro_rules! decode {
712 ($ty:ty, $out_value:expr, $decoder:expr, $offset:expr, $depth:expr) => {
713 <<$ty as $crate::encoding::TypeMarker>::Owned as $crate::encoding::Decode<$ty, _>>::decode(
714 $out_value, $decoder, $offset, $depth,
715 )
716 };
717 ($ty:ty, $d:path, $out_value:expr, $decoder:expr, $offset:expr, $depth:expr) => {
718 <<$ty as $crate::encoding::TypeMarker>::Owned as $crate::encoding::Decode<$ty, $d>>::decode(
719 $out_value, $decoder, $offset, $depth,
720 )
721 };
722}
723
724#[derive(Clone, Copy, Debug)]
730pub enum WireFormatVersion {
731 V2,
733}
734
735#[derive(Clone, Copy, Debug)]
741pub struct Context {
742 pub wire_format_version: WireFormatVersion,
744}
745
746const_assert_eq!(mem::size_of::<Context>(), 0);
748
749impl Context {
750 #[inline]
752 pub(crate) fn at_rest_flags(&self) -> AtRestFlags {
753 match self.wire_format_version {
754 WireFormatVersion::V2 => AtRestFlags::USE_V2_WIRE_FORMAT,
755 }
756 }
757}
758
759#[derive(Debug)]
765pub struct Encoder<'a, D: ResourceDialect> {
766 pub context: Context,
768
769 pub buf: &'a mut Vec<u8>,
771
772 handles: &'a mut Vec<<D::ProxyChannel as ProxyChannelFor<D>>::HandleDisposition>,
774
775 _dialect: PhantomData<D>,
777}
778
779#[inline]
781fn default_encode_context() -> Context {
782 Context { wire_format_version: WireFormatVersion::V2 }
783}
784
785impl<'a, D: ResourceDialect> Encoder<'a, D> {
786 #[inline]
788 pub fn encode<T: TypeMarker>(
789 buf: &'a mut Vec<u8>,
790 handles: &'a mut Vec<<D::ProxyChannel as ProxyChannelFor<D>>::HandleDisposition>,
791 x: impl Encode<T, D>,
792 ) -> Result<()> {
793 let context = default_encode_context();
794 Self::encode_with_context::<T>(context, buf, handles, x)
795 }
796
797 #[inline]
804 pub fn encode_with_context<T: TypeMarker>(
805 context: Context,
806 buf: &'a mut Vec<u8>,
807 handles: &'a mut Vec<<D::ProxyChannel as ProxyChannelFor<D>>::HandleDisposition>,
808 x: impl Encode<T, D>,
809 ) -> Result<()> {
810 fn prepare_for_encoding<'a, D: ResourceDialect>(
811 context: Context,
812 buf: &'a mut Vec<u8>,
813 handles: &'a mut Vec<<D::ProxyChannel as ProxyChannelFor<D>>::HandleDisposition>,
814 ty_inline_size: usize,
815 ) -> Encoder<'a, D> {
816 if ty_inline_size != 0 {
819 let aligned_inline_size = round_up_to_align(ty_inline_size, 8);
820 unsafe {
823 resize_vec_no_zeroing(buf, aligned_inline_size);
824
825 let padding_ptr = buf.get_unchecked_mut(aligned_inline_size - 8) as *mut u8;
827 (padding_ptr as *mut u64).write_unaligned(0);
828 }
829 }
830 handles.clear();
831 Encoder { buf, handles, context, _dialect: PhantomData }
832 }
833 let mut encoder = prepare_for_encoding(context, buf, handles, T::inline_size(context));
834 unsafe { x.encode(&mut encoder, 0, Depth(0)) }
836 }
837
838 #[inline(always)]
841 pub fn debug_check_bounds<T: TypeMarker>(&self, offset: usize) {
842 debug_assert!(offset + T::inline_size(self.context) <= self.buf.len());
843 }
844
845 #[inline(always)]
852 pub unsafe fn write_num<T: numeric::Numeric>(&mut self, num: T, offset: usize) {
853 debug_assert!(offset + mem::size_of::<T>() <= self.buf.len());
854 let ptr = unsafe { self.buf.get_unchecked_mut(offset) } as *mut u8;
858 unsafe { (ptr as *mut T).write_unaligned(num) };
859 }
860
861 #[inline(always)]
863 pub fn push_next_handle(
864 &mut self,
865 handle: <D::ProxyChannel as ProxyChannelFor<D>>::HandleDisposition,
866 ) {
867 self.handles.push(handle)
868 }
869
870 #[inline]
877 pub unsafe fn out_of_line_offset(&mut self, len: usize) -> usize {
878 debug_assert!(len > 0);
879 let new_offset = self.buf.len();
880 let padded_len = round_up_to_align(len, 8);
881 debug_assert!(padded_len >= 8);
882 let new_len = self.buf.len() + padded_len;
883 unsafe { resize_vec_no_zeroing(self.buf, new_len) };
884 let padding_ptr = unsafe { self.buf.get_unchecked_mut(new_len - 8) } as *mut u8;
888 unsafe { (padding_ptr as *mut u64).write_unaligned(0) };
889 new_offset
890 }
891
892 #[inline(always)]
899 pub unsafe fn padding(&mut self, offset: usize, len: usize) {
900 if len == 0 {
901 return;
902 }
903 debug_assert!(offset + len <= self.buf.len());
904 unsafe { ptr::write_bytes(self.buf.as_mut_ptr().add(offset), 0, len) };
908 }
909}
910
911unsafe impl<T: Timeline + 'static, U: 'static> TypeMarker for Instant<T, U> {
912 type Owned = Self;
913
914 #[inline(always)]
915 fn inline_align(_context: Context) -> usize {
916 mem::align_of::<Self>()
917 }
918
919 #[inline(always)]
920 fn inline_size(_context: Context) -> usize {
921 mem::size_of::<Self>()
922 }
923}
924
925impl<T: Timeline + Copy + 'static, U: Copy + 'static> ValueTypeMarker for Instant<T, U> {
926 type Borrowed<'a> = Self;
927 fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
928 *value
929 }
930}
931
932unsafe impl<T: Timeline + Copy + 'static, D: ResourceDialect> Encode<Instant<T>, D> for Instant<T> {
933 #[inline]
934 unsafe fn encode(
935 self,
936 encoder: &mut Encoder<'_, D>,
937 offset: usize,
938 _depth: Depth,
939 ) -> Result<()> {
940 encoder.debug_check_bounds::<Self>(offset);
941 unsafe { encoder.write_num(self.into_nanos(), offset) };
942 Ok(())
943 }
944}
945
946unsafe impl<T: Timeline + 'static, D: ResourceDialect> Encode<Ticks<T>, D> for Ticks<T> {
947 #[inline]
948 unsafe fn encode(
949 self,
950 encoder: &mut Encoder<'_, D>,
951 offset: usize,
952 _depth: Depth,
953 ) -> Result<()> {
954 encoder.debug_check_bounds::<Self>(offset);
955 unsafe { encoder.write_num(self.into_raw(), offset) };
956 Ok(())
957 }
958}
959
960#[derive(Debug)]
966pub struct Decoder<'a, D: ResourceDialect> {
967 pub context: Context,
969
970 pub buf: &'a [u8],
972
973 next_out_of_line: usize,
975
976 handles: &'a mut [<D::Handle as HandleFor<D>>::HandleInfo],
978
979 next_handle: usize,
981
982 _dialect: PhantomData<D>,
984}
985
986impl<'a, D: ResourceDialect> Decoder<'a, D> {
987 #[inline]
991 pub fn decode_into<T: TypeMarker>(
992 header: &TransactionHeader,
993 buf: &'a [u8],
994 handles: &'a mut [<D::Handle as HandleFor<D>>::HandleInfo],
995 value: &mut T::Owned,
996 ) -> Result<()>
997 where
998 T::Owned: Decode<T, D>,
999 {
1000 Self::decode_with_context::<T>(header.decoding_context(), buf, handles, value)
1001 }
1002
1003 #[inline]
1010 pub fn decode_with_context<T: TypeMarker>(
1011 context: Context,
1012 buf: &'a [u8],
1013 handles: &'a mut [<D::Handle as HandleFor<D>>::HandleInfo],
1014 value: &mut T::Owned,
1015 ) -> Result<()>
1016 where
1017 T::Owned: Decode<T, D>,
1018 {
1019 let inline_size = T::inline_size(context);
1020 let next_out_of_line = round_up_to_align(inline_size, 8);
1021 if next_out_of_line > buf.len() {
1022 return Err(Error::OutOfRange { expected: next_out_of_line, actual: buf.len() });
1023 }
1024 let mut decoder = Decoder {
1025 next_out_of_line,
1026 buf,
1027 handles,
1028 next_handle: 0,
1029 context,
1030 _dialect: PhantomData,
1031 };
1032 unsafe {
1034 value.decode(&mut decoder, 0, Depth(0))?;
1035 }
1036 unsafe { decoder.post_decoding(inline_size, next_out_of_line) }
1038 }
1039
1040 unsafe fn post_decoding(&self, padding_start: usize, padding_end: usize) -> Result<()> {
1047 if self.next_out_of_line < self.buf.len() {
1048 return Err(Error::ExtraBytes);
1049 }
1050 if self.next_handle < self.handles.len() {
1051 return Err(Error::ExtraHandles);
1052 }
1053
1054 let padding = padding_end - padding_start;
1055 if padding > 0 {
1056 let last_u64 = unsafe {
1059 let last_u64_ptr = self.buf.get_unchecked(padding_end - 8) as *const u8;
1060 (last_u64_ptr as *const u64).read_unaligned()
1061 };
1062 let mask = !(!0u64 >> (padding * 8));
1067 if last_u64 & mask != 0 {
1068 return Err(self.end_of_block_padding_error(padding_start, padding_end));
1069 }
1070 }
1071
1072 Ok(())
1073 }
1074
1075 #[inline(always)]
1078 pub fn next_out_of_line(&self) -> usize {
1079 self.next_out_of_line
1080 }
1081
1082 #[inline(always)]
1084 pub fn remaining_handles(&self) -> usize {
1085 self.handles.len() - self.next_handle
1086 }
1087
1088 #[inline(always)]
1091 pub fn debug_check_bounds<T: TypeMarker>(&self, offset: usize) {
1092 debug_assert!(offset + T::inline_size(self.context) <= self.buf.len());
1093 }
1094
1095 #[inline(always)]
1098 pub fn read_num<T: numeric::Numeric>(&mut self, offset: usize) -> T {
1099 debug_assert!(offset + mem::size_of::<T>() <= self.buf.len());
1100 unsafe {
1104 let ptr = self.buf.get_unchecked(offset) as *const u8;
1105 (ptr as *const T).read_unaligned()
1106 }
1107 }
1108
1109 #[inline(always)]
1116 pub unsafe fn out_of_line_offset(&mut self, len: usize) -> Result<usize> {
1117 debug_assert!(len > 0);
1118 let offset = self.next_out_of_line;
1119 let aligned_len = round_up_to_align(len, 8);
1120 self.next_out_of_line += aligned_len;
1121 debug_assert!(self.next_out_of_line >= 8);
1122 if self.next_out_of_line > self.buf.len() {
1123 return Err(Error::OutOfRange {
1124 expected: aligned_len,
1125 actual: self.buf.len() - offset,
1126 });
1127 }
1128 let last_u64_ptr =
1134 unsafe { self.buf.get_unchecked(self.next_out_of_line - 8) } as *const u8;
1135 let last_u64 = unsafe { (last_u64_ptr as *const u64).read_unaligned() };
1136 let padding = aligned_len - len;
1137 let mask = !(!0u64 >> (padding * 8));
1142 if last_u64 & mask != 0 {
1143 return Err(self.end_of_block_padding_error(offset + len, self.next_out_of_line));
1144 }
1145
1146 Ok(offset)
1147 }
1148
1149 fn end_of_block_padding_error(&self, start: usize, end: usize) -> Error {
1152 for byte in &self.buf[start..end] {
1153 if *byte != 0 {
1154 return Error::NonZeroPadding { padding_start: start };
1155 }
1156 }
1157 std::process::abort();
1160 }
1161
1162 #[inline]
1165 pub fn check_padding(&self, offset: usize, len: usize) -> Result<()> {
1166 if len == 0 {
1167 return Ok(());
1169 }
1170 debug_assert!(offset + len <= self.buf.len());
1171 for i in offset..offset + len {
1172 if unsafe { *self.buf.get_unchecked(i) } != 0 {
1174 return Err(Error::NonZeroPadding { padding_start: offset });
1175 }
1176 }
1177 Ok(())
1178 }
1179
1180 #[inline]
1186 pub fn check_inline_envelope_padding(
1187 &self,
1188 value_offset: usize,
1189 value_len: usize,
1190 ) -> Result<()> {
1191 let valid_padding = unsafe {
1194 match value_len {
1195 1 => {
1196 *self.buf.get_unchecked(value_offset + 1) == 0
1197 && *self.buf.get_unchecked(value_offset + 2) == 0
1198 && *self.buf.get_unchecked(value_offset + 3) == 0
1199 }
1200 2 => {
1201 *self.buf.get_unchecked(value_offset + 2) == 0
1202 && *self.buf.get_unchecked(value_offset + 3) == 0
1203 }
1204 3 => *self.buf.get_unchecked(value_offset + 3) == 0,
1205 4 => true,
1206 value_len => unreachable!("value_len={}", value_len),
1207 }
1208 };
1209 if valid_padding {
1210 Ok(())
1211 } else {
1212 Err(Error::NonZeroPadding { padding_start: value_offset + value_len })
1213 }
1214 }
1215
1216 #[inline]
1218 pub fn take_next_handle(
1219 &mut self,
1220 expected_object_type: crate::ObjectType,
1221 expected_rights: crate::Rights,
1222 ) -> Result<D::Handle> {
1223 let Some(next_handle) = self.handles.get_mut(self.next_handle) else {
1224 return Err(Error::OutOfHandles);
1225 };
1226 let handle = next_handle.consume(expected_object_type, expected_rights)?;
1227 self.next_handle += 1;
1228 Ok(handle)
1229 }
1230
1231 #[inline]
1233 pub fn drop_next_handle(&mut self) -> Result<()> {
1234 let Some(next_handle) = self.handles.get_mut(self.next_handle) else {
1235 return Err(Error::OutOfHandles);
1236 };
1237 next_handle.drop_in_place();
1238 self.next_handle += 1;
1239 Ok(())
1240 }
1241}
1242
1243impl<T: Timeline + 'static, D: ResourceDialect> Decode<Self, D> for Instant<T> {
1244 #[inline(always)]
1245 fn new_empty() -> Self {
1246 Instant::ZERO
1247 }
1248
1249 #[inline]
1250 unsafe fn decode(
1251 &mut self,
1252 decoder: &mut Decoder<'_, D>,
1253 offset: usize,
1254 _depth: Depth,
1255 ) -> Result<()> {
1256 decoder.debug_check_bounds::<Self>(offset);
1257 *self = Self::from_nanos(decoder.read_num(offset));
1258 Ok(())
1259 }
1260}
1261
1262impl<T: Timeline + 'static, D: ResourceDialect> Decode<Self, D> for Ticks<T> {
1263 #[inline(always)]
1264 fn new_empty() -> Self {
1265 Ticks::<T>::ZERO
1266 }
1267
1268 #[inline]
1269 unsafe fn decode(
1270 &mut self,
1271 decoder: &mut Decoder<'_, D>,
1272 offset: usize,
1273 _depth: Depth,
1274 ) -> Result<()> {
1275 decoder.debug_check_bounds::<Self>(offset);
1276 *self = Self::from_raw(decoder.read_num(offset));
1277 Ok(())
1278 }
1279}
1280
1281pub struct Ambiguous1;
1292
1293pub struct Ambiguous2;
1296
1297pub enum AmbiguousNever {}
1300
1301macro_rules! impl_ambiguous {
1302 ($ambiguous:ident) => {
1303 unsafe impl TypeMarker for $ambiguous {
1304 type Owned = AmbiguousNever;
1305
1306 fn inline_align(_context: Context) -> usize {
1307 panic!("reached code for fake ambiguous type");
1308 }
1309
1310 fn inline_size(_context: Context) -> usize {
1311 panic!("reached code for fake ambiguous type");
1312 }
1313 }
1314
1315 impl ValueTypeMarker for $ambiguous {
1316 type Borrowed<'a> = AmbiguousNever;
1317
1318 fn borrow(value: &<Self as TypeMarker>::Owned) -> Self::Borrowed<'_> {
1319 match *value {}
1320 }
1321 }
1322
1323 impl ResourceTypeMarker for $ambiguous {
1324 type Borrowed<'a> = AmbiguousNever;
1325 fn take_or_borrow(value: &mut <Self as TypeMarker>::Owned) -> Self::Borrowed<'_>
1326 where
1327 Self: TypeMarker,
1328 {
1329 match *value {}
1330 }
1331 }
1332
1333 unsafe impl<T, D: ResourceDialect> Encode<$ambiguous, D> for T {
1334 unsafe fn encode(
1335 self,
1336 _encoder: &mut Encoder<'_, D>,
1337 _offset: usize,
1338 _depth: Depth,
1339 ) -> Result<()> {
1340 panic!("reached code for fake ambiguous type");
1341 }
1342 }
1343
1344 impl<D: ResourceDialect> Decode<$ambiguous, D> for AmbiguousNever {
1347 fn new_empty() -> Self {
1348 panic!("reached code for fake ambiguous type");
1349 }
1350
1351 unsafe fn decode(
1352 &mut self,
1353 _decoder: &mut Decoder<'_, D>,
1354 _offset: usize,
1355 _depth: Depth,
1356 ) -> Result<()> {
1357 match *self {}
1358 }
1359 }
1360 };
1361}
1362
1363impl_ambiguous!(Ambiguous1);
1364impl_ambiguous!(Ambiguous2);
1365
1366pub struct EmptyPayload;
1372
1373unsafe impl TypeMarker for EmptyPayload {
1374 type Owned = ();
1375 #[inline(always)]
1376 fn inline_align(_context: Context) -> usize {
1377 1
1378 }
1379
1380 #[inline(always)]
1381 fn inline_size(_context: Context) -> usize {
1382 0
1383 }
1384}
1385
1386impl ValueTypeMarker for EmptyPayload {
1387 type Borrowed<'a> = ();
1388 #[inline(always)]
1389 fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
1390 *value
1391 }
1392}
1393
1394unsafe impl<D: ResourceDialect> Encode<EmptyPayload, D> for () {
1395 #[inline(always)]
1396 unsafe fn encode(
1397 self,
1398 _encoder: &mut Encoder<'_, D>,
1399 _offset: usize,
1400 _depth: Depth,
1401 ) -> Result<()> {
1402 Ok(())
1403 }
1404}
1405
1406impl<D: ResourceDialect> Decode<EmptyPayload, D> for () {
1407 #[inline(always)]
1408 fn new_empty() -> Self {}
1409
1410 #[inline(always)]
1411 unsafe fn decode(
1412 &mut self,
1413 _decoder: &mut Decoder<'_, D>,
1414 _offset: usize,
1415 _depth: Depth,
1416 ) -> Result<()> {
1417 Ok(())
1418 }
1419}
1420
1421pub struct EmptyStruct;
1424
1425unsafe impl TypeMarker for EmptyStruct {
1426 type Owned = ();
1427 #[inline(always)]
1428 fn inline_align(_context: Context) -> usize {
1429 1
1430 }
1431
1432 #[inline(always)]
1433 fn inline_size(_context: Context) -> usize {
1434 1
1435 }
1436}
1437
1438impl ValueTypeMarker for EmptyStruct {
1439 type Borrowed<'a> = ();
1440 #[inline(always)]
1441 fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
1442 *value
1443 }
1444}
1445
1446unsafe impl<D: ResourceDialect> Encode<EmptyStruct, D> for () {
1447 #[inline]
1448 unsafe fn encode(
1449 self,
1450 encoder: &mut Encoder<'_, D>,
1451 offset: usize,
1452 _depth: Depth,
1453 ) -> Result<()> {
1454 encoder.debug_check_bounds::<EmptyStruct>(offset);
1455 unsafe { encoder.write_num(0u8, offset) };
1456 Ok(())
1457 }
1458}
1459
1460impl<D: ResourceDialect> Decode<EmptyStruct, D> for () {
1461 #[inline(always)]
1462 fn new_empty() -> Self {}
1463
1464 #[inline]
1465 unsafe fn decode(
1466 &mut self,
1467 decoder: &mut Decoder<'_, D>,
1468 offset: usize,
1469 _depth: Depth,
1470 ) -> Result<()> {
1471 decoder.debug_check_bounds::<EmptyStruct>(offset);
1472 match decoder.read_num::<u8>(offset) {
1473 0 => Ok(()),
1474 _ => Err(Error::Invalid),
1475 }
1476 }
1477}
1478
1479mod numeric {
1485 use super::*;
1486
1487 pub trait Numeric {}
1489
1490 macro_rules! impl_numeric {
1493 ($numeric_ty:ty) => {
1494 impl Numeric for $numeric_ty {}
1495
1496 unsafe impl TypeMarker for $numeric_ty {
1497 type Owned = $numeric_ty;
1498 #[inline(always)]
1499 fn inline_align(_context: Context) -> usize {
1500 mem::align_of::<$numeric_ty>()
1501 }
1502
1503 #[inline(always)]
1504 fn inline_size(_context: Context) -> usize {
1505 mem::size_of::<$numeric_ty>()
1506 }
1507
1508 #[inline(always)]
1509 fn encode_is_copy() -> bool {
1510 true
1511 }
1512
1513 #[inline(always)]
1514 fn decode_is_copy() -> bool {
1515 true
1516 }
1517 }
1518
1519 impl ValueTypeMarker for $numeric_ty {
1520 type Borrowed<'a> = $numeric_ty;
1521
1522 #[inline(always)]
1523 fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
1524 *value
1525 }
1526 }
1527
1528 unsafe impl<D: ResourceDialect> Encode<$numeric_ty, D> for $numeric_ty {
1529 #[inline(always)]
1530 unsafe fn encode(
1531 self,
1532 encoder: &mut Encoder<'_, D>,
1533 offset: usize,
1534 _depth: Depth,
1535 ) -> Result<()> {
1536 encoder.debug_check_bounds::<$numeric_ty>(offset);
1537 unsafe { encoder.write_num::<$numeric_ty>(self, offset) };
1538 Ok(())
1539 }
1540 }
1541
1542 impl<D: ResourceDialect> Decode<$numeric_ty, D> for $numeric_ty {
1543 #[inline(always)]
1544 fn new_empty() -> Self {
1545 0 as $numeric_ty
1546 }
1547
1548 #[inline(always)]
1549 unsafe fn decode(
1550 &mut self,
1551 decoder: &mut Decoder<'_, D>,
1552 offset: usize,
1553 _depth: Depth,
1554 ) -> Result<()> {
1555 decoder.debug_check_bounds::<$numeric_ty>(offset);
1556 *self = decoder.read_num::<$numeric_ty>(offset);
1557 Ok(())
1558 }
1559 }
1560 };
1561 }
1562
1563 impl_numeric!(u8);
1564 impl_numeric!(u16);
1565 impl_numeric!(u32);
1566 impl_numeric!(u64);
1567 impl_numeric!(i8);
1568 impl_numeric!(i16);
1569 impl_numeric!(i32);
1570 impl_numeric!(i64);
1571 impl_numeric!(f32);
1572 impl_numeric!(f64);
1573}
1574
1575unsafe impl TypeMarker for bool {
1576 type Owned = bool;
1577
1578 #[inline(always)]
1579 fn inline_align(_context: Context) -> usize {
1580 mem::align_of::<bool>()
1581 }
1582
1583 #[inline(always)]
1584 fn inline_size(_context: Context) -> usize {
1585 mem::size_of::<bool>()
1586 }
1587
1588 #[inline(always)]
1589 fn encode_is_copy() -> bool {
1590 true
1593 }
1594
1595 #[inline(always)]
1596 fn decode_is_copy() -> bool {
1597 false
1599 }
1600}
1601
1602impl ValueTypeMarker for bool {
1603 type Borrowed<'a> = bool;
1604
1605 #[inline(always)]
1606 fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
1607 *value
1608 }
1609}
1610
1611unsafe impl<D: ResourceDialect> Encode<bool, D> for bool {
1612 #[inline]
1613 unsafe fn encode(
1614 self,
1615 encoder: &mut Encoder<'_, D>,
1616 offset: usize,
1617 _depth: Depth,
1618 ) -> Result<()> {
1619 encoder.debug_check_bounds::<bool>(offset);
1620 unsafe { encoder.write_num(self as u8, offset) };
1623 Ok(())
1624 }
1625}
1626
1627impl<D: ResourceDialect> Decode<bool, D> for bool {
1628 #[inline(always)]
1629 fn new_empty() -> Self {
1630 false
1631 }
1632
1633 #[inline]
1634 unsafe fn decode(
1635 &mut self,
1636 decoder: &mut Decoder<'_, D>,
1637 offset: usize,
1638 _depth: Depth,
1639 ) -> Result<()> {
1640 decoder.debug_check_bounds::<bool>(offset);
1641 *self = match unsafe { *decoder.buf.get_unchecked(offset) } {
1643 0 => false,
1644 1 => true,
1645 _ => return Err(Error::InvalidBoolean),
1646 };
1647 Ok(())
1648 }
1649}
1650
1651pub struct Array<T: TypeMarker, const N: usize>(PhantomData<T>);
1657
1658unsafe impl<T: TypeMarker, const N: usize> TypeMarker for Array<T, N> {
1659 type Owned = [T::Owned; N];
1660 #[inline(always)]
1661 fn inline_align(context: Context) -> usize {
1662 T::inline_align(context)
1663 }
1664
1665 #[inline(always)]
1666 fn inline_size(context: Context) -> usize {
1667 N * T::inline_size(context)
1668 }
1669
1670 #[inline(always)]
1671 fn encode_is_copy() -> bool {
1672 T::encode_is_copy()
1673 }
1674
1675 #[inline(always)]
1676 fn decode_is_copy() -> bool {
1677 T::decode_is_copy()
1678 }
1679}
1680
1681impl<T: ValueTypeMarker, const N: usize> ValueTypeMarker for Array<T, N> {
1682 type Borrowed<'a> = &'a [T::Owned; N];
1683 #[inline(always)]
1684 fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
1685 value
1686 }
1687}
1688
1689impl<T: ResourceTypeMarker, const N: usize> ResourceTypeMarker for Array<T, N> {
1690 type Borrowed<'a> = &'a mut [T::Owned; N];
1691 #[inline(always)]
1692 fn take_or_borrow(value: &mut <Self as TypeMarker>::Owned) -> Self::Borrowed<'_> {
1693 value
1694 }
1695}
1696
1697unsafe impl<T: ValueTypeMarker, const N: usize, D: ResourceDialect> Encode<Array<T, N>, D>
1698 for &[T::Owned; N]
1699where
1700 for<'q> T::Borrowed<'q>: Encode<T, D>,
1701{
1702 #[inline]
1703 unsafe fn encode(
1704 self,
1705 encoder: &mut Encoder<'_, D>,
1706 offset: usize,
1707 depth: Depth,
1708 ) -> Result<()> {
1709 encoder.debug_check_bounds::<Array<T, N>>(offset);
1710 unsafe { encode_array_value::<T, D>(self, encoder, offset, depth) }
1711 }
1712}
1713
1714unsafe impl<T: ResourceTypeMarker, const N: usize, D: ResourceDialect> Encode<Array<T, N>, D>
1715 for &mut [<T as TypeMarker>::Owned; N]
1716where
1717 for<'q> T::Borrowed<'q>: Encode<T, D>,
1718{
1719 #[inline]
1720 unsafe fn encode(
1721 self,
1722 encoder: &mut Encoder<'_, D>,
1723 offset: usize,
1724 depth: Depth,
1725 ) -> Result<()> {
1726 encoder.debug_check_bounds::<Array<T, N>>(offset);
1727 unsafe { encode_array_resource::<T, D>(self, encoder, offset, depth) }
1728 }
1729}
1730
1731impl<T: TypeMarker, const N: usize, D: ResourceDialect> Decode<Array<T, N>, D> for [T::Owned; N]
1732where
1733 T::Owned: Decode<T, D>,
1734{
1735 #[inline]
1736 fn new_empty() -> Self {
1737 let mut arr = mem::MaybeUninit::<[T::Owned; N]>::uninit();
1738 unsafe {
1739 let arr_ptr = arr.as_mut_ptr() as *mut T::Owned;
1740 for i in 0..N {
1741 ptr::write(arr_ptr.add(i), T::Owned::new_empty());
1742 }
1743 arr.assume_init()
1744 }
1745 }
1746
1747 #[inline]
1748 unsafe fn decode(
1749 &mut self,
1750 decoder: &mut Decoder<'_, D>,
1751 offset: usize,
1752 depth: Depth,
1753 ) -> Result<()> {
1754 decoder.debug_check_bounds::<Array<T, N>>(offset);
1755 unsafe { decode_array::<T, D>(self, decoder, offset, depth) }
1756 }
1757}
1758
1759#[inline]
1760unsafe fn encode_array_value<T: ValueTypeMarker, D: ResourceDialect>(
1761 slice: &[T::Owned],
1762 encoder: &mut Encoder<'_, D>,
1763 offset: usize,
1764 depth: Depth,
1765) -> Result<()>
1766where
1767 for<'a> T::Borrowed<'a>: Encode<T, D>,
1768{
1769 let stride = T::inline_size(encoder.context);
1770 let len = slice.len();
1771 debug_assert_ne!(len, 0);
1773 if T::encode_is_copy() {
1774 debug_assert_eq!(stride, mem::size_of::<T::Owned>());
1775 unsafe {
1782 let src = slice.as_ptr() as *const u8;
1783 let dst: *mut u8 = encoder.buf.as_mut_ptr().add(offset);
1784 ptr::copy_nonoverlapping(src, dst, len * stride);
1785 }
1786 } else {
1787 for i in 0..len {
1788 let item = unsafe { slice.get_unchecked(i) };
1790 unsafe { T::borrow(item).encode(encoder, offset + i * stride, depth)? };
1791 }
1792 }
1793 Ok(())
1794}
1795
1796#[inline]
1797unsafe fn encode_array_resource<T: ResourceTypeMarker + TypeMarker, D: ResourceDialect>(
1798 slice: &mut [T::Owned],
1799 encoder: &mut Encoder<'_, D>,
1800 offset: usize,
1801 depth: Depth,
1802) -> Result<()>
1803where
1804 for<'a> T::Borrowed<'a>: Encode<T, D>,
1805{
1806 let stride = T::inline_size(encoder.context);
1807 let len = slice.len();
1808 debug_assert_ne!(len, 0);
1810 if T::encode_is_copy() {
1811 debug_assert_eq!(stride, mem::size_of::<T::Owned>());
1812 unsafe {
1819 let src = slice.as_ptr() as *const u8;
1820 let dst: *mut u8 = encoder.buf.as_mut_ptr().add(offset);
1821 ptr::copy_nonoverlapping(src, dst, len * stride);
1822 }
1823 } else {
1824 for i in 0..len {
1825 let item = unsafe { slice.get_unchecked_mut(i) };
1827 unsafe { T::take_or_borrow(item).encode(encoder, offset + i * stride, depth)? };
1828 }
1829 }
1830 Ok(())
1831}
1832
1833#[inline]
1834unsafe fn decode_array<T: TypeMarker, D: ResourceDialect>(
1835 slice: &mut [T::Owned],
1836 decoder: &mut Decoder<'_, D>,
1837 offset: usize,
1838 depth: Depth,
1839) -> Result<()>
1840where
1841 T::Owned: Decode<T, D>,
1842{
1843 let stride = T::inline_size(decoder.context);
1844 let len = slice.len();
1845 debug_assert_ne!(len, 0);
1847 if T::decode_is_copy() {
1848 debug_assert_eq!(stride, mem::size_of::<T::Owned>());
1849 unsafe {
1856 let src: *const u8 = decoder.buf.as_ptr().add(offset);
1857 let dst = slice.as_mut_ptr() as *mut u8;
1858 ptr::copy_nonoverlapping(src, dst, len * stride);
1859 }
1860 } else {
1861 for i in 0..len {
1862 let item = unsafe { slice.get_unchecked_mut(i) };
1864 unsafe { item.decode(decoder, offset + i * stride, depth)? };
1865 }
1866 }
1867 Ok(())
1868}
1869
1870pub const MAX_BOUND: usize = usize::MAX;
1876
1877pub struct Vector<T: TypeMarker, const N: usize>(PhantomData<T>);
1879
1880pub type UnboundedVector<T> = Vector<T, MAX_BOUND>;
1882
1883unsafe impl<T: TypeMarker, const N: usize> TypeMarker for Vector<T, N> {
1884 type Owned = Vec<T::Owned>;
1885
1886 #[inline(always)]
1887 fn inline_align(_context: Context) -> usize {
1888 8
1889 }
1890
1891 #[inline(always)]
1892 fn inline_size(_context: Context) -> usize {
1893 16
1894 }
1895}
1896
1897impl<T: ValueTypeMarker, const N: usize> ValueTypeMarker for Vector<T, N> {
1898 type Borrowed<'a> = &'a [T::Owned];
1899 #[inline(always)]
1900 fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
1901 value
1902 }
1903}
1904
1905impl<T: ResourceTypeMarker, const N: usize> ResourceTypeMarker for Vector<T, N> {
1906 type Borrowed<'a> = &'a mut [T::Owned];
1907 #[inline(always)]
1908 fn take_or_borrow(value: &mut <Self as TypeMarker>::Owned) -> Self::Borrowed<'_> {
1909 value.as_mut_slice()
1910 }
1911}
1912
1913unsafe impl<T: ValueTypeMarker, const N: usize, D: ResourceDialect> Encode<Vector<T, N>, D>
1914 for &[<T as TypeMarker>::Owned]
1915where
1916 for<'q> T::Borrowed<'q>: Encode<T, D>,
1917{
1918 #[inline]
1919 unsafe fn encode(
1920 self,
1921 encoder: &mut Encoder<'_, D>,
1922 offset: usize,
1923 depth: Depth,
1924 ) -> Result<()> {
1925 encoder.debug_check_bounds::<Vector<T, N>>(offset);
1926 unsafe { encode_vector_value::<T, D>(self, N, check_vector_length, encoder, offset, depth) }
1927 }
1928}
1929
1930unsafe impl<T: ResourceTypeMarker + TypeMarker, const N: usize, D: ResourceDialect>
1931 Encode<Vector<T, N>, D> for &mut [<T as TypeMarker>::Owned]
1932where
1933 for<'q> T::Borrowed<'q>: Encode<T, D>,
1934{
1935 #[inline]
1936 unsafe fn encode(
1937 self,
1938 encoder: &mut Encoder<'_, D>,
1939 offset: usize,
1940 depth: Depth,
1941 ) -> Result<()> {
1942 encoder.debug_check_bounds::<Vector<T, N>>(offset);
1943 unsafe { encode_vector_resource::<T, D>(self, N, encoder, offset, depth) }
1944 }
1945}
1946
1947impl<T: TypeMarker, const N: usize, D: ResourceDialect> Decode<Vector<T, N>, D> for Vec<T::Owned>
1948where
1949 T::Owned: Decode<T, D>,
1950{
1951 #[inline(always)]
1952 fn new_empty() -> Self {
1953 Vec::new()
1954 }
1955
1956 #[inline]
1957 unsafe fn decode(
1958 &mut self,
1959 decoder: &mut Decoder<'_, D>,
1960 offset: usize,
1961 depth: Depth,
1962 ) -> Result<()> {
1963 decoder.debug_check_bounds::<Vector<T, N>>(offset);
1964 unsafe { decode_vector::<T, D>(self, N, decoder, offset, depth) }
1965 }
1966}
1967
1968#[inline]
1969unsafe fn encode_vector_value<T: ValueTypeMarker, D: ResourceDialect>(
1970 slice: &[<T as TypeMarker>::Owned],
1971 max_length: usize,
1972 check_length: impl Fn(usize, usize) -> Result<()>,
1973 encoder: &mut Encoder<'_, D>,
1974 offset: usize,
1975 mut depth: Depth,
1976) -> Result<()>
1977where
1978 for<'a> T::Borrowed<'a>: Encode<T, D>,
1979{
1980 unsafe { encoder.write_num(slice.len() as u64, offset) };
1981 unsafe { encoder.write_num(fidl_constants::ALLOC_PRESENT_U64, offset + 8) };
1982 if slice.is_empty() {
1984 return Ok(());
1985 }
1986 check_length(slice.len(), max_length)?;
1987 depth.increment()?;
1988 let bytes_len = slice.len() * T::inline_size(encoder.context);
1989 let offset = unsafe { encoder.out_of_line_offset(bytes_len) };
1990 unsafe { encode_array_value::<T, D>(slice, encoder, offset, depth) }
1991}
1992
1993#[inline]
1994unsafe fn encode_vector_resource<T: ResourceTypeMarker + TypeMarker, D: ResourceDialect>(
1995 slice: &mut [T::Owned],
1996 max_length: usize,
1997 encoder: &mut Encoder<'_, D>,
1998 offset: usize,
1999 mut depth: Depth,
2000) -> Result<()>
2001where
2002 for<'a> T::Borrowed<'a>: Encode<T, D>,
2003{
2004 unsafe { encoder.write_num(slice.len() as u64, offset) };
2005 unsafe { encoder.write_num(ALLOC_PRESENT_U64, offset + 8) };
2006 if slice.is_empty() {
2008 return Ok(());
2009 }
2010 check_vector_length(slice.len(), max_length)?;
2011 depth.increment()?;
2012 let bytes_len = slice.len() * T::inline_size(encoder.context);
2013 let offset = unsafe { encoder.out_of_line_offset(bytes_len) };
2014 unsafe { encode_array_resource::<T, D>(slice, encoder, offset, depth) }
2015}
2016
2017#[inline]
2018unsafe fn decode_vector<T: TypeMarker, D: ResourceDialect>(
2019 vec: &mut Vec<T::Owned>,
2020 max_length: usize,
2021 decoder: &mut Decoder<'_, D>,
2022 offset: usize,
2023 mut depth: Depth,
2024) -> Result<()>
2025where
2026 T::Owned: Decode<T, D>,
2027{
2028 let Some(len) = decode_vector_header(decoder, offset)? else {
2029 return Err(Error::NotNullable);
2030 };
2031 if len == 0 {
2033 return Ok(());
2034 }
2035 check_vector_length(len, max_length)?;
2036 depth.increment()?;
2037 let bytes_len = len * T::inline_size(decoder.context);
2038 let offset = unsafe { decoder.out_of_line_offset(bytes_len)? };
2039 if T::decode_is_copy() {
2040 unsafe {
2043 resize_vec_no_zeroing(vec, len);
2044 }
2045 } else {
2046 vec.resize_with(len, T::Owned::new_empty);
2047 }
2048 unsafe { decode_array::<T, D>(vec, decoder, offset, depth)? };
2050 Ok(())
2051}
2052
2053#[doc(hidden)] #[inline]
2057pub fn decode_vector_header<D: ResourceDialect>(
2058 decoder: &mut Decoder<'_, D>,
2059 offset: usize,
2060) -> Result<Option<usize>> {
2061 let len = decoder.read_num::<u64>(offset) as usize;
2062 match decoder.read_num::<u64>(offset + 8) {
2063 ALLOC_PRESENT_U64 => {
2064 if len <= u32::MAX as usize && len <= decoder.buf.len() {
2068 Ok(Some(len))
2069 } else {
2070 Err(Error::OutOfRange { expected: len, actual: decoder.buf.len() })
2071 }
2072 }
2073 ALLOC_ABSENT_U64 => {
2074 if len == 0 {
2075 Ok(None)
2076 } else {
2077 Err(Error::UnexpectedNullRef)
2078 }
2079 }
2080 _ => Err(Error::InvalidPresenceIndicator),
2081 }
2082}
2083
2084#[inline(always)]
2085fn check_vector_length(actual_length: usize, max_length: usize) -> Result<()> {
2086 if actual_length > max_length {
2087 return Err(Error::VectorTooLong { max_length, actual_length });
2088 }
2089 Ok(())
2090}
2091
2092pub struct BoundedString<const N: usize>;
2098
2099pub type UnboundedString = BoundedString<MAX_BOUND>;
2101
2102unsafe impl<const N: usize> TypeMarker for BoundedString<N> {
2103 type Owned = String;
2104
2105 #[inline(always)]
2106 fn inline_align(_context: Context) -> usize {
2107 8
2108 }
2109
2110 #[inline(always)]
2111 fn inline_size(_context: Context) -> usize {
2112 16
2113 }
2114}
2115
2116impl<const N: usize> ValueTypeMarker for BoundedString<N> {
2117 type Borrowed<'a> = &'a str;
2118 #[inline(always)]
2119 fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
2120 value
2121 }
2122}
2123
2124unsafe impl<const N: usize, D: ResourceDialect> Encode<BoundedString<N>, D> for &str {
2125 #[inline]
2126 unsafe fn encode(
2127 self,
2128 encoder: &mut Encoder<'_, D>,
2129 offset: usize,
2130 depth: Depth,
2131 ) -> Result<()> {
2132 encoder.debug_check_bounds::<BoundedString<N>>(offset);
2133 unsafe {
2134 encode_vector_value::<u8, D>(
2135 self.as_bytes(),
2136 N,
2137 check_string_length,
2138 encoder,
2139 offset,
2140 depth,
2141 )
2142 }
2143 }
2144}
2145
2146impl<const N: usize, D: ResourceDialect> Decode<BoundedString<N>, D> for String {
2147 #[inline(always)]
2148 fn new_empty() -> Self {
2149 String::new()
2150 }
2151
2152 #[inline]
2153 unsafe fn decode(
2154 &mut self,
2155 decoder: &mut Decoder<'_, D>,
2156 offset: usize,
2157 depth: Depth,
2158 ) -> Result<()> {
2159 decoder.debug_check_bounds::<BoundedString<N>>(offset);
2160 decode_string(self, N, decoder, offset, depth)
2161 }
2162}
2163
2164#[inline]
2165fn decode_string<D: ResourceDialect>(
2166 string: &mut String,
2167 max_length: usize,
2168 decoder: &mut Decoder<'_, D>,
2169 offset: usize,
2170 mut depth: Depth,
2171) -> Result<()> {
2172 let Some(len) = decode_vector_header(decoder, offset)? else {
2173 return Err(Error::NotNullable);
2174 };
2175 if len == 0 {
2177 return Ok(());
2178 }
2179 check_string_length(len, max_length)?;
2180 depth.increment()?;
2181 let offset = unsafe { decoder.out_of_line_offset(len)? };
2183 let bytes = unsafe { &decoder.buf.get_unchecked(offset..offset + len) };
2185 let utf8 = str::from_utf8(bytes).map_err(|_| Error::Utf8Error)?;
2186 let boxed_utf8: Box<str> = utf8.into();
2187 *string = boxed_utf8.into_string();
2188 Ok(())
2189}
2190
2191#[inline(always)]
2192fn check_string_length(actual_bytes: usize, max_bytes: usize) -> Result<()> {
2193 if actual_bytes > max_bytes {
2194 return Err(Error::StringTooLong { max_bytes, actual_bytes });
2195 }
2196 Ok(())
2197}
2198
2199impl<T: From<NullableHandle> + Into<NullableHandle>> EncodableAsHandle for T {
2204 type Dialect = DefaultFuchsiaResourceDialect;
2205}
2206
2207pub struct HandleType<T: EncodableAsHandle, const OBJECT_TYPE: u32, const RIGHTS: u32>(
2209 PhantomData<T>,
2210);
2211
2212pub type Endpoint<T> = HandleType<
2215 T,
2216 { crate::ObjectType::CHANNEL.into_raw() },
2217 { crate::Rights::CHANNEL_DEFAULT.bits() },
2218>;
2219
2220unsafe impl<T: 'static + EncodableAsHandle, const OBJECT_TYPE: u32, const RIGHTS: u32> TypeMarker
2221 for HandleType<T, OBJECT_TYPE, RIGHTS>
2222{
2223 type Owned = T;
2224
2225 #[inline(always)]
2226 fn inline_align(_context: Context) -> usize {
2227 4
2228 }
2229
2230 #[inline(always)]
2231 fn inline_size(_context: Context) -> usize {
2232 4
2233 }
2234}
2235
2236impl<T: 'static + EncodableAsHandle, const OBJECT_TYPE: u32, const RIGHTS: u32> ResourceTypeMarker
2237 for HandleType<T, OBJECT_TYPE, RIGHTS>
2238{
2239 type Borrowed<'a> = T;
2240 #[inline(always)]
2241 fn take_or_borrow(value: &mut <Self as TypeMarker>::Owned) -> Self::Borrowed<'_> {
2242 mem::replace(value, <T::Dialect as ResourceDialect>::Handle::invalid().into())
2243 }
2244}
2245
2246unsafe impl<T: 'static + EncodableAsHandle, const OBJECT_TYPE: u32, const RIGHTS: u32>
2247 Encode<HandleType<T, OBJECT_TYPE, RIGHTS>, T::Dialect> for T
2248{
2249 #[inline]
2250 unsafe fn encode(
2251 self,
2252 encoder: &mut Encoder<'_, T::Dialect>,
2253 offset: usize,
2254 _depth: Depth,
2255 ) -> Result<()> {
2256 encoder.debug_check_bounds::<HandleType<T, OBJECT_TYPE, RIGHTS>>(offset);
2257 unsafe {
2258 encode_handle(
2259 self.into(),
2260 crate::ObjectType::from_raw(OBJECT_TYPE),
2261 crate::Rights::from_bits_retain(RIGHTS),
2262 encoder,
2263 offset,
2264 )
2265 }
2266 }
2267}
2268
2269impl<T: 'static + EncodableAsHandle, const OBJECT_TYPE: u32, const RIGHTS: u32>
2270 Decode<HandleType<T, OBJECT_TYPE, RIGHTS>, T::Dialect> for T
2271{
2272 #[inline(always)]
2273 fn new_empty() -> Self {
2274 <T::Dialect as ResourceDialect>::Handle::invalid().into()
2275 }
2276
2277 #[inline]
2278 unsafe fn decode(
2279 &mut self,
2280 decoder: &mut Decoder<'_, T::Dialect>,
2281 offset: usize,
2282 _depth: Depth,
2283 ) -> Result<()> {
2284 decoder.debug_check_bounds::<HandleType<T, OBJECT_TYPE, RIGHTS>>(offset);
2285 *self = unsafe {
2286 decode_handle(
2287 crate::ObjectType::from_raw(OBJECT_TYPE),
2288 crate::Rights::from_bits_retain(RIGHTS),
2289 decoder,
2290 offset,
2291 )?
2292 }
2293 .into();
2294 Ok(())
2295 }
2296}
2297
2298#[inline]
2299unsafe fn encode_handle<D: ResourceDialect>(
2300 handle: D::Handle,
2301 object_type: crate::ObjectType,
2302 rights: crate::Rights,
2303 encoder: &mut Encoder<'_, D>,
2304 offset: usize,
2305) -> Result<()> {
2306 if handle.is_invalid() {
2307 return Err(Error::NotNullable);
2308 }
2309 unsafe { encoder.write_num(ALLOC_PRESENT_U32, offset) };
2310 encoder.handles.push(<D::ProxyChannel as ProxyChannelFor<D>>::HandleDisposition::from_handle(
2311 handle,
2312 object_type,
2313 rights,
2314 ));
2315 Ok(())
2316}
2317
2318#[inline]
2319unsafe fn decode_handle<D: ResourceDialect>(
2320 object_type: crate::ObjectType,
2321 rights: crate::Rights,
2322 decoder: &mut Decoder<'_, D>,
2323 offset: usize,
2324) -> Result<D::Handle> {
2325 match decoder.read_num::<u32>(offset) {
2326 ALLOC_PRESENT_U32 => {}
2327 ALLOC_ABSENT_U32 => return Err(Error::NotNullable),
2328 _ => return Err(Error::InvalidPresenceIndicator),
2329 }
2330 decoder.take_next_handle(object_type, rights)
2331}
2332
2333pub struct Optional<T: TypeMarker>(PhantomData<T>);
2339
2340pub struct OptionalUnion<T: TypeMarker>(PhantomData<T>);
2342
2343pub struct Boxed<T: TypeMarker>(PhantomData<T>);
2345
2346unsafe impl<T: TypeMarker> TypeMarker for Optional<T> {
2347 type Owned = Option<T::Owned>;
2348
2349 #[inline(always)]
2350 fn inline_align(context: Context) -> usize {
2351 T::inline_align(context)
2352 }
2353
2354 #[inline(always)]
2355 fn inline_size(context: Context) -> usize {
2356 T::inline_size(context)
2357 }
2358}
2359
2360unsafe impl<T: TypeMarker> TypeMarker for OptionalUnion<T> {
2361 type Owned = Option<Box<T::Owned>>;
2362
2363 #[inline(always)]
2364 fn inline_align(context: Context) -> usize {
2365 T::inline_align(context)
2366 }
2367
2368 #[inline(always)]
2369 fn inline_size(context: Context) -> usize {
2370 T::inline_size(context)
2371 }
2372}
2373
2374unsafe impl<T: TypeMarker> TypeMarker for Boxed<T> {
2375 type Owned = Option<Box<T::Owned>>;
2376
2377 #[inline(always)]
2378 fn inline_align(_context: Context) -> usize {
2379 8
2380 }
2381
2382 #[inline(always)]
2383 fn inline_size(_context: Context) -> usize {
2384 8
2385 }
2386}
2387
2388impl<T: ValueTypeMarker> ValueTypeMarker for Optional<T> {
2389 type Borrowed<'a> = Option<T::Borrowed<'a>>;
2390
2391 #[inline(always)]
2392 fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
2393 value.as_ref().map(T::borrow)
2394 }
2395}
2396
2397impl<T: ValueTypeMarker> ValueTypeMarker for OptionalUnion<T> {
2398 type Borrowed<'a> = Option<T::Borrowed<'a>>;
2399
2400 #[inline(always)]
2401 fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
2402 value.as_deref().map(T::borrow)
2403 }
2404}
2405
2406impl<T: ValueTypeMarker> ValueTypeMarker for Boxed<T> {
2407 type Borrowed<'a> = Option<T::Borrowed<'a>>;
2408
2409 #[inline(always)]
2410 fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
2411 value.as_deref().map(T::borrow)
2412 }
2413}
2414
2415impl<T: ResourceTypeMarker + TypeMarker> ResourceTypeMarker for Optional<T> {
2416 type Borrowed<'a> = Option<T::Borrowed<'a>>;
2417 #[inline(always)]
2418 fn take_or_borrow(value: &mut <Self as TypeMarker>::Owned) -> Self::Borrowed<'_> {
2419 value.as_mut().map(T::take_or_borrow)
2420 }
2421}
2422
2423impl<T: ResourceTypeMarker + TypeMarker> ResourceTypeMarker for OptionalUnion<T> {
2424 type Borrowed<'a> = Option<T::Borrowed<'a>>;
2425 #[inline(always)]
2426 fn take_or_borrow(value: &mut <Self as TypeMarker>::Owned) -> Self::Borrowed<'_> {
2427 value.as_deref_mut().map(T::take_or_borrow)
2428 }
2429}
2430
2431impl<T: ResourceTypeMarker + TypeMarker> ResourceTypeMarker for Boxed<T> {
2432 type Borrowed<'a> = Option<T::Borrowed<'a>>;
2433 #[inline(always)]
2434 fn take_or_borrow(value: &mut <Self as TypeMarker>::Owned) -> Self::Borrowed<'_> {
2435 value.as_deref_mut().map(T::take_or_borrow)
2436 }
2437}
2438
2439unsafe impl<T: TypeMarker, E: Encode<T, D>, D: ResourceDialect> Encode<Optional<T>, D>
2440 for Option<E>
2441{
2442 #[inline]
2443 unsafe fn encode(
2444 self,
2445 encoder: &mut Encoder<'_, D>,
2446 offset: usize,
2447 depth: Depth,
2448 ) -> Result<()> {
2449 encoder.debug_check_bounds::<Optional<T>>(offset);
2450 unsafe { encode_naturally_optional::<T, E, D>(self, encoder, offset, depth) }
2451 }
2452}
2453
2454unsafe impl<T: TypeMarker, E: Encode<T, D>, D: ResourceDialect> Encode<OptionalUnion<T>, D>
2455 for Option<E>
2456{
2457 #[inline]
2458 unsafe fn encode(
2459 self,
2460 encoder: &mut Encoder<'_, D>,
2461 offset: usize,
2462 depth: Depth,
2463 ) -> Result<()> {
2464 encoder.debug_check_bounds::<OptionalUnion<T>>(offset);
2465 unsafe { encode_naturally_optional::<T, E, D>(self, encoder, offset, depth) }
2466 }
2467}
2468
2469unsafe impl<T: TypeMarker, E: Encode<T, D>, D: ResourceDialect> Encode<Boxed<T>, D> for Option<E> {
2470 #[inline]
2471 unsafe fn encode(
2472 self,
2473 encoder: &mut Encoder<'_, D>,
2474 offset: usize,
2475 mut depth: Depth,
2476 ) -> Result<()> {
2477 encoder.debug_check_bounds::<Boxed<T>>(offset);
2478 match self {
2479 Some(val) => {
2480 depth.increment()?;
2481 unsafe { encoder.write_num(ALLOC_PRESENT_U64, offset) };
2482 let offset = unsafe { encoder.out_of_line_offset(T::inline_size(encoder.context)) };
2483 unsafe { val.encode(encoder, offset, depth)? };
2484 }
2485 None => unsafe { encoder.write_num(ALLOC_ABSENT_U64, offset) },
2486 }
2487 Ok(())
2488 }
2489}
2490
2491impl<T: TypeMarker, D: ResourceDialect> Decode<Optional<T>, D> for Option<T::Owned>
2492where
2493 T::Owned: Decode<T, D>,
2494{
2495 #[inline(always)]
2496 fn new_empty() -> Self {
2497 None
2498 }
2499
2500 #[inline]
2501 unsafe fn decode(
2502 &mut self,
2503 decoder: &mut Decoder<'_, D>,
2504 offset: usize,
2505 depth: Depth,
2506 ) -> Result<()> {
2507 decoder.debug_check_bounds::<Optional<T>>(offset);
2508 let inline_size = T::inline_size(decoder.context);
2509 if check_for_presence(decoder, offset, inline_size) {
2510 unsafe { self.get_or_insert(T::Owned::new_empty()).decode(decoder, offset, depth) }
2511 } else {
2512 *self = None;
2513 decoder.check_padding(offset, inline_size)?;
2514 Ok(())
2515 }
2516 }
2517}
2518
2519impl<T: TypeMarker, D: ResourceDialect> Decode<OptionalUnion<T>, D> for Option<Box<T::Owned>>
2520where
2521 T::Owned: Decode<T, D>,
2522{
2523 #[inline(always)]
2524 fn new_empty() -> Self {
2525 None
2526 }
2527
2528 #[inline]
2529 unsafe fn decode(
2530 &mut self,
2531 decoder: &mut Decoder<'_, D>,
2532 offset: usize,
2533 depth: Depth,
2534 ) -> Result<()> {
2535 decoder.debug_check_bounds::<OptionalUnion<T>>(offset);
2536 let inline_size = T::inline_size(decoder.context);
2537 if check_for_presence(decoder, offset, inline_size) {
2538 unsafe {
2539 decode!(
2540 T,
2541 self.get_or_insert_with(|| Box::new(T::Owned::new_empty())),
2542 decoder,
2543 offset,
2544 depth
2545 )
2546 }
2547 } else {
2548 *self = None;
2549 decoder.check_padding(offset, inline_size)?;
2550 Ok(())
2551 }
2552 }
2553}
2554
2555impl<T: TypeMarker, D: ResourceDialect> Decode<Boxed<T>, D> for Option<Box<T::Owned>>
2556where
2557 T::Owned: Decode<T, D>,
2558{
2559 #[inline(always)]
2560 fn new_empty() -> Self {
2561 None
2562 }
2563
2564 #[inline]
2565 unsafe fn decode(
2566 &mut self,
2567 decoder: &mut Decoder<'_, D>,
2568 offset: usize,
2569 mut depth: Depth,
2570 ) -> Result<()> {
2571 decoder.debug_check_bounds::<Boxed<T>>(offset);
2572 match decoder.read_num::<u64>(offset) {
2573 ALLOC_PRESENT_U64 => {
2574 depth.increment()?;
2575 let offset =
2576 unsafe { decoder.out_of_line_offset(T::inline_size(decoder.context))? };
2577 unsafe {
2578 decode!(
2579 T,
2580 self.get_or_insert_with(|| Box::new(T::Owned::new_empty())),
2581 decoder,
2582 offset,
2583 depth
2584 )?
2585 };
2586 Ok(())
2587 }
2588 ALLOC_ABSENT_U64 => {
2589 *self = None;
2590 Ok(())
2591 }
2592 _ => Err(Error::InvalidPresenceIndicator),
2593 }
2594 }
2595}
2596
2597#[inline]
2600unsafe fn encode_naturally_optional<T: TypeMarker, E: Encode<T, D>, D: ResourceDialect>(
2601 value: Option<E>,
2602 encoder: &mut Encoder<'_, D>,
2603 offset: usize,
2604 depth: Depth,
2605) -> Result<()> {
2606 match value {
2607 Some(val) => unsafe { val.encode(encoder, offset, depth)? },
2608 None => unsafe { encoder.padding(offset, T::inline_size(encoder.context)) },
2609 }
2610 Ok(())
2611}
2612
2613#[inline]
2617fn check_for_presence<D: ResourceDialect>(
2618 decoder: &Decoder<'_, D>,
2619 offset: usize,
2620 inline_size: usize,
2621) -> bool {
2622 debug_assert!(offset + inline_size <= decoder.buf.len());
2623 let range = unsafe { decoder.buf.get_unchecked(offset..offset + inline_size) };
2624 range.iter().any(|byte| *byte != 0)
2625}
2626
2627#[doc(hidden)] #[inline]
2633pub unsafe fn encode_in_envelope<T: TypeMarker, D: ResourceDialect>(
2634 val: impl Encode<T, D>,
2635 encoder: &mut Encoder<'_, D>,
2636 offset: usize,
2637 mut depth: Depth,
2638) -> Result<()> {
2639 depth.increment()?;
2640 let bytes_before = encoder.buf.len();
2641 let handles_before = encoder.handles.len();
2642 let inline_size = T::inline_size(encoder.context);
2643 if inline_size <= 4 {
2644 unsafe { encoder.write_num(1u64 << 48, offset) };
2646 unsafe { val.encode(encoder, offset, depth)? };
2647 let handles_written = (encoder.handles.len() - handles_before) as u16;
2648 unsafe { encoder.write_num(handles_written, offset + 4) };
2649 } else {
2650 let out_of_line_offset = unsafe { encoder.out_of_line_offset(inline_size) };
2651 unsafe { val.encode(encoder, out_of_line_offset, depth)? };
2652 let bytes_written = (encoder.buf.len() - bytes_before) as u32;
2653 let handles_written = (encoder.handles.len() - handles_before) as u32;
2654 debug_assert_eq!(bytes_written % 8, 0);
2655 unsafe { encoder.write_num(bytes_written, offset) };
2656 unsafe { encoder.write_num(handles_written, offset + 4) };
2657 }
2658 Ok(())
2659}
2660
2661#[doc(hidden)] #[inline]
2663pub unsafe fn encode_in_envelope_optional<T: TypeMarker, D: ResourceDialect>(
2664 val: Option<impl Encode<T, D>>,
2665 encoder: &mut Encoder<'_, D>,
2666 offset: usize,
2667 depth: Depth,
2668) -> Result<()> {
2669 match val {
2670 None => unsafe { encoder.write_num(0u64, offset) },
2671 Some(val) => unsafe { encode_in_envelope(val, encoder, offset, depth)? },
2672 }
2673 Ok(())
2674}
2675
2676#[doc(hidden)] #[inline(always)]
2680pub unsafe fn decode_envelope_header<D: ResourceDialect>(
2681 decoder: &mut Decoder<'_, D>,
2682 offset: usize,
2683) -> Result<Option<(bool, u32, u32)>> {
2684 let num_bytes = decoder.read_num::<u32>(offset);
2685 let num_handles = decoder.read_num::<u16>(offset + 4) as u32;
2686 let inlined = decoder.read_num::<u16>(offset + 6);
2687 match (num_bytes, num_handles, inlined) {
2688 (0, 0, 0) => Ok(None),
2689 (_, _, 1) => Ok(Some((true, 4, num_handles))),
2690 (_, _, 0) if num_bytes.is_multiple_of(8) => Ok(Some((false, num_bytes, num_handles))),
2691 (_, _, 0) => Err(Error::InvalidNumBytesInEnvelope),
2692 _ => Err(Error::InvalidInlineMarkerInEnvelope),
2693 }
2694}
2695
2696#[doc(hidden)] #[inline]
2699pub unsafe fn decode_unknown_envelope<D: ResourceDialect>(
2700 decoder: &mut Decoder<'_, D>,
2701 offset: usize,
2702 mut depth: Depth,
2703) -> Result<()> {
2704 if let Some((inlined, num_bytes, num_handles)) =
2705 unsafe { decode_envelope_header(decoder, offset)? }
2706 {
2707 if !inlined {
2708 depth.increment()?;
2709 if num_bytes != 0 {
2711 let _ = unsafe { decoder.out_of_line_offset(num_bytes as usize)? };
2712 }
2713 }
2714 if num_handles != 0 {
2715 for _ in 0..num_handles {
2716 decoder.drop_next_handle()?;
2717 }
2718 }
2719 }
2720 Ok(())
2721}
2722
2723#[doc(hidden)] #[inline]
2731pub unsafe fn decode_union_inline_portion<D: ResourceDialect>(
2732 decoder: &mut Decoder<'_, D>,
2733 offset: usize,
2734) -> Result<(u64, bool, u32, u32)> {
2735 let ordinal = decoder.read_num::<u64>(offset);
2736 match unsafe { decode_envelope_header(decoder, offset + 8)? } {
2737 Some((inlined, num_bytes, num_handles)) => Ok((ordinal, inlined, num_bytes, num_handles)),
2738 None => Err(Error::NotNullable),
2739 }
2740}
2741
2742pub struct ResultType<T: TypeMarker, E: TypeMarker>(PhantomData<(T, E)>);
2748
2749pub struct FlexibleType<T: TypeMarker>(PhantomData<T>);
2751
2752pub struct FlexibleResultType<T: TypeMarker, E: TypeMarker>(PhantomData<(T, E)>);
2754
2755#[doc(hidden)] #[derive(Debug)]
2758pub enum Flexible<T> {
2759 Ok(T),
2760 FrameworkErr(FrameworkErr),
2761}
2762
2763#[doc(hidden)] #[derive(Debug)]
2766pub enum FlexibleResult<T, E> {
2767 Ok(T),
2768 DomainErr(E),
2769 FrameworkErr(FrameworkErr),
2770}
2771
2772#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
2774#[repr(i32)]
2775pub enum FrameworkErr {
2776 UnknownMethod = zx_types::ZX_ERR_NOT_SUPPORTED,
2778}
2779
2780impl FrameworkErr {
2781 #[inline]
2782 fn from_primitive(prim: i32) -> Option<Self> {
2783 match prim {
2784 zx_types::ZX_ERR_NOT_SUPPORTED => Some(Self::UnknownMethod),
2785 _ => None,
2786 }
2787 }
2788
2789 #[inline(always)]
2790 const fn into_primitive(self) -> i32 {
2791 self as i32
2792 }
2793}
2794
2795unsafe impl TypeMarker for FrameworkErr {
2796 type Owned = Self;
2797 #[inline(always)]
2798 fn inline_align(_context: Context) -> usize {
2799 std::mem::align_of::<i32>()
2800 }
2801
2802 #[inline(always)]
2803 fn inline_size(_context: Context) -> usize {
2804 std::mem::size_of::<i32>()
2805 }
2806
2807 #[inline(always)]
2808 fn encode_is_copy() -> bool {
2809 true
2810 }
2811
2812 #[inline(always)]
2813 fn decode_is_copy() -> bool {
2814 false
2815 }
2816}
2817
2818impl ValueTypeMarker for FrameworkErr {
2819 type Borrowed<'a> = Self;
2820 #[inline(always)]
2821 fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
2822 *value
2823 }
2824}
2825
2826unsafe impl<D: ResourceDialect> Encode<Self, D> for FrameworkErr {
2827 #[inline]
2828 unsafe fn encode(
2829 self,
2830 encoder: &mut Encoder<'_, D>,
2831 offset: usize,
2832 _depth: Depth,
2833 ) -> Result<()> {
2834 encoder.debug_check_bounds::<Self>(offset);
2835 unsafe { encoder.write_num(self.into_primitive(), offset) };
2836 Ok(())
2837 }
2838}
2839
2840impl<D: ResourceDialect> Decode<Self, D> for FrameworkErr {
2841 #[inline(always)]
2842 fn new_empty() -> Self {
2843 Self::UnknownMethod
2844 }
2845
2846 #[inline]
2847 unsafe fn decode(
2848 &mut self,
2849 decoder: &mut Decoder<'_, D>,
2850 offset: usize,
2851 _depth: Depth,
2852 ) -> Result<()> {
2853 decoder.debug_check_bounds::<Self>(offset);
2854 let prim = decoder.read_num::<i32>(offset);
2855 *self = Self::from_primitive(prim).ok_or(Error::InvalidEnumValue)?;
2856 Ok(())
2857 }
2858}
2859
2860impl<T> Flexible<T> {
2861 pub fn new(value: T) -> Self {
2863 Self::Ok(value)
2864 }
2865
2866 pub fn into_result<P: ProtocolMarker>(self, method_name: &'static str) -> Result<T> {
2868 match self {
2869 Flexible::Ok(ok) => Ok(ok),
2870 Flexible::FrameworkErr(FrameworkErr::UnknownMethod) => {
2871 Err(Error::UnsupportedMethod { method_name, protocol_name: P::DEBUG_NAME })
2872 }
2873 }
2874 }
2875}
2876
2877impl<T, E> FlexibleResult<T, E> {
2878 pub fn new(result: std::result::Result<T, E>) -> Self {
2880 match result {
2881 Ok(value) => Self::Ok(value),
2882 Err(err) => Self::DomainErr(err),
2883 }
2884 }
2885
2886 pub fn into_result<P: ProtocolMarker>(
2888 self,
2889 method_name: &'static str,
2890 ) -> Result<std::result::Result<T, E>> {
2891 match self {
2892 FlexibleResult::Ok(ok) => Ok(Ok(ok)),
2893 FlexibleResult::DomainErr(err) => Ok(Err(err)),
2894 FlexibleResult::FrameworkErr(FrameworkErr::UnknownMethod) => {
2895 Err(Error::UnsupportedMethod { method_name, protocol_name: P::DEBUG_NAME })
2896 }
2897 }
2898 }
2899}
2900
2901macro_rules! impl_result_union {
2903 (
2904 params: [$($encode_param:ident: Encode<$type_param:ident>),*],
2905 ty: $ty:ty,
2906 owned: $owned:ty,
2907 encode: $encode:ty,
2908 members: [$(
2909 {
2910 ctor: { $($member_ctor:tt)* },
2911 ty: $member_ty:ty,
2912 ordinal: $member_ordinal:tt,
2913 },
2914 )*]
2915 ) => {
2916 unsafe impl<$($type_param: TypeMarker),*> TypeMarker for $ty {
2917 type Owned = $owned;
2918
2919 #[inline(always)]
2920 fn inline_align(_context: Context) -> usize {
2921 8
2922 }
2923
2924 #[inline(always)]
2925 fn inline_size(_context: Context) -> usize {
2926 16
2927 }
2928 }
2929
2930 unsafe impl<D: ResourceDialect, $($type_param: TypeMarker, $encode_param: Encode<$type_param, D>),*> Encode<$ty, D> for $encode {
2931 #[inline]
2932 unsafe fn encode(self, encoder: &mut Encoder<'_, D>, offset: usize, depth: Depth) -> Result<()> {
2933 encoder.debug_check_bounds::<$ty>(offset);
2934 match self {
2935 $(
2936 $($member_ctor)*(val) => {
2937 unsafe { encoder.write_num::<u64>($member_ordinal, offset) };
2938 unsafe { encode_in_envelope::<$member_ty, D>(val, encoder, offset + 8, depth) }
2939 }
2940 )*
2941 }
2942 }
2943 }
2944
2945 impl<D: ResourceDialect, $($type_param: TypeMarker),*> Decode<$ty, D> for $owned
2946 where $($type_param::Owned: Decode<$type_param, D>),*
2947 {
2948 #[inline(always)]
2949 fn new_empty() -> Self {
2950 #![allow(unreachable_code)]
2951 $(
2952 return $($member_ctor)*(new_empty!($member_ty, D));
2953 )*
2954 }
2955
2956 #[inline]
2957 unsafe fn decode(&mut self, decoder: &mut Decoder<'_, D>, offset: usize, mut depth: Depth) -> Result<()> {
2958 decoder.debug_check_bounds::<$ty>(offset);
2959 let next_out_of_line = decoder.next_out_of_line();
2960 let handles_before = decoder.remaining_handles();
2961 let (ordinal, inlined, num_bytes, num_handles) = unsafe { decode_union_inline_portion(decoder, offset)? };
2962 let member_inline_size = match ordinal {
2963 $(
2964 $member_ordinal => <$member_ty as TypeMarker>::inline_size(decoder.context),
2965 )*
2966 _ => return Err(Error::UnknownUnionTag),
2967 };
2968 if inlined != (member_inline_size <= 4) {
2969 return Err(Error::InvalidInlineBitInEnvelope);
2970 }
2971 let inner_offset;
2972 if inlined {
2973 decoder.check_inline_envelope_padding(offset + 8, member_inline_size)?;
2974 inner_offset = offset + 8;
2975 } else {
2976 depth.increment()?;
2977 inner_offset = unsafe { decoder.out_of_line_offset(member_inline_size)? };
2978 }
2979 match ordinal {
2980 $(
2981 $member_ordinal => {
2982 #[allow(irrefutable_let_patterns)]
2983 if let $($member_ctor)*(_) = self {
2984 } else {
2986 *self = $($member_ctor)*(new_empty!($member_ty, D));
2988 }
2989 #[allow(irrefutable_let_patterns)]
2990 if let $($member_ctor)*(val) = self {
2991 unsafe { decode!($member_ty, D, val, decoder, inner_offset, depth)? };
2992 } else {
2993 unreachable!()
2994 }
2995 }
2996 )*
2997 ordinal => panic!("unexpected ordinal {:?}", ordinal)
2998 }
2999 if !inlined && decoder.next_out_of_line() != next_out_of_line + (num_bytes as usize) {
3000 return Err(Error::InvalidNumBytesInEnvelope);
3001 }
3002 if handles_before != decoder.remaining_handles() + (num_handles as usize) {
3003 return Err(Error::InvalidNumHandlesInEnvelope);
3004 }
3005 Ok(())
3006 }
3007 }
3008 };
3009}
3010
3011impl_result_union! {
3012 params: [X: Encode<T>, Y: Encode<E>],
3013 ty: ResultType<T, E>,
3014 owned: std::result::Result<T::Owned, E::Owned>,
3015 encode: std::result::Result<X, Y>,
3016 members: [
3017 { ctor: { Ok }, ty: T, ordinal: 1, },
3018 { ctor: { Err }, ty: E, ordinal: 2, },
3019 ]
3020}
3021
3022impl_result_union! {
3023 params: [X: Encode<T>],
3024 ty: FlexibleType<T>,
3025 owned: Flexible<T::Owned>,
3026 encode: Flexible<X>,
3027 members: [
3028 { ctor: { Flexible::Ok }, ty: T, ordinal: 1, },
3029 { ctor: { Flexible::FrameworkErr }, ty: FrameworkErr, ordinal: 3, },
3030 ]
3031}
3032
3033impl_result_union! {
3034 params: [X: Encode<T>, Y: Encode<E>],
3035 ty: FlexibleResultType<T, E>,
3036 owned: FlexibleResult<T::Owned, E::Owned>,
3037 encode: FlexibleResult<X, Y>,
3038 members: [
3039 { ctor: { FlexibleResult::Ok }, ty: T, ordinal: 1, },
3040 { ctor: { FlexibleResult::DomainErr }, ty: E, ordinal: 2, },
3041 { ctor: { FlexibleResult::FrameworkErr }, ty: FrameworkErr, ordinal: 3, },
3042 ]
3043}
3044
3045#[derive(Copy, Clone, Debug, Eq, PartialEq)]
3051pub struct EpitaphBody {
3052 pub error: Result<(), zx_status::Status>,
3054}
3055
3056unsafe impl TypeMarker for EpitaphBody {
3057 type Owned = Self;
3058
3059 #[inline(always)]
3060 fn inline_align(_context: Context) -> usize {
3061 4
3062 }
3063
3064 #[inline(always)]
3065 fn inline_size(_context: Context) -> usize {
3066 4
3067 }
3068}
3069
3070impl ValueTypeMarker for EpitaphBody {
3071 type Borrowed<'a> = &'a Self;
3072
3073 fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
3074 value
3075 }
3076}
3077
3078unsafe impl<D: ResourceDialect> Encode<EpitaphBody, D> for &EpitaphBody {
3079 #[inline]
3080 unsafe fn encode(
3081 self,
3082 encoder: &mut Encoder<'_, D>,
3083 offset: usize,
3084 _depth: Depth,
3085 ) -> Result<()> {
3086 encoder.debug_check_bounds::<EpitaphBody>(offset);
3087 unsafe { encoder.write_num::<i32>(zx_status::Status::result_into_raw(self.error), offset) };
3088 Ok(())
3089 }
3090}
3091
3092impl<D: ResourceDialect> Decode<Self, D> for EpitaphBody {
3093 #[inline(always)]
3094 fn new_empty() -> Self {
3095 Self { error: Ok(()) }
3096 }
3097
3098 #[inline]
3099 unsafe fn decode(
3100 &mut self,
3101 decoder: &mut Decoder<'_, D>,
3102 offset: usize,
3103 _depth: Depth,
3104 ) -> Result<()> {
3105 decoder.debug_check_bounds::<Self>(offset);
3106 self.error = zx_status::Status::ok(decoder.read_num::<i32>(offset));
3107 Ok(())
3108 }
3109}
3110
3111unsafe impl TypeMarker for ObjectType {
3116 type Owned = Self;
3117
3118 #[inline(always)]
3119 fn inline_align(_context: Context) -> usize {
3120 mem::align_of::<Self>()
3121 }
3122
3123 #[inline(always)]
3124 fn inline_size(_context: Context) -> usize {
3125 mem::size_of::<Self>()
3126 }
3127}
3128
3129impl ValueTypeMarker for ObjectType {
3130 type Borrowed<'a> = Self;
3131
3132 fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
3133 *value
3134 }
3135}
3136
3137unsafe impl<D: ResourceDialect> Encode<ObjectType, D> for ObjectType {
3138 #[inline]
3139 unsafe fn encode(
3140 self,
3141 encoder: &mut Encoder<'_, D>,
3142 offset: usize,
3143 _depth: Depth,
3144 ) -> Result<()> {
3145 encoder.debug_check_bounds::<Self>(offset);
3146 unsafe { encoder.write_num(self.into_raw(), offset) };
3147 Ok(())
3148 }
3149}
3150
3151impl<D: ResourceDialect> Decode<Self, D> for ObjectType {
3152 #[inline(always)]
3153 fn new_empty() -> Self {
3154 ObjectType::NONE
3155 }
3156
3157 #[inline]
3158 unsafe fn decode(
3159 &mut self,
3160 decoder: &mut Decoder<'_, D>,
3161 offset: usize,
3162 _depth: Depth,
3163 ) -> Result<()> {
3164 decoder.debug_check_bounds::<Self>(offset);
3165 *self = Self::from_raw(decoder.read_num(offset));
3166 Ok(())
3167 }
3168}
3169
3170unsafe impl TypeMarker for Rights {
3171 type Owned = Self;
3172
3173 #[inline(always)]
3174 fn inline_align(_context: Context) -> usize {
3175 mem::align_of::<Self>()
3176 }
3177
3178 #[inline(always)]
3179 fn inline_size(_context: Context) -> usize {
3180 mem::size_of::<Self>()
3181 }
3182}
3183
3184impl ValueTypeMarker for Rights {
3185 type Borrowed<'a> = Self;
3186
3187 fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
3188 *value
3189 }
3190}
3191
3192unsafe impl<D: ResourceDialect> Encode<Rights, D> for Rights {
3193 #[inline]
3194 unsafe fn encode(
3195 self,
3196 encoder: &mut Encoder<'_, D>,
3197 offset: usize,
3198 _depth: Depth,
3199 ) -> Result<()> {
3200 encoder.debug_check_bounds::<Self>(offset);
3201 if self.bits() & Self::all().bits() != self.bits() {
3202 return Err(Error::InvalidBitsValue);
3203 }
3204 unsafe { encoder.write_num(self.bits(), offset) };
3205 Ok(())
3206 }
3207}
3208
3209impl<D: ResourceDialect> Decode<Self, D> for Rights {
3210 #[inline(always)]
3211 fn new_empty() -> Self {
3212 Rights::empty()
3213 }
3214
3215 #[inline]
3216 unsafe fn decode(
3217 &mut self,
3218 decoder: &mut Decoder<'_, D>,
3219 offset: usize,
3220 _depth: Depth,
3221 ) -> Result<()> {
3222 decoder.debug_check_bounds::<Self>(offset);
3223 *self = Self::from_bits(decoder.read_num(offset)).ok_or(Error::InvalidBitsValue)?;
3224 Ok(())
3225 }
3226}
3227
3228pub struct GenericMessageType<H: ValueTypeMarker, T: TypeMarker>(PhantomData<(H, T)>);
3234
3235pub struct GenericMessage<H, E> {
3237 pub header: H,
3239 pub body: E,
3241}
3242
3243pub enum GenericMessageOwned {}
3249
3250unsafe impl<H: ValueTypeMarker, T: TypeMarker> TypeMarker for GenericMessageType<H, T> {
3251 type Owned = GenericMessageOwned;
3252
3253 #[inline(always)]
3254 fn inline_align(context: Context) -> usize {
3255 std::cmp::max(H::inline_align(context), T::inline_align(context))
3256 }
3257
3258 #[inline(always)]
3259 fn inline_size(context: Context) -> usize {
3260 H::inline_size(context) + T::inline_size(context)
3261 }
3262}
3263
3264unsafe impl<H: ValueTypeMarker, T: TypeMarker, E: Encode<T, D>, D: ResourceDialect>
3265 Encode<GenericMessageType<H, T>, D> for GenericMessage<<H as TypeMarker>::Owned, E>
3266where
3267 for<'a> H::Borrowed<'a>: Encode<H, D>,
3268{
3269 #[inline]
3270 unsafe fn encode(
3271 self,
3272 encoder: &mut Encoder<'_, D>,
3273 offset: usize,
3274 depth: Depth,
3275 ) -> Result<()> {
3276 encoder.debug_check_bounds::<GenericMessageType<H, T>>(offset);
3277 unsafe {
3278 H::borrow(&self.header).encode(encoder, offset, depth)?;
3279 self.body.encode(encoder, offset + H::inline_size(encoder.context), depth)
3280 }
3281 }
3282}
3283
3284impl<H: ValueTypeMarker, T: TypeMarker, D: ResourceDialect> Decode<GenericMessageType<H, T>, D>
3285 for GenericMessageOwned
3286{
3287 fn new_empty() -> Self {
3288 panic!("cannot create GenericMessageOwned");
3289 }
3290
3291 unsafe fn decode(
3292 &mut self,
3293 _decoder: &mut Decoder<'_, D>,
3294 _offset: usize,
3295 _depth: Depth,
3296 ) -> Result<()> {
3297 match *self {}
3298 }
3299}
3300
3301pub type TransactionMessageType<T> = GenericMessageType<TransactionHeader, T>;
3307
3308pub type TransactionMessage<E> = GenericMessage<TransactionHeader, E>;
3310
3311#[derive(Copy, Clone, Debug, Eq, PartialEq)]
3313#[repr(C)]
3314pub struct TransactionHeader {
3315 pub tx_id: u32,
3317 pub at_rest_flags: [u8; 2],
3320 pub dynamic_flags: u8,
3323 pub magic_number: u8,
3326 pub ordinal: u64,
3328}
3329
3330impl TransactionHeader {
3331 #[inline]
3334 pub fn is_compatible(&self) -> bool {
3335 self.magic_number == MAGIC_NUMBER_INITIAL
3336 }
3337}
3338
3339bitflags! {
3340 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
3342 pub struct AtRestFlags: u16 {
3343 const USE_V2_WIRE_FORMAT = 2;
3349 }
3350}
3351
3352bitflags! {
3353 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
3356 pub struct DynamicFlags: u8 {
3357 const FLEXIBLE = 1 << 7;
3359 }
3360}
3361
3362impl From<AtRestFlags> for [u8; 2] {
3363 #[inline]
3364 fn from(value: AtRestFlags) -> Self {
3365 value.bits().to_le_bytes()
3366 }
3367}
3368
3369impl TransactionHeader {
3370 #[inline]
3372 pub fn new(tx_id: u32, ordinal: u64, dynamic_flags: DynamicFlags) -> Self {
3373 TransactionHeader::new_full(
3374 tx_id,
3375 ordinal,
3376 default_encode_context(),
3377 dynamic_flags,
3378 MAGIC_NUMBER_INITIAL,
3379 )
3380 }
3381
3382 #[inline]
3384 pub fn new_full(
3385 tx_id: u32,
3386 ordinal: u64,
3387 context: Context,
3388 dynamic_flags: DynamicFlags,
3389 magic_number: u8,
3390 ) -> Self {
3391 TransactionHeader {
3392 tx_id,
3393 at_rest_flags: context.at_rest_flags().into(),
3394 dynamic_flags: dynamic_flags.bits(),
3395 magic_number,
3396 ordinal,
3397 }
3398 }
3399
3400 #[inline]
3402 pub fn is_epitaph(&self) -> bool {
3403 self.ordinal == EPITAPH_ORDINAL
3404 }
3405
3406 #[inline]
3408 pub fn validate_wire_format(&self) -> Result<()> {
3409 if self.magic_number != MAGIC_NUMBER_INITIAL {
3410 return Err(Error::IncompatibleMagicNumber(self.magic_number));
3411 }
3412 if !self.at_rest_flags().contains(AtRestFlags::USE_V2_WIRE_FORMAT) {
3413 return Err(Error::UnsupportedWireFormatVersion);
3414 }
3415 Ok(())
3416 }
3417
3418 #[inline]
3421 pub fn validate_request_tx_id(&self, method_type: MethodType) -> Result<()> {
3422 match method_type {
3423 MethodType::OneWay if self.tx_id != 0 => Err(Error::InvalidRequestTxid),
3424 MethodType::TwoWay if self.tx_id == 0 => Err(Error::InvalidRequestTxid),
3425 _ => Ok(()),
3426 }
3427 }
3428
3429 #[inline]
3431 pub fn at_rest_flags(&self) -> AtRestFlags {
3432 AtRestFlags::from_bits_truncate(u16::from_le_bytes(self.at_rest_flags))
3433 }
3434
3435 #[inline]
3437 pub fn dynamic_flags(&self) -> DynamicFlags {
3438 DynamicFlags::from_bits_truncate(self.dynamic_flags)
3439 }
3440
3441 #[inline]
3445 pub fn decoding_context(&self) -> Context {
3446 Context { wire_format_version: WireFormatVersion::V2 }
3447 }
3448}
3449
3450pub fn decode_transaction_header(bytes: &[u8]) -> Result<(TransactionHeader, &[u8])> {
3453 let mut header = new_empty!(TransactionHeader, NoHandleResourceDialect);
3454 let context = Context { wire_format_version: WireFormatVersion::V2 };
3455 let header_len = <TransactionHeader as TypeMarker>::inline_size(context);
3456 if bytes.len() < header_len {
3457 return Err(Error::OutOfRange { expected: header_len, actual: bytes.len() });
3458 }
3459 let (header_bytes, body_bytes) = bytes.split_at(header_len);
3460 Decoder::<NoHandleResourceDialect>::decode_with_context::<TransactionHeader>(
3461 context,
3462 header_bytes,
3463 &mut [],
3464 &mut header,
3465 )
3466 .map_err(|_| Error::InvalidHeader)?;
3467 header.validate_wire_format()?;
3468 Ok((header, body_bytes))
3469}
3470
3471unsafe impl TypeMarker for TransactionHeader {
3472 type Owned = Self;
3473
3474 #[inline(always)]
3475 fn inline_align(_context: Context) -> usize {
3476 8
3477 }
3478
3479 #[inline(always)]
3480 fn inline_size(_context: Context) -> usize {
3481 16
3482 }
3483}
3484
3485impl ValueTypeMarker for TransactionHeader {
3486 type Borrowed<'a> = &'a Self;
3487
3488 fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
3489 value
3490 }
3491}
3492
3493unsafe impl<D: ResourceDialect> Encode<TransactionHeader, D> for &TransactionHeader {
3494 #[inline]
3495 unsafe fn encode(
3496 self,
3497 encoder: &mut Encoder<'_, D>,
3498 offset: usize,
3499 _depth: Depth,
3500 ) -> Result<()> {
3501 encoder.debug_check_bounds::<TransactionHeader>(offset);
3502 unsafe {
3503 let buf_ptr = encoder.buf.as_mut_ptr().add(offset);
3504 (buf_ptr as *mut TransactionHeader).write_unaligned(*self);
3505 }
3506 Ok(())
3507 }
3508}
3509
3510impl<D: ResourceDialect> Decode<Self, D> for TransactionHeader {
3511 #[inline(always)]
3512 fn new_empty() -> Self {
3513 Self { tx_id: 0, at_rest_flags: [0; 2], dynamic_flags: 0, magic_number: 0, ordinal: 0 }
3514 }
3515
3516 #[inline]
3517 unsafe fn decode(
3518 &mut self,
3519 decoder: &mut Decoder<'_, D>,
3520 offset: usize,
3521 _depth: Depth,
3522 ) -> Result<()> {
3523 decoder.debug_check_bounds::<Self>(offset);
3524 unsafe {
3525 let buf_ptr = decoder.buf.as_ptr().add(offset);
3526 let obj_ptr = self as *mut TransactionHeader;
3527 std::ptr::copy_nonoverlapping(buf_ptr, obj_ptr as *mut u8, 16);
3528 }
3529 Ok(())
3530 }
3531}
3532
3533pub struct TlsBuf<D: ResourceDialect> {
3540 bytes: Vec<u8>,
3541 encode_handles: Vec<<D::ProxyChannel as ProxyChannelFor<D>>::HandleDisposition>,
3542 decode_handles: Vec<<D::Handle as HandleFor<D>>::HandleInfo>,
3543}
3544
3545impl<D: ResourceDialect> Default for TlsBuf<D> {
3546 fn default() -> TlsBuf<D> {
3548 TlsBuf {
3549 bytes: Vec::with_capacity(MIN_BUF_BYTES_SIZE),
3550 encode_handles: Vec::new(),
3551 decode_handles: Vec::new(),
3552 }
3553 }
3554}
3555
3556#[inline]
3557fn with_tls_buf<D: ResourceDialect, R>(f: impl FnOnce(&mut TlsBuf<D>) -> R) -> R {
3558 D::with_tls_buf(f)
3559}
3560
3561pub(crate) const MIN_BUF_BYTES_SIZE: usize = 512;
3562
3563#[inline]
3567pub fn with_tls_encode_buf<R, D: ResourceDialect>(
3568 f: impl FnOnce(
3569 &mut Vec<u8>,
3570 &mut Vec<<D::ProxyChannel as ProxyChannelFor<D>>::HandleDisposition>,
3571 ) -> R,
3572) -> R {
3573 with_tls_buf::<D, R>(|buf| {
3574 let res = f(&mut buf.bytes, &mut buf.encode_handles);
3575 buf.bytes.clear();
3576 buf.encode_handles.clear();
3577 res
3578 })
3579}
3580
3581#[inline]
3585pub fn with_tls_decode_buf<R, D: ResourceDialect>(
3586 f: impl FnOnce(&mut Vec<u8>, &mut Vec<<D::Handle as HandleFor<D>>::HandleInfo>) -> R,
3587) -> R {
3588 with_tls_buf::<D, R>(|buf| {
3589 let res = f(&mut buf.bytes, &mut buf.decode_handles);
3590 buf.bytes.clear();
3591 buf.decode_handles.clear();
3592 res
3593 })
3594}
3595
3596#[inline]
3598pub fn clear_tls_buf<D: ResourceDialect>() {
3599 with_tls_buf::<D, ()>(|buf| {
3600 buf.bytes.clear();
3601 buf.bytes.shrink_to_fit();
3602 buf.encode_handles.clear();
3603 buf.encode_handles.shrink_to_fit();
3604 buf.decode_handles.clear();
3605 buf.decode_handles.shrink_to_fit();
3606 });
3607}
3608
3609#[inline]
3613pub fn with_tls_encoded<T: TypeMarker, D: ResourceDialect, Out>(
3614 val: impl Encode<T, D>,
3615 f: impl FnOnce(
3616 &mut Vec<u8>,
3617 &mut Vec<<D::ProxyChannel as ProxyChannelFor<D>>::HandleDisposition>,
3618 ) -> Result<Out>,
3619) -> Result<Out> {
3620 with_tls_encode_buf::<Result<Out>, D>(|bytes, handles| {
3621 Encoder::<D>::encode(bytes, handles, val)?;
3622 f(bytes, handles)
3623 })
3624}
3625
3626#[cfg(test)]
3631mod test {
3632 use super::*;
3633 use crate::handle::convert_handle_dispositions_to_infos;
3634 use crate::time::{BootInstant, BootTicks, MonotonicInstant, MonotonicTicks};
3635 use assert_matches::assert_matches;
3636 use std::fmt;
3637
3638 const CONTEXTS: [Context; 1] = [Context { wire_format_version: WireFormatVersion::V2 }];
3639
3640 const OBJECT_TYPE_NONE: u32 = crate::handle::ObjectType::NONE.into_raw();
3641 const SAME_RIGHTS: u32 = crate::handle::Rights::SAME_RIGHTS.bits();
3642
3643 #[track_caller]
3644 fn to_infos(dispositions: &mut Vec<HandleDisposition<'_>>) -> Vec<HandleInfo> {
3645 convert_handle_dispositions_to_infos(mem::take(dispositions)).unwrap()
3646 }
3647
3648 #[track_caller]
3649 pub fn encode_decode<T: TypeMarker>(
3650 ctx: Context,
3651 start: impl Encode<T, DefaultFuchsiaResourceDialect>,
3652 ) -> T::Owned
3653 where
3654 T::Owned: Decode<T, DefaultFuchsiaResourceDialect>,
3655 {
3656 let buf = &mut Vec::new();
3657 let handle_buf = &mut Vec::new();
3658 Encoder::encode_with_context::<T>(ctx, buf, handle_buf, start).expect("Encoding failed");
3659 let mut out = T::Owned::new_empty();
3660 Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<T>(
3661 ctx,
3662 buf,
3663 &mut to_infos(handle_buf),
3664 &mut out,
3665 )
3666 .expect("Decoding failed");
3667 out
3668 }
3669
3670 #[track_caller]
3671 fn encode_assert_bytes<T: TypeMarker>(
3672 ctx: Context,
3673 data: impl Encode<T, DefaultFuchsiaResourceDialect>,
3674 encoded_bytes: &[u8],
3675 ) {
3676 let buf = &mut Vec::new();
3677 let handle_buf = &mut Vec::new();
3678 Encoder::encode_with_context::<T>(ctx, buf, handle_buf, data).expect("Encoding failed");
3679 assert_eq!(buf, encoded_bytes);
3680 }
3681
3682 #[track_caller]
3683 fn identity<T>(data: &T::Owned)
3684 where
3685 T: ValueTypeMarker,
3686 T::Owned: fmt::Debug + PartialEq + Decode<T, DefaultFuchsiaResourceDialect>,
3687 for<'a> T::Borrowed<'a>: Encode<T, DefaultFuchsiaResourceDialect>,
3688 {
3689 for ctx in CONTEXTS {
3690 assert_eq!(*data, encode_decode(ctx, T::borrow(data)));
3691 }
3692 }
3693
3694 #[track_caller]
3695 fn identities<T>(values: &[T::Owned])
3696 where
3697 T: ValueTypeMarker,
3698 T::Owned: fmt::Debug + PartialEq + Decode<T, DefaultFuchsiaResourceDialect>,
3699 for<'a> T::Borrowed<'a>: Encode<T, DefaultFuchsiaResourceDialect>,
3700 {
3701 for value in values {
3702 identity::<T>(value);
3703 }
3704 }
3705
3706 #[test]
3707 fn encode_decode_byte() {
3708 identities::<u8>(&[0u8, 57u8, 255u8]);
3709 identities::<i8>(&[0i8, -57i8, 12i8]);
3710 identity::<Optional<Vector<i32, 3>>>(&None::<Vec<i32>>);
3711 }
3712
3713 #[test]
3714 fn encode_decode_multibyte() {
3715 identities::<u64>(&[0u64, 1u64, u64::MAX, u64::MIN]);
3716 identities::<i64>(&[0i64, 1i64, i64::MAX, i64::MIN]);
3717 identities::<f32>(&[0f32, 1f32, f32::MAX, f32::MIN]);
3718 identities::<f64>(&[0f64, 1f64, f64::MAX, f64::MIN]);
3719 }
3720
3721 #[test]
3722 fn encode_decode_nan() {
3723 for ctx in CONTEXTS {
3724 assert!(encode_decode::<f32>(ctx, f32::NAN).is_nan());
3725 assert!(encode_decode::<f64>(ctx, f64::NAN).is_nan());
3726 }
3727 }
3728
3729 #[test]
3730 fn encode_decode_instants() {
3731 let monotonic = MonotonicInstant::from_nanos(987654321);
3732 let boot = BootInstant::from_nanos(987654321);
3733 let monotonic_ticks = MonotonicTicks::from_raw(111111111);
3734 let boot_ticks = BootTicks::from_raw(22222222);
3735 for ctx in CONTEXTS {
3736 assert_eq!(encode_decode::<BootInstant>(ctx, boot), boot);
3737 assert_eq!(encode_decode::<MonotonicInstant>(ctx, monotonic), monotonic);
3738 assert_eq!(encode_decode::<BootTicks>(ctx, boot_ticks), boot_ticks);
3739 assert_eq!(encode_decode::<MonotonicTicks>(ctx, monotonic_ticks), monotonic_ticks);
3740 }
3741 }
3742
3743 #[test]
3744 fn encode_decode_out_of_line() {
3745 type V<T> = UnboundedVector<T>;
3746 type S = UnboundedString;
3747 type O<T> = Optional<T>;
3748
3749 identity::<V<i32>>(&Vec::<i32>::new());
3750 identity::<V<i32>>(&vec![1, 2, 3]);
3751 identity::<O<V<i32>>>(&None::<Vec<i32>>);
3752 identity::<O<V<i32>>>(&Some(Vec::<i32>::new()));
3753 identity::<O<V<i32>>>(&Some(vec![1, 2, 3]));
3754 identity::<O<V<V<i32>>>>(&Some(vec![vec![1, 2, 3]]));
3755 identity::<O<V<O<V<i32>>>>>(&Some(vec![Some(vec![1, 2, 3])]));
3756 identity::<S>(&"".to_string());
3757 identity::<S>(&"foo".to_string());
3758 identity::<O<S>>(&None::<String>);
3759 identity::<O<S>>(&Some("".to_string()));
3760 identity::<O<S>>(&Some("foo".to_string()));
3761 identity::<O<V<O<S>>>>(&Some(vec![None, Some("foo".to_string())]));
3762 identity::<V<S>>(&vec!["foo".to_string(), "bar".to_string()]);
3763 }
3764
3765 #[test]
3766 fn array_of_arrays() {
3767 identity::<Array<Array<u32, 5>, 2>>(&[[1, 2, 3, 4, 5], [5, 4, 3, 2, 1]]);
3768 }
3769
3770 fn slice_identity<T>(start: &[T::Owned])
3771 where
3772 T: ValueTypeMarker,
3773 T::Owned: fmt::Debug + PartialEq + Decode<T, DefaultFuchsiaResourceDialect>,
3774 for<'a> T::Borrowed<'a>: Encode<T, DefaultFuchsiaResourceDialect>,
3775 {
3776 for ctx in CONTEXTS {
3777 let decoded = encode_decode::<UnboundedVector<T>>(ctx, start);
3778 assert_eq!(start, UnboundedVector::<T>::borrow(&decoded));
3779 }
3780 }
3781
3782 #[test]
3783 fn encode_slices_of_primitives() {
3784 slice_identity::<u8>(&[]);
3785 slice_identity::<u8>(&[0]);
3786 slice_identity::<u8>(&[1, 2, 3, 4, 5, 255]);
3787
3788 slice_identity::<i8>(&[]);
3789 slice_identity::<i8>(&[0]);
3790 slice_identity::<i8>(&[1, 2, 3, 4, 5, -128, 127]);
3791
3792 slice_identity::<u64>(&[]);
3793 slice_identity::<u64>(&[0]);
3794 slice_identity::<u64>(&[1, 2, 3, 4, 5, u64::MAX]);
3795
3796 slice_identity::<f32>(&[]);
3797 slice_identity::<f32>(&[0.0]);
3798 slice_identity::<f32>(&[1.0, 2.0, 3.0, 4.0, 5.0, f32::MIN, f32::MAX]);
3799
3800 slice_identity::<f64>(&[]);
3801 slice_identity::<f64>(&[0.0]);
3802 slice_identity::<f64>(&[1.0, 2.0, 3.0, 4.0, 5.0, f64::MIN, f64::MAX]);
3803 }
3804
3805 #[test]
3806 fn result_encode_empty_ok_value() {
3807 for ctx in CONTEXTS {
3808 encode_assert_bytes::<EmptyPayload>(ctx, (), &[]);
3810 }
3811 encode_assert_bytes::<ResultType<EmptyStruct, i32>>(
3814 Context { wire_format_version: WireFormatVersion::V2 },
3815 Ok::<(), i32>(()),
3816 &[
3817 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, ],
3822 );
3823 }
3824
3825 #[test]
3826 fn result_decode_empty_ok_value() {
3827 let mut result = Err(0);
3828 Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<ResultType<EmptyStruct, u32>>(
3829 Context { wire_format_version: WireFormatVersion::V2 },
3830 &[
3831 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, ],
3834 &mut [],
3835 &mut result,
3836 )
3837 .expect("Decoding failed");
3838 assert_matches!(result, Ok(()));
3839 }
3840
3841 #[test]
3842 fn encode_decode_result() {
3843 type Res = ResultType<UnboundedString, u32>;
3844 for ctx in CONTEXTS {
3845 assert_eq!(encode_decode::<Res>(ctx, Ok::<&str, u32>("foo")), Ok("foo".to_string()));
3846 assert_eq!(encode_decode::<Res>(ctx, Err::<&str, u32>(5)), Err(5));
3847 }
3848 }
3849
3850 #[test]
3851 fn result_validates_num_bytes() {
3852 type Res = ResultType<u64, u64>;
3853 for ctx in CONTEXTS {
3854 for ordinal in [1, 2] {
3855 let bytes = [
3857 ordinal, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, ];
3862 let mut out = new_empty!(Res, DefaultFuchsiaResourceDialect);
3863 assert_matches!(
3864 Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<Res>(
3865 ctx,
3866 &bytes,
3867 &mut [],
3868 &mut out
3869 ),
3870 Err(Error::InvalidNumBytesInEnvelope)
3871 );
3872 }
3873 }
3874 }
3875
3876 #[test]
3877 fn result_validates_num_handles() {
3878 type Res = ResultType<u64, u64>;
3879 for ctx in CONTEXTS {
3880 for ordinal in [1, 2] {
3881 let bytes = [
3883 ordinal, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, ];
3888 let mut out = new_empty!(Res, DefaultFuchsiaResourceDialect);
3889 assert_matches!(
3890 Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<Res>(
3891 ctx,
3892 &bytes,
3893 &mut [],
3894 &mut out
3895 ),
3896 Err(Error::InvalidNumHandlesInEnvelope)
3897 );
3898 }
3899 }
3900 }
3901
3902 #[test]
3903 fn decode_result_unknown_tag() {
3904 type Res = ResultType<u32, u32>;
3905 let ctx = Context { wire_format_version: WireFormatVersion::V2 };
3906
3907 let bytes: &[u8] = &[
3908 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3910 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
3912 ];
3913 let handle_buf = &mut Vec::<HandleInfo>::new();
3914
3915 let mut out = new_empty!(Res, DefaultFuchsiaResourceDialect);
3916 let res = Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<Res>(
3917 ctx, bytes, handle_buf, &mut out,
3918 );
3919 assert_matches!(res, Err(Error::UnknownUnionTag));
3920 }
3921
3922 #[test]
3923 fn decode_result_success_invalid_empty_struct() {
3924 type Res = ResultType<EmptyStruct, u32>;
3925 let ctx = Context { wire_format_version: WireFormatVersion::V2 };
3926
3927 let bytes: &[u8] = &[
3928 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3930 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
3932 ];
3933 let handle_buf = &mut Vec::<HandleInfo>::new();
3934
3935 let mut out = new_empty!(Res, DefaultFuchsiaResourceDialect);
3936 let res = Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<Res>(
3937 ctx, bytes, handle_buf, &mut out,
3938 );
3939 assert_matches!(res, Err(Error::Invalid));
3940 }
3941
3942 #[test]
3943 fn encode_decode_transaction_msg() {
3944 for ctx in CONTEXTS {
3945 let header = TransactionHeader {
3946 tx_id: 4,
3947 ordinal: 6,
3948 at_rest_flags: [2, 0],
3949 dynamic_flags: 0,
3950 magic_number: 1,
3951 };
3952 type Body = UnboundedString;
3953 let body = "hello";
3954
3955 let start = TransactionMessage { header, body };
3956
3957 let buf = &mut Vec::new();
3958 let handle_buf = &mut Vec::new();
3959 Encoder::<DefaultFuchsiaResourceDialect>::encode_with_context::<
3960 TransactionMessageType<Body>,
3961 >(ctx, buf, handle_buf, start)
3962 .expect("Encoding failed");
3963
3964 let (out_header, out_buf) =
3965 decode_transaction_header(buf).expect("Decoding header failed");
3966 assert_eq!(header, out_header);
3967
3968 let mut body_out = String::new();
3969 Decoder::<DefaultFuchsiaResourceDialect>::decode_into::<Body>(
3970 &header,
3971 out_buf,
3972 &mut to_infos(handle_buf),
3973 &mut body_out,
3974 )
3975 .expect("Decoding body failed");
3976 assert_eq!(body, body_out);
3977 }
3978 }
3979
3980 #[test]
3981 fn direct_encode_transaction_header_strict() {
3982 let bytes = &[
3983 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
3986 let header = TransactionHeader {
3987 tx_id: 4,
3988 ordinal: 6,
3989 at_rest_flags: [0; 2],
3990 dynamic_flags: DynamicFlags::empty().bits(),
3991 magic_number: 1,
3992 };
3993
3994 for ctx in CONTEXTS {
3995 encode_assert_bytes::<TransactionHeader>(ctx, &header, bytes);
3996 }
3997 }
3998
3999 #[test]
4000 fn direct_decode_transaction_header_strict() {
4001 let bytes = &[
4002 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
4005 let header = TransactionHeader {
4006 tx_id: 4,
4007 ordinal: 6,
4008 at_rest_flags: [0; 2],
4009 dynamic_flags: DynamicFlags::empty().bits(),
4010 magic_number: 1,
4011 };
4012
4013 for ctx in CONTEXTS {
4014 let mut out = new_empty!(TransactionHeader, DefaultFuchsiaResourceDialect);
4015 Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<TransactionHeader>(
4016 ctx,
4017 bytes,
4018 &mut [],
4019 &mut out,
4020 )
4021 .expect("Decoding failed");
4022 assert_eq!(out, header);
4023 }
4024 }
4025
4026 #[test]
4027 fn direct_encode_transaction_header_flexible() {
4028 let bytes = &[
4029 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
4032 let header = TransactionHeader {
4033 tx_id: 4,
4034 ordinal: 6,
4035 at_rest_flags: [0; 2],
4036 dynamic_flags: DynamicFlags::FLEXIBLE.bits(),
4037 magic_number: 1,
4038 };
4039
4040 for ctx in CONTEXTS {
4041 encode_assert_bytes::<TransactionHeader>(ctx, &header, bytes);
4042 }
4043 }
4044
4045 #[test]
4046 fn direct_decode_transaction_header_flexible() {
4047 let bytes = &[
4048 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
4051 let header = TransactionHeader {
4052 tx_id: 4,
4053 ordinal: 6,
4054 at_rest_flags: [0; 2],
4055 dynamic_flags: DynamicFlags::FLEXIBLE.bits(),
4056 magic_number: 1,
4057 };
4058
4059 for ctx in CONTEXTS {
4060 let mut out = new_empty!(TransactionHeader, DefaultFuchsiaResourceDialect);
4061 Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<TransactionHeader>(
4062 ctx,
4063 bytes,
4064 &mut [],
4065 &mut out,
4066 )
4067 .expect("Decoding failed");
4068 assert_eq!(out, header);
4069 }
4070 }
4071
4072 #[test]
4073 fn extra_data_is_disallowed() {
4074 for ctx in CONTEXTS {
4075 assert_matches!(
4076 Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<EmptyPayload>(
4077 ctx,
4078 &[0],
4079 &mut [],
4080 &mut ()
4081 ),
4082 Err(Error::ExtraBytes)
4083 );
4084 assert_matches!(
4085 Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<EmptyPayload>(
4086 ctx,
4087 &[],
4088 &mut [HandleInfo::new(
4089 NullableHandle::invalid(),
4090 ObjectType::NONE,
4091 Rights::NONE,
4092 )],
4093 &mut ()
4094 ),
4095 Err(Error::ExtraHandles)
4096 );
4097 }
4098 }
4099
4100 #[test]
4101 fn encode_default_context() {
4102 let buf = &mut Vec::new();
4103 Encoder::<DefaultFuchsiaResourceDialect>::encode::<u8>(buf, &mut Vec::new(), 1u8)
4104 .expect("Encoding failed");
4105 assert_eq!(buf, &[1u8, 0, 0, 0, 0, 0, 0, 0]);
4106 }
4107
4108 #[test]
4109 fn encode_handle() {
4110 type T = HandleType<NullableHandle, OBJECT_TYPE_NONE, SAME_RIGHTS>;
4111 for ctx in CONTEXTS {
4112 let handle = crate::handle::Event::create().into_handle();
4113 let raw_handle = handle.raw_handle();
4114 let buf = &mut Vec::new();
4115 let handle_buf = &mut Vec::new();
4116 Encoder::<DefaultFuchsiaResourceDialect>::encode_with_context::<T>(
4117 ctx, buf, handle_buf, handle,
4118 )
4119 .expect("Encoding failed");
4120
4121 assert_eq!(handle_buf.len(), 1);
4122 assert!(handle_buf[0].is_move());
4123 assert_eq!(handle_buf[0].raw_handle(), raw_handle);
4124
4125 let mut handle_out = new_empty!(T);
4126 Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<T>(
4127 ctx,
4128 buf,
4129 &mut to_infos(handle_buf),
4130 &mut handle_out,
4131 )
4132 .expect("Decoding failed");
4133 assert_eq!(
4134 handle_out.raw_handle(),
4135 raw_handle,
4136 "decoded handle must match encoded handle"
4137 );
4138 }
4139 }
4140
4141 #[test]
4142 fn decode_too_few_handles() {
4143 type T = HandleType<NullableHandle, OBJECT_TYPE_NONE, SAME_RIGHTS>;
4144 for ctx in CONTEXTS {
4145 let bytes: &[u8] = &[0xff; 8];
4146 let handle_buf = &mut Vec::new();
4147 let mut handle_out = NullableHandle::invalid();
4148 let res = Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<T>(
4149 ctx,
4150 bytes,
4151 handle_buf,
4152 &mut handle_out,
4153 );
4154 assert_matches!(res, Err(Error::OutOfHandles));
4155 }
4156 }
4157
4158 #[test]
4159 fn encode_epitaph() {
4160 for ctx in CONTEXTS {
4161 let buf = &mut Vec::new();
4162 let handle_buf = &mut Vec::new();
4163 Encoder::<DefaultFuchsiaResourceDialect>::encode_with_context::<EpitaphBody>(
4164 ctx,
4165 buf,
4166 handle_buf,
4167 &EpitaphBody { error: Err(zx_status::Status::UNAVAILABLE) },
4168 )
4169 .expect("encoding failed");
4170 assert_eq!(buf, &[0xe4, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00]);
4171
4172 let mut out = new_empty!(EpitaphBody, DefaultFuchsiaResourceDialect);
4173 Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<EpitaphBody>(
4174 ctx,
4175 buf,
4176 &mut to_infos(handle_buf),
4177 &mut out,
4178 )
4179 .expect("Decoding failed");
4180 assert_eq!(EpitaphBody { error: Err(zx_status::Status::UNAVAILABLE) }, out);
4181 }
4182 }
4183}