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