1pub use static_assertions::const_assert_eq;
10
11use crate::endpoints::ProtocolMarker;
12use crate::handle::{
13 Handle, HandleBased, HandleDisposition, HandleInfo, HandleOp, 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 = Handle;
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: Handle, object_type: ObjectType, rights: Rights) -> Self {
432 HandleDisposition::new(HandleOp::Move(handle), object_type, rights, Status::OK)
433 }
434}
435
436impl HandleFor<DefaultFuchsiaResourceDialect> for Handle {
437 type HandleInfo = HandleInfo;
438
439 fn invalid() -> Self {
440 Handle::invalid()
441 }
442
443 fn is_invalid(&self) -> bool {
444 Handle::is_invalid(self)
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<Handle> {
454 let handle_info = std::mem::replace(
455 self,
456 HandleInfo::new(Handle::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(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(Handle::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 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.truncate(0);
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 = self.buf.get_unchecked_mut(offset) as *mut u8;
860 (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 resize_vec_no_zeroing(self.buf, new_len);
886 let padding_ptr = self.buf.get_unchecked_mut(new_len - 8) as *mut u8;
890 (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 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 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 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 = self.buf.get_unchecked(self.next_out_of_line - 8) as *const u8;
1136 let last_u64 = (last_u64_ptr as *const u64).read_unaligned();
1137 let padding = aligned_len - len;
1138 let mask = !(!0u64 >> (padding * 8));
1143 if last_u64 & mask != 0 {
1144 return Err(self.end_of_block_padding_error(offset + len, self.next_out_of_line));
1145 }
1146
1147 Ok(offset)
1148 }
1149
1150 fn end_of_block_padding_error(&self, start: usize, end: usize) -> Error {
1153 for i in start..end {
1154 if self.buf[i] != 0 {
1155 return Error::NonZeroPadding { padding_start: start };
1156 }
1157 }
1158 std::process::abort();
1161 }
1162
1163 #[inline]
1166 pub fn check_padding(&self, offset: usize, len: usize) -> Result<()> {
1167 if len == 0 {
1168 return Ok(());
1170 }
1171 debug_assert!(offset + len <= self.buf.len());
1172 for i in offset..offset + len {
1173 if unsafe { *self.buf.get_unchecked(i) } != 0 {
1175 return Err(Error::NonZeroPadding { padding_start: offset });
1176 }
1177 }
1178 Ok(())
1179 }
1180
1181 #[inline]
1187 pub fn check_inline_envelope_padding(
1188 &self,
1189 value_offset: usize,
1190 value_len: usize,
1191 ) -> Result<()> {
1192 let valid_padding = unsafe {
1195 match value_len {
1196 1 => {
1197 *self.buf.get_unchecked(value_offset + 1) == 0
1198 && *self.buf.get_unchecked(value_offset + 2) == 0
1199 && *self.buf.get_unchecked(value_offset + 3) == 0
1200 }
1201 2 => {
1202 *self.buf.get_unchecked(value_offset + 2) == 0
1203 && *self.buf.get_unchecked(value_offset + 3) == 0
1204 }
1205 3 => *self.buf.get_unchecked(value_offset + 3) == 0,
1206 4 => true,
1207 value_len => unreachable!("value_len={}", value_len),
1208 }
1209 };
1210 if valid_padding {
1211 Ok(())
1212 } else {
1213 Err(Error::NonZeroPadding { padding_start: value_offset + value_len })
1214 }
1215 }
1216
1217 #[inline]
1219 pub fn take_next_handle(
1220 &mut self,
1221 expected_object_type: crate::ObjectType,
1222 expected_rights: crate::Rights,
1223 ) -> Result<D::Handle> {
1224 let Some(next_handle) = self.handles.get_mut(self.next_handle) else {
1225 return Err(Error::OutOfHandles);
1226 };
1227 let handle = next_handle.consume(expected_object_type, expected_rights)?;
1228 self.next_handle += 1;
1229 Ok(handle)
1230 }
1231
1232 #[inline]
1234 pub fn drop_next_handle(&mut self) -> Result<()> {
1235 let Some(next_handle) = self.handles.get_mut(self.next_handle) else {
1236 return Err(Error::OutOfHandles);
1237 };
1238 next_handle.drop_in_place();
1239 self.next_handle += 1;
1240 Ok(())
1241 }
1242}
1243
1244impl<T: Timeline + 'static, D: ResourceDialect> Decode<Self, D> for Instant<T> {
1245 #[inline(always)]
1246 fn new_empty() -> Self {
1247 Instant::ZERO
1248 }
1249
1250 #[inline]
1251 unsafe fn decode(
1252 &mut self,
1253 decoder: &mut Decoder<'_, D>,
1254 offset: usize,
1255 _depth: Depth,
1256 ) -> Result<()> {
1257 decoder.debug_check_bounds::<Self>(offset);
1258 *self = Self::from_nanos(decoder.read_num(offset));
1259 Ok(())
1260 }
1261}
1262
1263impl<T: Timeline + 'static, D: ResourceDialect> Decode<Self, D> for Ticks<T> {
1264 #[inline(always)]
1265 fn new_empty() -> Self {
1266 Ticks::<T>::ZERO
1267 }
1268
1269 #[inline]
1270 unsafe fn decode(
1271 &mut self,
1272 decoder: &mut Decoder<'_, D>,
1273 offset: usize,
1274 _depth: Depth,
1275 ) -> Result<()> {
1276 decoder.debug_check_bounds::<Self>(offset);
1277 *self = Self::from_raw(decoder.read_num(offset));
1278 Ok(())
1279 }
1280}
1281
1282pub struct Ambiguous1;
1293
1294pub struct Ambiguous2;
1297
1298pub enum AmbiguousNever {}
1301
1302macro_rules! impl_ambiguous {
1303 ($ambiguous:ident) => {
1304 unsafe impl TypeMarker for $ambiguous {
1305 type Owned = AmbiguousNever;
1306
1307 fn inline_align(_context: Context) -> usize {
1308 panic!("reached code for fake ambiguous type");
1309 }
1310
1311 fn inline_size(_context: Context) -> usize {
1312 panic!("reached code for fake ambiguous type");
1313 }
1314 }
1315
1316 impl ValueTypeMarker for $ambiguous {
1317 type Borrowed<'a> = AmbiguousNever;
1318
1319 fn borrow(value: &<Self as TypeMarker>::Owned) -> Self::Borrowed<'_> {
1320 match *value {}
1321 }
1322 }
1323
1324 impl ResourceTypeMarker for $ambiguous {
1325 type Borrowed<'a> = AmbiguousNever;
1326 fn take_or_borrow(value: &mut <Self as TypeMarker>::Owned) -> Self::Borrowed<'_>
1327 where
1328 Self: TypeMarker,
1329 {
1330 match *value {}
1331 }
1332 }
1333
1334 unsafe impl<T, D: ResourceDialect> Encode<$ambiguous, D> for T {
1335 unsafe fn encode(
1336 self,
1337 _encoder: &mut Encoder<'_, D>,
1338 _offset: usize,
1339 _depth: Depth,
1340 ) -> Result<()> {
1341 panic!("reached code for fake ambiguous type");
1342 }
1343 }
1344
1345 impl<D: ResourceDialect> Decode<$ambiguous, D> for AmbiguousNever {
1348 fn new_empty() -> Self {
1349 panic!("reached code for fake ambiguous type");
1350 }
1351
1352 unsafe fn decode(
1353 &mut self,
1354 _decoder: &mut Decoder<'_, D>,
1355 _offset: usize,
1356 _depth: Depth,
1357 ) -> Result<()> {
1358 match *self {}
1359 }
1360 }
1361 };
1362}
1363
1364impl_ambiguous!(Ambiguous1);
1365impl_ambiguous!(Ambiguous2);
1366
1367pub struct EmptyPayload;
1373
1374unsafe impl TypeMarker for EmptyPayload {
1375 type Owned = ();
1376 #[inline(always)]
1377 fn inline_align(_context: Context) -> usize {
1378 1
1379 }
1380
1381 #[inline(always)]
1382 fn inline_size(_context: Context) -> usize {
1383 0
1384 }
1385}
1386
1387impl ValueTypeMarker for EmptyPayload {
1388 type Borrowed<'a> = ();
1389 #[inline(always)]
1390 fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
1391 *value
1392 }
1393}
1394
1395unsafe impl<D: ResourceDialect> Encode<EmptyPayload, D> for () {
1396 #[inline(always)]
1397 unsafe fn encode(
1398 self,
1399 _encoder: &mut Encoder<'_, D>,
1400 _offset: usize,
1401 _depth: Depth,
1402 ) -> Result<()> {
1403 Ok(())
1404 }
1405}
1406
1407impl<D: ResourceDialect> Decode<EmptyPayload, D> for () {
1408 #[inline(always)]
1409 fn new_empty() -> Self {}
1410
1411 #[inline(always)]
1412 unsafe fn decode(
1413 &mut self,
1414 _decoder: &mut Decoder<'_, D>,
1415 _offset: usize,
1416 _depth: Depth,
1417 ) -> Result<()> {
1418 Ok(())
1419 }
1420}
1421
1422pub struct EmptyStruct;
1425
1426unsafe impl TypeMarker for EmptyStruct {
1427 type Owned = ();
1428 #[inline(always)]
1429 fn inline_align(_context: Context) -> usize {
1430 1
1431 }
1432
1433 #[inline(always)]
1434 fn inline_size(_context: Context) -> usize {
1435 1
1436 }
1437}
1438
1439impl ValueTypeMarker for EmptyStruct {
1440 type Borrowed<'a> = ();
1441 #[inline(always)]
1442 fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
1443 *value
1444 }
1445}
1446
1447unsafe impl<D: ResourceDialect> Encode<EmptyStruct, D> for () {
1448 #[inline]
1449 unsafe fn encode(
1450 self,
1451 encoder: &mut Encoder<'_, D>,
1452 offset: usize,
1453 _depth: Depth,
1454 ) -> Result<()> {
1455 encoder.debug_check_bounds::<EmptyStruct>(offset);
1456 encoder.write_num(0u8, offset);
1457 Ok(())
1458 }
1459}
1460
1461impl<D: ResourceDialect> Decode<EmptyStruct, D> for () {
1462 #[inline(always)]
1463 fn new_empty() -> Self {}
1464
1465 #[inline]
1466 unsafe fn decode(
1467 &mut self,
1468 decoder: &mut Decoder<'_, D>,
1469 offset: usize,
1470 _depth: Depth,
1471 ) -> Result<()> {
1472 decoder.debug_check_bounds::<EmptyStruct>(offset);
1473 match decoder.read_num::<u8>(offset) {
1474 0 => Ok(()),
1475 _ => Err(Error::Invalid),
1476 }
1477 }
1478}
1479
1480mod numeric {
1486 use super::*;
1487
1488 pub trait Numeric {}
1490
1491 macro_rules! impl_numeric {
1494 ($numeric_ty:ty) => {
1495 impl Numeric for $numeric_ty {}
1496
1497 unsafe impl TypeMarker for $numeric_ty {
1498 type Owned = $numeric_ty;
1499 #[inline(always)]
1500 fn inline_align(_context: Context) -> usize {
1501 mem::align_of::<$numeric_ty>()
1502 }
1503
1504 #[inline(always)]
1505 fn inline_size(_context: Context) -> usize {
1506 mem::size_of::<$numeric_ty>()
1507 }
1508
1509 #[inline(always)]
1510 fn encode_is_copy() -> bool {
1511 true
1512 }
1513
1514 #[inline(always)]
1515 fn decode_is_copy() -> bool {
1516 true
1517 }
1518 }
1519
1520 impl ValueTypeMarker for $numeric_ty {
1521 type Borrowed<'a> = $numeric_ty;
1522
1523 #[inline(always)]
1524 fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
1525 *value
1526 }
1527 }
1528
1529 unsafe impl<D: ResourceDialect> Encode<$numeric_ty, D> for $numeric_ty {
1530 #[inline(always)]
1531 unsafe fn encode(
1532 self,
1533 encoder: &mut Encoder<'_, D>,
1534 offset: usize,
1535 _depth: Depth,
1536 ) -> Result<()> {
1537 encoder.debug_check_bounds::<$numeric_ty>(offset);
1538 encoder.write_num::<$numeric_ty>(self, offset);
1539 Ok(())
1540 }
1541 }
1542
1543 impl<D: ResourceDialect> Decode<$numeric_ty, D> for $numeric_ty {
1544 #[inline(always)]
1545 fn new_empty() -> Self {
1546 0 as $numeric_ty
1547 }
1548
1549 #[inline(always)]
1550 unsafe fn decode(
1551 &mut self,
1552 decoder: &mut Decoder<'_, D>,
1553 offset: usize,
1554 _depth: Depth,
1555 ) -> Result<()> {
1556 decoder.debug_check_bounds::<$numeric_ty>(offset);
1557 *self = decoder.read_num::<$numeric_ty>(offset);
1558 Ok(())
1559 }
1560 }
1561 };
1562 }
1563
1564 impl_numeric!(u8);
1565 impl_numeric!(u16);
1566 impl_numeric!(u32);
1567 impl_numeric!(u64);
1568 impl_numeric!(i8);
1569 impl_numeric!(i16);
1570 impl_numeric!(i32);
1571 impl_numeric!(i64);
1572 impl_numeric!(f32);
1573 impl_numeric!(f64);
1574}
1575
1576unsafe impl TypeMarker for bool {
1577 type Owned = bool;
1578
1579 #[inline(always)]
1580 fn inline_align(_context: Context) -> usize {
1581 mem::align_of::<bool>()
1582 }
1583
1584 #[inline(always)]
1585 fn inline_size(_context: Context) -> usize {
1586 mem::size_of::<bool>()
1587 }
1588
1589 #[inline(always)]
1590 fn encode_is_copy() -> bool {
1591 true
1594 }
1595
1596 #[inline(always)]
1597 fn decode_is_copy() -> bool {
1598 false
1600 }
1601}
1602
1603impl ValueTypeMarker for bool {
1604 type Borrowed<'a> = bool;
1605
1606 #[inline(always)]
1607 fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
1608 *value
1609 }
1610}
1611
1612unsafe impl<D: ResourceDialect> Encode<bool, D> for bool {
1613 #[inline]
1614 unsafe fn encode(
1615 self,
1616 encoder: &mut Encoder<'_, D>,
1617 offset: usize,
1618 _depth: Depth,
1619 ) -> Result<()> {
1620 encoder.debug_check_bounds::<bool>(offset);
1621 encoder.write_num(self as u8, offset);
1624 Ok(())
1625 }
1626}
1627
1628impl<D: ResourceDialect> Decode<bool, D> for bool {
1629 #[inline(always)]
1630 fn new_empty() -> Self {
1631 false
1632 }
1633
1634 #[inline]
1635 unsafe fn decode(
1636 &mut self,
1637 decoder: &mut Decoder<'_, D>,
1638 offset: usize,
1639 _depth: Depth,
1640 ) -> Result<()> {
1641 decoder.debug_check_bounds::<bool>(offset);
1642 *self = match unsafe { *decoder.buf.get_unchecked(offset) } {
1644 0 => false,
1645 1 => true,
1646 _ => return Err(Error::InvalidBoolean),
1647 };
1648 Ok(())
1649 }
1650}
1651
1652pub struct Array<T: TypeMarker, const N: usize>(PhantomData<T>);
1658
1659unsafe impl<T: TypeMarker, const N: usize> TypeMarker for Array<T, N> {
1660 type Owned = [T::Owned; N];
1661 #[inline(always)]
1662 fn inline_align(context: Context) -> usize {
1663 T::inline_align(context)
1664 }
1665
1666 #[inline(always)]
1667 fn inline_size(context: Context) -> usize {
1668 N * T::inline_size(context)
1669 }
1670
1671 #[inline(always)]
1672 fn encode_is_copy() -> bool {
1673 T::encode_is_copy()
1674 }
1675
1676 #[inline(always)]
1677 fn decode_is_copy() -> bool {
1678 T::decode_is_copy()
1679 }
1680}
1681
1682impl<T: ValueTypeMarker, const N: usize> ValueTypeMarker for Array<T, N> {
1683 type Borrowed<'a> = &'a [T::Owned; N];
1684 #[inline(always)]
1685 fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
1686 value
1687 }
1688}
1689
1690impl<T: ResourceTypeMarker, const N: usize> ResourceTypeMarker for Array<T, N> {
1691 type Borrowed<'a> = &'a mut [T::Owned; N];
1692 #[inline(always)]
1693 fn take_or_borrow(value: &mut <Self as TypeMarker>::Owned) -> Self::Borrowed<'_> {
1694 value
1695 }
1696}
1697
1698unsafe impl<T: ValueTypeMarker, const N: usize, D: ResourceDialect> Encode<Array<T, N>, D>
1699 for &[T::Owned; N]
1700where
1701 for<'q> T::Borrowed<'q>: Encode<T, D>,
1702{
1703 #[inline]
1704 unsafe fn encode(
1705 self,
1706 encoder: &mut Encoder<'_, D>,
1707 offset: usize,
1708 depth: Depth,
1709 ) -> Result<()> {
1710 encoder.debug_check_bounds::<Array<T, N>>(offset);
1711 encode_array_value::<T, D>(self, encoder, offset, depth)
1712 }
1713}
1714
1715unsafe impl<T: ResourceTypeMarker, const N: usize, D: ResourceDialect> Encode<Array<T, N>, D>
1716 for &mut [<T as TypeMarker>::Owned; N]
1717where
1718 for<'q> T::Borrowed<'q>: Encode<T, D>,
1719{
1720 #[inline]
1721 unsafe fn encode(
1722 self,
1723 encoder: &mut Encoder<'_, D>,
1724 offset: usize,
1725 depth: Depth,
1726 ) -> Result<()> {
1727 encoder.debug_check_bounds::<Array<T, N>>(offset);
1728 encode_array_resource::<T, D>(self, encoder, offset, depth)
1729 }
1730}
1731
1732impl<T: TypeMarker, const N: usize, D: ResourceDialect> Decode<Array<T, N>, D> for [T::Owned; N]
1733where
1734 T::Owned: Decode<T, D>,
1735{
1736 #[inline]
1737 fn new_empty() -> Self {
1738 let mut arr = mem::MaybeUninit::<[T::Owned; N]>::uninit();
1739 unsafe {
1740 let arr_ptr = arr.as_mut_ptr() as *mut T::Owned;
1741 for i in 0..N {
1742 ptr::write(arr_ptr.add(i), T::Owned::new_empty());
1743 }
1744 arr.assume_init()
1745 }
1746 }
1747
1748 #[inline]
1749 unsafe fn decode(
1750 &mut self,
1751 decoder: &mut Decoder<'_, D>,
1752 offset: usize,
1753 depth: Depth,
1754 ) -> Result<()> {
1755 decoder.debug_check_bounds::<Array<T, N>>(offset);
1756 decode_array::<T, D>(self, decoder, offset, depth)
1757 }
1758}
1759
1760#[inline]
1761unsafe fn encode_array_value<T: ValueTypeMarker, D: ResourceDialect>(
1762 slice: &[T::Owned],
1763 encoder: &mut Encoder<'_, D>,
1764 offset: usize,
1765 depth: Depth,
1766) -> Result<()>
1767where
1768 for<'a> T::Borrowed<'a>: Encode<T, D>,
1769{
1770 let stride = T::inline_size(encoder.context);
1771 let len = slice.len();
1772 debug_assert_ne!(len, 0);
1774 if T::encode_is_copy() {
1775 debug_assert_eq!(stride, mem::size_of::<T::Owned>());
1776 unsafe {
1783 let src = slice.as_ptr() as *const u8;
1784 let dst: *mut u8 = encoder.buf.as_mut_ptr().add(offset);
1785 ptr::copy_nonoverlapping(src, dst, len * stride);
1786 }
1787 } else {
1788 for i in 0..len {
1789 let item = unsafe { slice.get_unchecked(i) };
1791 T::borrow(item).encode(encoder, offset + i * stride, depth)?;
1792 }
1793 }
1794 Ok(())
1795}
1796
1797#[inline]
1798unsafe fn encode_array_resource<T: ResourceTypeMarker + TypeMarker, D: ResourceDialect>(
1799 slice: &mut [T::Owned],
1800 encoder: &mut Encoder<'_, D>,
1801 offset: usize,
1802 depth: Depth,
1803) -> Result<()>
1804where
1805 for<'a> T::Borrowed<'a>: Encode<T, D>,
1806{
1807 let stride = T::inline_size(encoder.context);
1808 let len = slice.len();
1809 debug_assert_ne!(len, 0);
1811 if T::encode_is_copy() {
1812 debug_assert_eq!(stride, mem::size_of::<T::Owned>());
1813 unsafe {
1820 let src = slice.as_ptr() as *const u8;
1821 let dst: *mut u8 = encoder.buf.as_mut_ptr().add(offset);
1822 ptr::copy_nonoverlapping(src, dst, len * stride);
1823 }
1824 } else {
1825 for i in 0..len {
1826 let item = unsafe { slice.get_unchecked_mut(i) };
1828 T::take_or_borrow(item).encode(encoder, offset + i * stride, depth)?;
1829 }
1830 }
1831 Ok(())
1832}
1833
1834#[inline]
1835unsafe fn decode_array<T: TypeMarker, D: ResourceDialect>(
1836 slice: &mut [T::Owned],
1837 decoder: &mut Decoder<'_, D>,
1838 offset: usize,
1839 depth: Depth,
1840) -> Result<()>
1841where
1842 T::Owned: Decode<T, D>,
1843{
1844 let stride = T::inline_size(decoder.context);
1845 let len = slice.len();
1846 debug_assert_ne!(len, 0);
1848 if T::decode_is_copy() {
1849 debug_assert_eq!(stride, mem::size_of::<T::Owned>());
1850 unsafe {
1857 let src: *const u8 = decoder.buf.as_ptr().add(offset);
1858 let dst = slice.as_mut_ptr() as *mut u8;
1859 ptr::copy_nonoverlapping(src, dst, len * stride);
1860 }
1861 } else {
1862 for i in 0..len {
1863 let item = unsafe { slice.get_unchecked_mut(i) };
1865 item.decode(decoder, offset + i * stride, depth)?;
1866 }
1867 }
1868 Ok(())
1869}
1870
1871pub const MAX_BOUND: usize = usize::MAX;
1877
1878pub struct Vector<T: TypeMarker, const N: usize>(PhantomData<T>);
1880
1881pub type UnboundedVector<T> = Vector<T, MAX_BOUND>;
1883
1884unsafe impl<T: TypeMarker, const N: usize> TypeMarker for Vector<T, N> {
1885 type Owned = Vec<T::Owned>;
1886
1887 #[inline(always)]
1888 fn inline_align(_context: Context) -> usize {
1889 8
1890 }
1891
1892 #[inline(always)]
1893 fn inline_size(_context: Context) -> usize {
1894 16
1895 }
1896}
1897
1898impl<T: ValueTypeMarker, const N: usize> ValueTypeMarker for Vector<T, N> {
1899 type Borrowed<'a> = &'a [T::Owned];
1900 #[inline(always)]
1901 fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
1902 value
1903 }
1904}
1905
1906impl<T: ResourceTypeMarker, const N: usize> ResourceTypeMarker for Vector<T, N> {
1907 type Borrowed<'a> = &'a mut [T::Owned];
1908 #[inline(always)]
1909 fn take_or_borrow(value: &mut <Self as TypeMarker>::Owned) -> Self::Borrowed<'_> {
1910 value.as_mut_slice()
1911 }
1912}
1913
1914unsafe impl<T: ValueTypeMarker, const N: usize, D: ResourceDialect> Encode<Vector<T, N>, D>
1915 for &[<T as TypeMarker>::Owned]
1916where
1917 for<'q> T::Borrowed<'q>: Encode<T, D>,
1918{
1919 #[inline]
1920 unsafe fn encode(
1921 self,
1922 encoder: &mut Encoder<'_, D>,
1923 offset: usize,
1924 depth: Depth,
1925 ) -> Result<()> {
1926 encoder.debug_check_bounds::<Vector<T, N>>(offset);
1927 encode_vector_value::<T, D>(self, N, check_vector_length, encoder, offset, depth)
1928 }
1929}
1930
1931unsafe impl<T: ResourceTypeMarker + TypeMarker, const N: usize, D: ResourceDialect>
1932 Encode<Vector<T, N>, D> for &mut [<T as TypeMarker>::Owned]
1933where
1934 for<'q> T::Borrowed<'q>: Encode<T, D>,
1935{
1936 #[inline]
1937 unsafe fn encode(
1938 self,
1939 encoder: &mut Encoder<'_, D>,
1940 offset: usize,
1941 depth: Depth,
1942 ) -> Result<()> {
1943 encoder.debug_check_bounds::<Vector<T, N>>(offset);
1944 encode_vector_resource::<T, D>(self, N, encoder, offset, depth)
1945 }
1946}
1947
1948impl<T: TypeMarker, const N: usize, D: ResourceDialect> Decode<Vector<T, N>, D> for Vec<T::Owned>
1949where
1950 T::Owned: Decode<T, D>,
1951{
1952 #[inline(always)]
1953 fn new_empty() -> Self {
1954 Vec::new()
1955 }
1956
1957 #[inline]
1958 unsafe fn decode(
1959 &mut self,
1960 decoder: &mut Decoder<'_, D>,
1961 offset: usize,
1962 depth: Depth,
1963 ) -> Result<()> {
1964 decoder.debug_check_bounds::<Vector<T, N>>(offset);
1965 decode_vector::<T, D>(self, N, decoder, offset, depth)
1966 }
1967}
1968
1969#[inline]
1970unsafe fn encode_vector_value<T: ValueTypeMarker, D: ResourceDialect>(
1971 slice: &[<T as TypeMarker>::Owned],
1972 max_length: usize,
1973 check_length: impl Fn(usize, usize) -> Result<()>,
1974 encoder: &mut Encoder<'_, D>,
1975 offset: usize,
1976 mut depth: Depth,
1977) -> Result<()>
1978where
1979 for<'a> T::Borrowed<'a>: Encode<T, D>,
1980{
1981 encoder.write_num(slice.len() as u64, offset);
1982 encoder.write_num(fidl_constants::ALLOC_PRESENT_U64, offset + 8);
1983 if slice.is_empty() {
1985 return Ok(());
1986 }
1987 check_length(slice.len(), max_length)?;
1988 depth.increment()?;
1989 let bytes_len = slice.len() * T::inline_size(encoder.context);
1990 let offset = encoder.out_of_line_offset(bytes_len);
1991 encode_array_value::<T, D>(slice, encoder, offset, depth)
1992}
1993
1994#[inline]
1995unsafe fn encode_vector_resource<T: ResourceTypeMarker + TypeMarker, D: ResourceDialect>(
1996 slice: &mut [T::Owned],
1997 max_length: usize,
1998 encoder: &mut Encoder<'_, D>,
1999 offset: usize,
2000 mut depth: Depth,
2001) -> Result<()>
2002where
2003 for<'a> T::Borrowed<'a>: Encode<T, D>,
2004{
2005 encoder.write_num(slice.len() as u64, offset);
2006 encoder.write_num(ALLOC_PRESENT_U64, offset + 8);
2007 if slice.is_empty() {
2009 return Ok(());
2010 }
2011 check_vector_length(slice.len(), max_length)?;
2012 depth.increment()?;
2013 let bytes_len = slice.len() * T::inline_size(encoder.context);
2014 let offset = encoder.out_of_line_offset(bytes_len);
2015 encode_array_resource::<T, D>(slice, encoder, offset, depth)
2016}
2017
2018#[inline]
2019unsafe fn decode_vector<T: TypeMarker, D: ResourceDialect>(
2020 vec: &mut Vec<T::Owned>,
2021 max_length: usize,
2022 decoder: &mut Decoder<'_, D>,
2023 offset: usize,
2024 mut depth: Depth,
2025) -> Result<()>
2026where
2027 T::Owned: Decode<T, D>,
2028{
2029 let Some(len) = decode_vector_header(decoder, offset)? else {
2030 return Err(Error::NotNullable);
2031 };
2032 if len == 0 {
2034 return Ok(());
2035 }
2036 check_vector_length(len, max_length)?;
2037 depth.increment()?;
2038 let bytes_len = len * T::inline_size(decoder.context);
2039 let offset = decoder.out_of_line_offset(bytes_len)?;
2040 if T::decode_is_copy() {
2041 unsafe {
2044 resize_vec_no_zeroing(vec, len);
2045 }
2046 } else {
2047 vec.resize_with(len, T::Owned::new_empty);
2048 }
2049 decode_array::<T, D>(vec, decoder, offset, depth)?;
2051 Ok(())
2052}
2053
2054#[doc(hidden)] #[inline]
2058pub fn decode_vector_header<D: ResourceDialect>(
2059 decoder: &mut Decoder<'_, D>,
2060 offset: usize,
2061) -> Result<Option<usize>> {
2062 let len = decoder.read_num::<u64>(offset) as usize;
2063 match decoder.read_num::<u64>(offset + 8) {
2064 ALLOC_PRESENT_U64 => {
2065 if len <= u32::MAX as usize && len <= decoder.buf.len() {
2069 Ok(Some(len))
2070 } else {
2071 Err(Error::OutOfRange { expected: len, actual: decoder.buf.len() })
2072 }
2073 }
2074 ALLOC_ABSENT_U64 => {
2075 if len == 0 {
2076 Ok(None)
2077 } else {
2078 Err(Error::UnexpectedNullRef)
2079 }
2080 }
2081 _ => Err(Error::InvalidPresenceIndicator),
2082 }
2083}
2084
2085#[inline(always)]
2086fn check_vector_length(actual_length: usize, max_length: usize) -> Result<()> {
2087 if actual_length > max_length {
2088 return Err(Error::VectorTooLong { max_length, actual_length });
2089 }
2090 Ok(())
2091}
2092
2093pub struct BoundedString<const N: usize>;
2099
2100pub type UnboundedString = BoundedString<MAX_BOUND>;
2102
2103unsafe impl<const N: usize> TypeMarker for BoundedString<N> {
2104 type Owned = String;
2105
2106 #[inline(always)]
2107 fn inline_align(_context: Context) -> usize {
2108 8
2109 }
2110
2111 #[inline(always)]
2112 fn inline_size(_context: Context) -> usize {
2113 16
2114 }
2115}
2116
2117impl<const N: usize> ValueTypeMarker for BoundedString<N> {
2118 type Borrowed<'a> = &'a str;
2119 #[inline(always)]
2120 fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
2121 value
2122 }
2123}
2124
2125unsafe impl<const N: usize, D: ResourceDialect> Encode<BoundedString<N>, D> for &str {
2126 #[inline]
2127 unsafe fn encode(
2128 self,
2129 encoder: &mut Encoder<'_, D>,
2130 offset: usize,
2131 depth: Depth,
2132 ) -> Result<()> {
2133 encoder.debug_check_bounds::<BoundedString<N>>(offset);
2134 encode_vector_value::<u8, D>(
2135 self.as_bytes(),
2136 N,
2137 check_string_length,
2138 encoder,
2139 offset,
2140 depth,
2141 )
2142 }
2143}
2144
2145impl<const N: usize, D: ResourceDialect> Decode<BoundedString<N>, D> for String {
2146 #[inline(always)]
2147 fn new_empty() -> Self {
2148 String::new()
2149 }
2150
2151 #[inline]
2152 unsafe fn decode(
2153 &mut self,
2154 decoder: &mut Decoder<'_, D>,
2155 offset: usize,
2156 depth: Depth,
2157 ) -> Result<()> {
2158 decoder.debug_check_bounds::<BoundedString<N>>(offset);
2159 decode_string(self, N, decoder, offset, depth)
2160 }
2161}
2162
2163#[inline]
2164fn decode_string<D: ResourceDialect>(
2165 string: &mut String,
2166 max_length: usize,
2167 decoder: &mut Decoder<'_, D>,
2168 offset: usize,
2169 mut depth: Depth,
2170) -> Result<()> {
2171 let Some(len) = decode_vector_header(decoder, offset)? else {
2172 return Err(Error::NotNullable);
2173 };
2174 if len == 0 {
2176 return Ok(());
2177 }
2178 check_string_length(len, max_length)?;
2179 depth.increment()?;
2180 let offset = unsafe { decoder.out_of_line_offset(len)? };
2182 let bytes = unsafe { &decoder.buf.get_unchecked(offset..offset + len) };
2184 let utf8 = str::from_utf8(bytes).map_err(|_| Error::Utf8Error)?;
2185 let boxed_utf8: Box<str> = utf8.into();
2186 *string = boxed_utf8.into_string();
2187 Ok(())
2188}
2189
2190#[inline(always)]
2191fn check_string_length(actual_bytes: usize, max_bytes: usize) -> Result<()> {
2192 if actual_bytes > max_bytes {
2193 return Err(Error::StringTooLong { max_bytes, actual_bytes });
2194 }
2195 Ok(())
2196}
2197
2198impl<T: HandleBased> EncodableAsHandle for T {
2203 type Dialect = DefaultFuchsiaResourceDialect;
2204}
2205
2206pub struct HandleType<T: EncodableAsHandle, const OBJECT_TYPE: u32, const RIGHTS: u32>(
2208 PhantomData<T>,
2209);
2210
2211pub type Endpoint<T> = HandleType<
2214 T,
2215 { crate::ObjectType::CHANNEL.into_raw() },
2216 { crate::Rights::CHANNEL_DEFAULT.bits() },
2217>;
2218
2219unsafe impl<T: 'static + EncodableAsHandle, const OBJECT_TYPE: u32, const RIGHTS: u32> TypeMarker
2220 for HandleType<T, OBJECT_TYPE, RIGHTS>
2221{
2222 type Owned = T;
2223
2224 #[inline(always)]
2225 fn inline_align(_context: Context) -> usize {
2226 4
2227 }
2228
2229 #[inline(always)]
2230 fn inline_size(_context: Context) -> usize {
2231 4
2232 }
2233}
2234
2235impl<T: 'static + EncodableAsHandle, const OBJECT_TYPE: u32, const RIGHTS: u32> ResourceTypeMarker
2236 for HandleType<T, OBJECT_TYPE, RIGHTS>
2237{
2238 type Borrowed<'a> = T;
2239 #[inline(always)]
2240 fn take_or_borrow(value: &mut <Self as TypeMarker>::Owned) -> Self::Borrowed<'_> {
2241 mem::replace(value, <T::Dialect as ResourceDialect>::Handle::invalid().into())
2242 }
2243}
2244
2245unsafe impl<T: 'static + EncodableAsHandle, const OBJECT_TYPE: u32, const RIGHTS: u32>
2246 Encode<HandleType<T, OBJECT_TYPE, RIGHTS>, T::Dialect> for T
2247{
2248 #[inline]
2249 unsafe fn encode(
2250 self,
2251 encoder: &mut Encoder<'_, T::Dialect>,
2252 offset: usize,
2253 _depth: Depth,
2254 ) -> Result<()> {
2255 encoder.debug_check_bounds::<HandleType<T, OBJECT_TYPE, RIGHTS>>(offset);
2256 encode_handle(
2257 self.into(),
2258 crate::ObjectType::from_raw(OBJECT_TYPE),
2259 crate::Rights::from_bits_retain(RIGHTS),
2260 encoder,
2261 offset,
2262 )
2263 }
2264}
2265
2266impl<T: 'static + EncodableAsHandle, const OBJECT_TYPE: u32, const RIGHTS: u32>
2267 Decode<HandleType<T, OBJECT_TYPE, RIGHTS>, T::Dialect> for T
2268{
2269 #[inline(always)]
2270 fn new_empty() -> Self {
2271 <T::Dialect as ResourceDialect>::Handle::invalid().into()
2272 }
2273
2274 #[inline]
2275 unsafe fn decode(
2276 &mut self,
2277 decoder: &mut Decoder<'_, T::Dialect>,
2278 offset: usize,
2279 _depth: Depth,
2280 ) -> Result<()> {
2281 decoder.debug_check_bounds::<HandleType<T, OBJECT_TYPE, RIGHTS>>(offset);
2282 *self = decode_handle(
2283 crate::ObjectType::from_raw(OBJECT_TYPE),
2284 crate::Rights::from_bits_retain(RIGHTS),
2285 decoder,
2286 offset,
2287 )?
2288 .into();
2289 Ok(())
2290 }
2291}
2292
2293#[inline]
2294unsafe fn encode_handle<D: ResourceDialect>(
2295 handle: D::Handle,
2296 object_type: crate::ObjectType,
2297 rights: crate::Rights,
2298 encoder: &mut Encoder<'_, D>,
2299 offset: usize,
2300) -> Result<()> {
2301 if handle.is_invalid() {
2302 return Err(Error::NotNullable);
2303 }
2304 encoder.write_num(ALLOC_PRESENT_U32, offset);
2305 encoder.handles.push(<D::ProxyChannel as ProxyChannelFor<D>>::HandleDisposition::from_handle(
2306 handle,
2307 object_type,
2308 rights,
2309 ));
2310 Ok(())
2311}
2312
2313#[inline]
2314unsafe fn decode_handle<D: ResourceDialect>(
2315 object_type: crate::ObjectType,
2316 rights: crate::Rights,
2317 decoder: &mut Decoder<'_, D>,
2318 offset: usize,
2319) -> Result<D::Handle> {
2320 match decoder.read_num::<u32>(offset) {
2321 ALLOC_PRESENT_U32 => {}
2322 ALLOC_ABSENT_U32 => return Err(Error::NotNullable),
2323 _ => return Err(Error::InvalidPresenceIndicator),
2324 }
2325 decoder.take_next_handle(object_type, rights)
2326}
2327
2328pub struct Optional<T: TypeMarker>(PhantomData<T>);
2334
2335pub struct OptionalUnion<T: TypeMarker>(PhantomData<T>);
2337
2338pub struct Boxed<T: TypeMarker>(PhantomData<T>);
2340
2341unsafe impl<T: TypeMarker> TypeMarker for Optional<T> {
2342 type Owned = Option<T::Owned>;
2343
2344 #[inline(always)]
2345 fn inline_align(context: Context) -> usize {
2346 T::inline_align(context)
2347 }
2348
2349 #[inline(always)]
2350 fn inline_size(context: Context) -> usize {
2351 T::inline_size(context)
2352 }
2353}
2354
2355unsafe impl<T: TypeMarker> TypeMarker for OptionalUnion<T> {
2356 type Owned = Option<Box<T::Owned>>;
2357
2358 #[inline(always)]
2359 fn inline_align(context: Context) -> usize {
2360 T::inline_align(context)
2361 }
2362
2363 #[inline(always)]
2364 fn inline_size(context: Context) -> usize {
2365 T::inline_size(context)
2366 }
2367}
2368
2369unsafe impl<T: TypeMarker> TypeMarker for Boxed<T> {
2370 type Owned = Option<Box<T::Owned>>;
2371
2372 #[inline(always)]
2373 fn inline_align(_context: Context) -> usize {
2374 8
2375 }
2376
2377 #[inline(always)]
2378 fn inline_size(_context: Context) -> usize {
2379 8
2380 }
2381}
2382
2383impl<T: ValueTypeMarker> ValueTypeMarker for Optional<T> {
2384 type Borrowed<'a> = Option<T::Borrowed<'a>>;
2385
2386 #[inline(always)]
2387 fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
2388 value.as_ref().map(T::borrow)
2389 }
2390}
2391
2392impl<T: ValueTypeMarker> ValueTypeMarker for OptionalUnion<T> {
2393 type Borrowed<'a> = Option<T::Borrowed<'a>>;
2394
2395 #[inline(always)]
2396 fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
2397 value.as_deref().map(T::borrow)
2398 }
2399}
2400
2401impl<T: ValueTypeMarker> ValueTypeMarker for Boxed<T> {
2402 type Borrowed<'a> = Option<T::Borrowed<'a>>;
2403
2404 #[inline(always)]
2405 fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
2406 value.as_deref().map(T::borrow)
2407 }
2408}
2409
2410impl<T: ResourceTypeMarker + TypeMarker> ResourceTypeMarker for Optional<T> {
2411 type Borrowed<'a> = Option<T::Borrowed<'a>>;
2412 #[inline(always)]
2413 fn take_or_borrow(value: &mut <Self as TypeMarker>::Owned) -> Self::Borrowed<'_> {
2414 value.as_mut().map(T::take_or_borrow)
2415 }
2416}
2417
2418impl<T: ResourceTypeMarker + TypeMarker> ResourceTypeMarker for OptionalUnion<T> {
2419 type Borrowed<'a> = Option<T::Borrowed<'a>>;
2420 #[inline(always)]
2421 fn take_or_borrow(value: &mut <Self as TypeMarker>::Owned) -> Self::Borrowed<'_> {
2422 value.as_deref_mut().map(T::take_or_borrow)
2423 }
2424}
2425
2426impl<T: ResourceTypeMarker + TypeMarker> ResourceTypeMarker for Boxed<T> {
2427 type Borrowed<'a> = Option<T::Borrowed<'a>>;
2428 #[inline(always)]
2429 fn take_or_borrow(value: &mut <Self as TypeMarker>::Owned) -> Self::Borrowed<'_> {
2430 value.as_deref_mut().map(T::take_or_borrow)
2431 }
2432}
2433
2434unsafe impl<T: TypeMarker, E: Encode<T, D>, D: ResourceDialect> Encode<Optional<T>, D>
2435 for Option<E>
2436{
2437 #[inline]
2438 unsafe fn encode(
2439 self,
2440 encoder: &mut Encoder<'_, D>,
2441 offset: usize,
2442 depth: Depth,
2443 ) -> Result<()> {
2444 encoder.debug_check_bounds::<Optional<T>>(offset);
2445 encode_naturally_optional::<T, E, D>(self, encoder, offset, depth)
2446 }
2447}
2448
2449unsafe impl<T: TypeMarker, E: Encode<T, D>, D: ResourceDialect> Encode<OptionalUnion<T>, D>
2450 for Option<E>
2451{
2452 #[inline]
2453 unsafe fn encode(
2454 self,
2455 encoder: &mut Encoder<'_, D>,
2456 offset: usize,
2457 depth: Depth,
2458 ) -> Result<()> {
2459 encoder.debug_check_bounds::<OptionalUnion<T>>(offset);
2460 encode_naturally_optional::<T, E, D>(self, encoder, offset, depth)
2461 }
2462}
2463
2464unsafe impl<T: TypeMarker, E: Encode<T, D>, D: ResourceDialect> Encode<Boxed<T>, D> for Option<E> {
2465 #[inline]
2466 unsafe fn encode(
2467 self,
2468 encoder: &mut Encoder<'_, D>,
2469 offset: usize,
2470 mut depth: Depth,
2471 ) -> Result<()> {
2472 encoder.debug_check_bounds::<Boxed<T>>(offset);
2473 match self {
2474 Some(val) => {
2475 depth.increment()?;
2476 encoder.write_num(ALLOC_PRESENT_U64, offset);
2477 let offset = encoder.out_of_line_offset(T::inline_size(encoder.context));
2478 val.encode(encoder, offset, depth)?;
2479 }
2480 None => encoder.write_num(ALLOC_ABSENT_U64, offset),
2481 }
2482 Ok(())
2483 }
2484}
2485
2486impl<T: TypeMarker, D: ResourceDialect> Decode<Optional<T>, D> for Option<T::Owned>
2487where
2488 T::Owned: Decode<T, D>,
2489{
2490 #[inline(always)]
2491 fn new_empty() -> Self {
2492 None
2493 }
2494
2495 #[inline]
2496 unsafe fn decode(
2497 &mut self,
2498 decoder: &mut Decoder<'_, D>,
2499 offset: usize,
2500 depth: Depth,
2501 ) -> Result<()> {
2502 decoder.debug_check_bounds::<Optional<T>>(offset);
2503 let inline_size = T::inline_size(decoder.context);
2504 if check_for_presence(decoder, offset, inline_size) {
2505 self.get_or_insert(T::Owned::new_empty()).decode(decoder, offset, depth)
2506 } else {
2507 *self = None;
2508 decoder.check_padding(offset, inline_size)?;
2509 Ok(())
2510 }
2511 }
2512}
2513
2514impl<T: TypeMarker, D: ResourceDialect> Decode<OptionalUnion<T>, D> for Option<Box<T::Owned>>
2515where
2516 T::Owned: Decode<T, D>,
2517{
2518 #[inline(always)]
2519 fn new_empty() -> Self {
2520 None
2521 }
2522
2523 #[inline]
2524 unsafe fn decode(
2525 &mut self,
2526 decoder: &mut Decoder<'_, D>,
2527 offset: usize,
2528 depth: Depth,
2529 ) -> Result<()> {
2530 decoder.debug_check_bounds::<OptionalUnion<T>>(offset);
2531 let inline_size = T::inline_size(decoder.context);
2532 if check_for_presence(decoder, offset, inline_size) {
2533 decode!(
2534 T,
2535 self.get_or_insert_with(|| Box::new(T::Owned::new_empty())),
2536 decoder,
2537 offset,
2538 depth
2539 )
2540 } else {
2541 *self = None;
2542 decoder.check_padding(offset, inline_size)?;
2543 Ok(())
2544 }
2545 }
2546}
2547
2548impl<T: TypeMarker, D: ResourceDialect> Decode<Boxed<T>, D> for Option<Box<T::Owned>>
2549where
2550 T::Owned: Decode<T, D>,
2551{
2552 #[inline(always)]
2553 fn new_empty() -> Self {
2554 None
2555 }
2556
2557 #[inline]
2558 unsafe fn decode(
2559 &mut self,
2560 decoder: &mut Decoder<'_, D>,
2561 offset: usize,
2562 mut depth: Depth,
2563 ) -> Result<()> {
2564 decoder.debug_check_bounds::<Boxed<T>>(offset);
2565 match decoder.read_num::<u64>(offset) {
2566 ALLOC_PRESENT_U64 => {
2567 depth.increment()?;
2568 let offset = decoder.out_of_line_offset(T::inline_size(decoder.context))?;
2569 decode!(
2570 T,
2571 self.get_or_insert_with(|| Box::new(T::Owned::new_empty())),
2572 decoder,
2573 offset,
2574 depth
2575 )?;
2576 Ok(())
2577 }
2578 ALLOC_ABSENT_U64 => {
2579 *self = None;
2580 Ok(())
2581 }
2582 _ => Err(Error::InvalidPresenceIndicator),
2583 }
2584 }
2585}
2586
2587#[inline]
2590unsafe fn encode_naturally_optional<T: TypeMarker, E: Encode<T, D>, D: ResourceDialect>(
2591 value: Option<E>,
2592 encoder: &mut Encoder<'_, D>,
2593 offset: usize,
2594 depth: Depth,
2595) -> Result<()> {
2596 match value {
2597 Some(val) => val.encode(encoder, offset, depth)?,
2598 None => encoder.padding(offset, T::inline_size(encoder.context)),
2599 }
2600 Ok(())
2601}
2602
2603#[inline]
2607fn check_for_presence<D: ResourceDialect>(
2608 decoder: &Decoder<'_, D>,
2609 offset: usize,
2610 inline_size: usize,
2611) -> bool {
2612 debug_assert!(offset + inline_size <= decoder.buf.len());
2613 let range = unsafe { decoder.buf.get_unchecked(offset..offset + inline_size) };
2614 range.iter().any(|byte| *byte != 0)
2615}
2616
2617#[doc(hidden)] #[inline]
2623pub unsafe fn encode_in_envelope<T: TypeMarker, D: ResourceDialect>(
2624 val: impl Encode<T, D>,
2625 encoder: &mut Encoder<'_, D>,
2626 offset: usize,
2627 mut depth: Depth,
2628) -> Result<()> {
2629 depth.increment()?;
2630 let bytes_before = encoder.buf.len();
2631 let handles_before = encoder.handles.len();
2632 let inline_size = T::inline_size(encoder.context);
2633 if inline_size <= 4 {
2634 encoder.write_num(1u64 << 48, offset);
2636 val.encode(encoder, offset, depth)?;
2637 let handles_written = (encoder.handles.len() - handles_before) as u16;
2638 encoder.write_num(handles_written, offset + 4);
2639 } else {
2640 let out_of_line_offset = encoder.out_of_line_offset(inline_size);
2641 val.encode(encoder, out_of_line_offset, depth)?;
2642 let bytes_written = (encoder.buf.len() - bytes_before) as u32;
2643 let handles_written = (encoder.handles.len() - handles_before) as u32;
2644 debug_assert_eq!(bytes_written % 8, 0);
2645 encoder.write_num(bytes_written, offset);
2646 encoder.write_num(handles_written, offset + 4);
2647 }
2648 Ok(())
2649}
2650
2651#[doc(hidden)] #[inline]
2653pub unsafe fn encode_in_envelope_optional<T: TypeMarker, D: ResourceDialect>(
2654 val: Option<impl Encode<T, D>>,
2655 encoder: &mut Encoder<'_, D>,
2656 offset: usize,
2657 depth: Depth,
2658) -> Result<()> {
2659 match val {
2660 None => encoder.write_num(0u64, offset),
2661 Some(val) => encode_in_envelope(val, encoder, offset, depth)?,
2662 }
2663 Ok(())
2664}
2665
2666#[doc(hidden)] #[inline(always)]
2670pub unsafe fn decode_envelope_header<D: ResourceDialect>(
2671 decoder: &mut Decoder<'_, D>,
2672 offset: usize,
2673) -> Result<Option<(bool, u32, u32)>> {
2674 let num_bytes = decoder.read_num::<u32>(offset);
2675 let num_handles = decoder.read_num::<u16>(offset + 4) as u32;
2676 let inlined = decoder.read_num::<u16>(offset + 6);
2677 match (num_bytes, num_handles, inlined) {
2678 (0, 0, 0) => Ok(None),
2679 (_, _, 1) => Ok(Some((true, 4, num_handles))),
2680 (_, _, 0) if num_bytes.is_multiple_of(8) => Ok(Some((false, num_bytes, num_handles))),
2681 (_, _, 0) => Err(Error::InvalidNumBytesInEnvelope),
2682 _ => Err(Error::InvalidInlineMarkerInEnvelope),
2683 }
2684}
2685
2686#[doc(hidden)] #[inline]
2689pub unsafe fn decode_unknown_envelope<D: ResourceDialect>(
2690 decoder: &mut Decoder<'_, D>,
2691 offset: usize,
2692 mut depth: Depth,
2693) -> Result<()> {
2694 if let Some((inlined, num_bytes, num_handles)) = decode_envelope_header(decoder, offset)? {
2695 if !inlined {
2696 depth.increment()?;
2697 if num_bytes != 0 {
2699 let _ = decoder.out_of_line_offset(num_bytes as usize)?;
2700 }
2701 }
2702 if num_handles != 0 {
2703 for _ in 0..num_handles {
2704 decoder.drop_next_handle()?;
2705 }
2706 }
2707 }
2708 Ok(())
2709}
2710
2711#[doc(hidden)] #[inline]
2719pub unsafe fn decode_union_inline_portion<D: ResourceDialect>(
2720 decoder: &mut Decoder<'_, D>,
2721 offset: usize,
2722) -> Result<(u64, bool, u32, u32)> {
2723 let ordinal = decoder.read_num::<u64>(offset);
2724 match decode_envelope_header(decoder, offset + 8)? {
2725 Some((inlined, num_bytes, num_handles)) => Ok((ordinal, inlined, num_bytes, num_handles)),
2726 None => Err(Error::NotNullable),
2727 }
2728}
2729
2730pub struct ResultType<T: TypeMarker, E: TypeMarker>(PhantomData<(T, E)>);
2736
2737pub struct FlexibleType<T: TypeMarker>(PhantomData<T>);
2739
2740pub struct FlexibleResultType<T: TypeMarker, E: TypeMarker>(PhantomData<(T, E)>);
2742
2743#[doc(hidden)] #[derive(Debug)]
2746pub enum Flexible<T> {
2747 Ok(T),
2748 FrameworkErr(FrameworkErr),
2749}
2750
2751#[doc(hidden)] #[derive(Debug)]
2754pub enum FlexibleResult<T, E> {
2755 Ok(T),
2756 DomainErr(E),
2757 FrameworkErr(FrameworkErr),
2758}
2759
2760#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
2762#[repr(i32)]
2763pub enum FrameworkErr {
2764 UnknownMethod = zx_types::ZX_ERR_NOT_SUPPORTED,
2766}
2767
2768impl FrameworkErr {
2769 #[inline]
2770 fn from_primitive(prim: i32) -> Option<Self> {
2771 match prim {
2772 zx_types::ZX_ERR_NOT_SUPPORTED => Some(Self::UnknownMethod),
2773 _ => None,
2774 }
2775 }
2776
2777 #[inline(always)]
2778 const fn into_primitive(self) -> i32 {
2779 self as i32
2780 }
2781}
2782
2783unsafe impl TypeMarker for FrameworkErr {
2784 type Owned = Self;
2785 #[inline(always)]
2786 fn inline_align(_context: Context) -> usize {
2787 std::mem::align_of::<i32>()
2788 }
2789
2790 #[inline(always)]
2791 fn inline_size(_context: Context) -> usize {
2792 std::mem::size_of::<i32>()
2793 }
2794
2795 #[inline(always)]
2796 fn encode_is_copy() -> bool {
2797 true
2798 }
2799
2800 #[inline(always)]
2801 fn decode_is_copy() -> bool {
2802 false
2803 }
2804}
2805
2806impl ValueTypeMarker for FrameworkErr {
2807 type Borrowed<'a> = Self;
2808 #[inline(always)]
2809 fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
2810 *value
2811 }
2812}
2813
2814unsafe impl<D: ResourceDialect> Encode<Self, D> for FrameworkErr {
2815 #[inline]
2816 unsafe fn encode(
2817 self,
2818 encoder: &mut Encoder<'_, D>,
2819 offset: usize,
2820 _depth: Depth,
2821 ) -> Result<()> {
2822 encoder.debug_check_bounds::<Self>(offset);
2823 encoder.write_num(self.into_primitive(), offset);
2824 Ok(())
2825 }
2826}
2827
2828impl<D: ResourceDialect> Decode<Self, D> for FrameworkErr {
2829 #[inline(always)]
2830 fn new_empty() -> Self {
2831 Self::UnknownMethod
2832 }
2833
2834 #[inline]
2835 unsafe fn decode(
2836 &mut self,
2837 decoder: &mut Decoder<'_, D>,
2838 offset: usize,
2839 _depth: Depth,
2840 ) -> Result<()> {
2841 decoder.debug_check_bounds::<Self>(offset);
2842 let prim = decoder.read_num::<i32>(offset);
2843 *self = Self::from_primitive(prim).ok_or(Error::InvalidEnumValue)?;
2844 Ok(())
2845 }
2846}
2847
2848impl<T> Flexible<T> {
2849 pub fn new(value: T) -> Self {
2851 Self::Ok(value)
2852 }
2853
2854 pub fn into_result<P: ProtocolMarker>(self, method_name: &'static str) -> Result<T> {
2856 match self {
2857 Flexible::Ok(ok) => Ok(ok),
2858 Flexible::FrameworkErr(FrameworkErr::UnknownMethod) => {
2859 Err(Error::UnsupportedMethod { method_name, protocol_name: P::DEBUG_NAME })
2860 }
2861 }
2862 }
2863}
2864
2865impl<T, E> FlexibleResult<T, E> {
2866 pub fn new(result: std::result::Result<T, E>) -> Self {
2868 match result {
2869 Ok(value) => Self::Ok(value),
2870 Err(err) => Self::DomainErr(err),
2871 }
2872 }
2873
2874 pub fn into_result<P: ProtocolMarker>(
2876 self,
2877 method_name: &'static str,
2878 ) -> Result<std::result::Result<T, E>> {
2879 match self {
2880 FlexibleResult::Ok(ok) => Ok(Ok(ok)),
2881 FlexibleResult::DomainErr(err) => Ok(Err(err)),
2882 FlexibleResult::FrameworkErr(FrameworkErr::UnknownMethod) => {
2883 Err(Error::UnsupportedMethod { method_name, protocol_name: P::DEBUG_NAME })
2884 }
2885 }
2886 }
2887}
2888
2889macro_rules! impl_result_union {
2891 (
2892 params: [$($encode_param:ident: Encode<$type_param:ident>),*],
2893 ty: $ty:ty,
2894 owned: $owned:ty,
2895 encode: $encode:ty,
2896 members: [$(
2897 {
2898 ctor: { $($member_ctor:tt)* },
2899 ty: $member_ty:ty,
2900 ordinal: $member_ordinal:tt,
2901 },
2902 )*]
2903 ) => {
2904 unsafe impl<$($type_param: TypeMarker),*> TypeMarker for $ty {
2905 type Owned = $owned;
2906
2907 #[inline(always)]
2908 fn inline_align(_context: Context) -> usize {
2909 8
2910 }
2911
2912 #[inline(always)]
2913 fn inline_size(_context: Context) -> usize {
2914 16
2915 }
2916 }
2917
2918 unsafe impl<D: ResourceDialect, $($type_param: TypeMarker, $encode_param: Encode<$type_param, D>),*> Encode<$ty, D> for $encode {
2919 #[inline]
2920 unsafe fn encode(self, encoder: &mut Encoder<'_, D>, offset: usize, depth: Depth) -> Result<()> {
2921 encoder.debug_check_bounds::<$ty>(offset);
2922 match self {
2923 $(
2924 $($member_ctor)*(val) => {
2925 encoder.write_num::<u64>($member_ordinal, offset);
2926 encode_in_envelope::<$member_ty, D>(val, encoder, offset + 8, depth)
2927 }
2928 )*
2929 }
2930 }
2931 }
2932
2933 impl<D: ResourceDialect, $($type_param: TypeMarker),*> Decode<$ty, D> for $owned
2934 where $($type_param::Owned: Decode<$type_param, D>),*
2935 {
2936 #[inline(always)]
2937 fn new_empty() -> Self {
2938 #![allow(unreachable_code)]
2939 $(
2940 return $($member_ctor)*(new_empty!($member_ty, D));
2941 )*
2942 }
2943
2944 #[inline]
2945 unsafe fn decode(&mut self, decoder: &mut Decoder<'_, D>, offset: usize, mut depth: Depth) -> Result<()> {
2946 decoder.debug_check_bounds::<$ty>(offset);
2947 let next_out_of_line = decoder.next_out_of_line();
2948 let handles_before = decoder.remaining_handles();
2949 let (ordinal, inlined, num_bytes, num_handles) = decode_union_inline_portion(decoder, offset)?;
2950 let member_inline_size = match ordinal {
2951 $(
2952 $member_ordinal => <$member_ty as TypeMarker>::inline_size(decoder.context),
2953 )*
2954 _ => return Err(Error::UnknownUnionTag),
2955 };
2956 if inlined != (member_inline_size <= 4) {
2957 return Err(Error::InvalidInlineBitInEnvelope);
2958 }
2959 let inner_offset;
2960 if inlined {
2961 decoder.check_inline_envelope_padding(offset + 8, member_inline_size)?;
2962 inner_offset = offset + 8;
2963 } else {
2964 depth.increment()?;
2965 inner_offset = decoder.out_of_line_offset(member_inline_size)?;
2966 }
2967 match ordinal {
2968 $(
2969 $member_ordinal => {
2970 #[allow(irrefutable_let_patterns)]
2971 if let $($member_ctor)*(_) = self {
2972 } else {
2974 *self = $($member_ctor)*(new_empty!($member_ty, D));
2976 }
2977 #[allow(irrefutable_let_patterns)]
2978 if let $($member_ctor)*(ref mut val) = self {
2979 decode!($member_ty, D, val, decoder, inner_offset, depth)?;
2980 } else {
2981 unreachable!()
2982 }
2983 }
2984 )*
2985 ordinal => panic!("unexpected ordinal {:?}", ordinal)
2986 }
2987 if !inlined && decoder.next_out_of_line() != next_out_of_line + (num_bytes as usize) {
2988 return Err(Error::InvalidNumBytesInEnvelope);
2989 }
2990 if handles_before != decoder.remaining_handles() + (num_handles as usize) {
2991 return Err(Error::InvalidNumHandlesInEnvelope);
2992 }
2993 Ok(())
2994 }
2995 }
2996 };
2997}
2998
2999impl_result_union! {
3000 params: [X: Encode<T>, Y: Encode<E>],
3001 ty: ResultType<T, E>,
3002 owned: std::result::Result<T::Owned, E::Owned>,
3003 encode: std::result::Result<X, Y>,
3004 members: [
3005 { ctor: { Ok }, ty: T, ordinal: 1, },
3006 { ctor: { Err }, ty: E, ordinal: 2, },
3007 ]
3008}
3009
3010impl_result_union! {
3011 params: [X: Encode<T>],
3012 ty: FlexibleType<T>,
3013 owned: Flexible<T::Owned>,
3014 encode: Flexible<X>,
3015 members: [
3016 { ctor: { Flexible::Ok }, ty: T, ordinal: 1, },
3017 { ctor: { Flexible::FrameworkErr }, ty: FrameworkErr, ordinal: 3, },
3018 ]
3019}
3020
3021impl_result_union! {
3022 params: [X: Encode<T>, Y: Encode<E>],
3023 ty: FlexibleResultType<T, E>,
3024 owned: FlexibleResult<T::Owned, E::Owned>,
3025 encode: FlexibleResult<X, Y>,
3026 members: [
3027 { ctor: { FlexibleResult::Ok }, ty: T, ordinal: 1, },
3028 { ctor: { FlexibleResult::DomainErr }, ty: E, ordinal: 2, },
3029 { ctor: { FlexibleResult::FrameworkErr }, ty: FrameworkErr, ordinal: 3, },
3030 ]
3031}
3032
3033#[derive(Copy, Clone, Debug, Eq, PartialEq)]
3039pub struct EpitaphBody {
3040 pub error: zx_status::Status,
3042}
3043
3044unsafe impl TypeMarker for EpitaphBody {
3045 type Owned = Self;
3046
3047 #[inline(always)]
3048 fn inline_align(_context: Context) -> usize {
3049 4
3050 }
3051
3052 #[inline(always)]
3053 fn inline_size(_context: Context) -> usize {
3054 4
3055 }
3056}
3057
3058impl ValueTypeMarker for EpitaphBody {
3059 type Borrowed<'a> = &'a Self;
3060
3061 fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
3062 value
3063 }
3064}
3065
3066unsafe impl<D: ResourceDialect> Encode<EpitaphBody, D> for &EpitaphBody {
3067 #[inline]
3068 unsafe fn encode(
3069 self,
3070 encoder: &mut Encoder<'_, D>,
3071 offset: usize,
3072 _depth: Depth,
3073 ) -> Result<()> {
3074 encoder.debug_check_bounds::<EpitaphBody>(offset);
3075 encoder.write_num::<i32>(self.error.into_raw(), offset);
3076 Ok(())
3077 }
3078}
3079
3080impl<D: ResourceDialect> Decode<Self, D> for EpitaphBody {
3081 #[inline(always)]
3082 fn new_empty() -> Self {
3083 Self { error: zx_status::Status::from_raw(0) }
3084 }
3085
3086 #[inline]
3087 unsafe fn decode(
3088 &mut self,
3089 decoder: &mut Decoder<'_, D>,
3090 offset: usize,
3091 _depth: Depth,
3092 ) -> Result<()> {
3093 decoder.debug_check_bounds::<Self>(offset);
3094 self.error = zx_status::Status::from_raw(decoder.read_num::<i32>(offset));
3095 Ok(())
3096 }
3097}
3098
3099unsafe impl TypeMarker for ObjectType {
3104 type Owned = Self;
3105
3106 #[inline(always)]
3107 fn inline_align(_context: Context) -> usize {
3108 mem::align_of::<Self>()
3109 }
3110
3111 #[inline(always)]
3112 fn inline_size(_context: Context) -> usize {
3113 mem::size_of::<Self>()
3114 }
3115}
3116
3117impl ValueTypeMarker for ObjectType {
3118 type Borrowed<'a> = Self;
3119
3120 fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
3121 *value
3122 }
3123}
3124
3125unsafe impl<D: ResourceDialect> Encode<ObjectType, D> for ObjectType {
3126 #[inline]
3127 unsafe fn encode(
3128 self,
3129 encoder: &mut Encoder<'_, D>,
3130 offset: usize,
3131 _depth: Depth,
3132 ) -> Result<()> {
3133 encoder.debug_check_bounds::<Self>(offset);
3134 encoder.write_num(self.into_raw(), offset);
3135 Ok(())
3136 }
3137}
3138
3139impl<D: ResourceDialect> Decode<Self, D> for ObjectType {
3140 #[inline(always)]
3141 fn new_empty() -> Self {
3142 ObjectType::NONE
3143 }
3144
3145 #[inline]
3146 unsafe fn decode(
3147 &mut self,
3148 decoder: &mut Decoder<'_, D>,
3149 offset: usize,
3150 _depth: Depth,
3151 ) -> Result<()> {
3152 decoder.debug_check_bounds::<Self>(offset);
3153 *self = Self::from_raw(decoder.read_num(offset));
3154 Ok(())
3155 }
3156}
3157
3158unsafe impl TypeMarker for Rights {
3159 type Owned = Self;
3160
3161 #[inline(always)]
3162 fn inline_align(_context: Context) -> usize {
3163 mem::align_of::<Self>()
3164 }
3165
3166 #[inline(always)]
3167 fn inline_size(_context: Context) -> usize {
3168 mem::size_of::<Self>()
3169 }
3170}
3171
3172impl ValueTypeMarker for Rights {
3173 type Borrowed<'a> = Self;
3174
3175 fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
3176 *value
3177 }
3178}
3179
3180unsafe impl<D: ResourceDialect> Encode<Rights, D> for Rights {
3181 #[inline]
3182 unsafe fn encode(
3183 self,
3184 encoder: &mut Encoder<'_, D>,
3185 offset: usize,
3186 _depth: Depth,
3187 ) -> Result<()> {
3188 encoder.debug_check_bounds::<Self>(offset);
3189 if self.bits() & Self::all().bits() != self.bits() {
3190 return Err(Error::InvalidBitsValue);
3191 }
3192 encoder.write_num(self.bits(), offset);
3193 Ok(())
3194 }
3195}
3196
3197impl<D: ResourceDialect> Decode<Self, D> for Rights {
3198 #[inline(always)]
3199 fn new_empty() -> Self {
3200 Rights::empty()
3201 }
3202
3203 #[inline]
3204 unsafe fn decode(
3205 &mut self,
3206 decoder: &mut Decoder<'_, D>,
3207 offset: usize,
3208 _depth: Depth,
3209 ) -> Result<()> {
3210 decoder.debug_check_bounds::<Self>(offset);
3211 *self = Self::from_bits(decoder.read_num(offset)).ok_or(Error::InvalidBitsValue)?;
3212 Ok(())
3213 }
3214}
3215
3216pub struct GenericMessageType<H: ValueTypeMarker, T: TypeMarker>(PhantomData<(H, T)>);
3222
3223pub struct GenericMessage<H, E> {
3225 pub header: H,
3227 pub body: E,
3229}
3230
3231pub enum GenericMessageOwned {}
3237
3238unsafe impl<H: ValueTypeMarker, T: TypeMarker> TypeMarker for GenericMessageType<H, T> {
3239 type Owned = GenericMessageOwned;
3240
3241 #[inline(always)]
3242 fn inline_align(context: Context) -> usize {
3243 std::cmp::max(H::inline_align(context), T::inline_align(context))
3244 }
3245
3246 #[inline(always)]
3247 fn inline_size(context: Context) -> usize {
3248 H::inline_size(context) + T::inline_size(context)
3249 }
3250}
3251
3252unsafe impl<H: ValueTypeMarker, T: TypeMarker, E: Encode<T, D>, D: ResourceDialect>
3253 Encode<GenericMessageType<H, T>, D> for GenericMessage<<H as TypeMarker>::Owned, E>
3254where
3255 for<'a> H::Borrowed<'a>: Encode<H, D>,
3256{
3257 #[inline]
3258 unsafe fn encode(
3259 self,
3260 encoder: &mut Encoder<'_, D>,
3261 offset: usize,
3262 depth: Depth,
3263 ) -> Result<()> {
3264 encoder.debug_check_bounds::<GenericMessageType<H, T>>(offset);
3265 H::borrow(&self.header).encode(encoder, offset, depth)?;
3266 self.body.encode(encoder, offset + H::inline_size(encoder.context), depth)
3267 }
3268}
3269
3270impl<H: ValueTypeMarker, T: TypeMarker, D: ResourceDialect> Decode<GenericMessageType<H, T>, D>
3271 for GenericMessageOwned
3272{
3273 fn new_empty() -> Self {
3274 panic!("cannot create GenericMessageOwned");
3275 }
3276
3277 unsafe fn decode(
3278 &mut self,
3279 _decoder: &mut Decoder<'_, D>,
3280 _offset: usize,
3281 _depth: Depth,
3282 ) -> Result<()> {
3283 match *self {}
3284 }
3285}
3286
3287pub type TransactionMessageType<T> = GenericMessageType<TransactionHeader, T>;
3293
3294pub type TransactionMessage<E> = GenericMessage<TransactionHeader, E>;
3296
3297#[derive(Copy, Clone, Debug, Eq, PartialEq)]
3299#[repr(C)]
3300pub struct TransactionHeader {
3301 pub tx_id: u32,
3303 pub at_rest_flags: [u8; 2],
3306 pub dynamic_flags: u8,
3309 pub magic_number: u8,
3312 pub ordinal: u64,
3314}
3315
3316impl TransactionHeader {
3317 #[inline]
3320 pub fn is_compatible(&self) -> bool {
3321 self.magic_number == MAGIC_NUMBER_INITIAL
3322 }
3323}
3324
3325bitflags! {
3326 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
3328 pub struct AtRestFlags: u16 {
3329 const USE_V2_WIRE_FORMAT = 2;
3335 }
3336}
3337
3338bitflags! {
3339 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
3342 pub struct DynamicFlags: u8 {
3343 const FLEXIBLE = 1 << 7;
3345 }
3346}
3347
3348impl From<AtRestFlags> for [u8; 2] {
3349 #[inline]
3350 fn from(value: AtRestFlags) -> Self {
3351 value.bits().to_le_bytes()
3352 }
3353}
3354
3355impl TransactionHeader {
3356 #[inline]
3358 pub fn new(tx_id: u32, ordinal: u64, dynamic_flags: DynamicFlags) -> Self {
3359 TransactionHeader::new_full(
3360 tx_id,
3361 ordinal,
3362 default_encode_context(),
3363 dynamic_flags,
3364 MAGIC_NUMBER_INITIAL,
3365 )
3366 }
3367
3368 #[inline]
3370 pub fn new_full(
3371 tx_id: u32,
3372 ordinal: u64,
3373 context: Context,
3374 dynamic_flags: DynamicFlags,
3375 magic_number: u8,
3376 ) -> Self {
3377 TransactionHeader {
3378 tx_id,
3379 at_rest_flags: context.at_rest_flags().into(),
3380 dynamic_flags: dynamic_flags.bits(),
3381 magic_number,
3382 ordinal,
3383 }
3384 }
3385
3386 #[inline]
3388 pub fn is_epitaph(&self) -> bool {
3389 self.ordinal == EPITAPH_ORDINAL
3390 }
3391
3392 #[inline]
3394 pub fn validate_wire_format(&self) -> Result<()> {
3395 if self.magic_number != MAGIC_NUMBER_INITIAL {
3396 return Err(Error::IncompatibleMagicNumber(self.magic_number));
3397 }
3398 if !self.at_rest_flags().contains(AtRestFlags::USE_V2_WIRE_FORMAT) {
3399 return Err(Error::UnsupportedWireFormatVersion);
3400 }
3401 Ok(())
3402 }
3403
3404 #[inline]
3407 pub fn validate_request_tx_id(&self, method_type: MethodType) -> Result<()> {
3408 match method_type {
3409 MethodType::OneWay if self.tx_id != 0 => Err(Error::InvalidRequestTxid),
3410 MethodType::TwoWay if self.tx_id == 0 => Err(Error::InvalidRequestTxid),
3411 _ => Ok(()),
3412 }
3413 }
3414
3415 #[inline]
3417 pub fn at_rest_flags(&self) -> AtRestFlags {
3418 AtRestFlags::from_bits_truncate(u16::from_le_bytes(self.at_rest_flags))
3419 }
3420
3421 #[inline]
3423 pub fn dynamic_flags(&self) -> DynamicFlags {
3424 DynamicFlags::from_bits_truncate(self.dynamic_flags)
3425 }
3426
3427 #[inline]
3431 pub fn decoding_context(&self) -> Context {
3432 Context { wire_format_version: WireFormatVersion::V2 }
3433 }
3434}
3435
3436pub fn decode_transaction_header(bytes: &[u8]) -> Result<(TransactionHeader, &[u8])> {
3439 let mut header = new_empty!(TransactionHeader, NoHandleResourceDialect);
3440 let context = Context { wire_format_version: WireFormatVersion::V2 };
3441 let header_len = <TransactionHeader as TypeMarker>::inline_size(context);
3442 if bytes.len() < header_len {
3443 return Err(Error::OutOfRange { expected: header_len, actual: bytes.len() });
3444 }
3445 let (header_bytes, body_bytes) = bytes.split_at(header_len);
3446 Decoder::<NoHandleResourceDialect>::decode_with_context::<TransactionHeader>(
3447 context,
3448 header_bytes,
3449 &mut [],
3450 &mut header,
3451 )
3452 .map_err(|_| Error::InvalidHeader)?;
3453 header.validate_wire_format()?;
3454 Ok((header, body_bytes))
3455}
3456
3457unsafe impl TypeMarker for TransactionHeader {
3458 type Owned = Self;
3459
3460 #[inline(always)]
3461 fn inline_align(_context: Context) -> usize {
3462 8
3463 }
3464
3465 #[inline(always)]
3466 fn inline_size(_context: Context) -> usize {
3467 16
3468 }
3469}
3470
3471impl ValueTypeMarker for TransactionHeader {
3472 type Borrowed<'a> = &'a Self;
3473
3474 fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
3475 value
3476 }
3477}
3478
3479unsafe impl<D: ResourceDialect> Encode<TransactionHeader, D> for &TransactionHeader {
3480 #[inline]
3481 unsafe fn encode(
3482 self,
3483 encoder: &mut Encoder<'_, D>,
3484 offset: usize,
3485 _depth: Depth,
3486 ) -> Result<()> {
3487 encoder.debug_check_bounds::<TransactionHeader>(offset);
3488 unsafe {
3489 let buf_ptr = encoder.buf.as_mut_ptr().add(offset);
3490 (buf_ptr as *mut TransactionHeader).write_unaligned(*self);
3491 }
3492 Ok(())
3493 }
3494}
3495
3496impl<D: ResourceDialect> Decode<Self, D> for TransactionHeader {
3497 #[inline(always)]
3498 fn new_empty() -> Self {
3499 Self { tx_id: 0, at_rest_flags: [0; 2], dynamic_flags: 0, magic_number: 0, ordinal: 0 }
3500 }
3501
3502 #[inline]
3503 unsafe fn decode(
3504 &mut self,
3505 decoder: &mut Decoder<'_, D>,
3506 offset: usize,
3507 _depth: Depth,
3508 ) -> Result<()> {
3509 decoder.debug_check_bounds::<Self>(offset);
3510 unsafe {
3511 let buf_ptr = decoder.buf.as_ptr().add(offset);
3512 let obj_ptr = self as *mut TransactionHeader;
3513 std::ptr::copy_nonoverlapping(buf_ptr, obj_ptr as *mut u8, 16);
3514 }
3515 Ok(())
3516 }
3517}
3518
3519pub struct TlsBuf<D: ResourceDialect> {
3526 bytes: Vec<u8>,
3527 encode_handles: Vec<<D::ProxyChannel as ProxyChannelFor<D>>::HandleDisposition>,
3528 decode_handles: Vec<<D::Handle as HandleFor<D>>::HandleInfo>,
3529}
3530
3531impl<D: ResourceDialect> Default for TlsBuf<D> {
3532 fn default() -> TlsBuf<D> {
3534 TlsBuf {
3535 bytes: Vec::with_capacity(MIN_BUF_BYTES_SIZE),
3536 encode_handles: Vec::new(),
3537 decode_handles: Vec::new(),
3538 }
3539 }
3540}
3541
3542#[inline]
3543fn with_tls_buf<D: ResourceDialect, R>(f: impl FnOnce(&mut TlsBuf<D>) -> R) -> R {
3544 D::with_tls_buf(f)
3545}
3546
3547pub(crate) const MIN_BUF_BYTES_SIZE: usize = 512;
3548
3549#[inline]
3553pub fn with_tls_encode_buf<R, D: ResourceDialect>(
3554 f: impl FnOnce(
3555 &mut Vec<u8>,
3556 &mut Vec<<D::ProxyChannel as ProxyChannelFor<D>>::HandleDisposition>,
3557 ) -> R,
3558) -> R {
3559 with_tls_buf::<D, R>(|buf| {
3560 let res = f(&mut buf.bytes, &mut buf.encode_handles);
3561 buf.bytes.clear();
3562 buf.encode_handles.clear();
3563 res
3564 })
3565}
3566
3567#[inline]
3571pub fn with_tls_decode_buf<R, D: ResourceDialect>(
3572 f: impl FnOnce(&mut Vec<u8>, &mut Vec<<D::Handle as HandleFor<D>>::HandleInfo>) -> R,
3573) -> R {
3574 with_tls_buf::<D, R>(|buf| {
3575 let res = f(&mut buf.bytes, &mut buf.decode_handles);
3576 buf.bytes.clear();
3577 buf.decode_handles.clear();
3578 res
3579 })
3580}
3581
3582#[inline]
3584pub fn clear_tls_buf<D: ResourceDialect>() {
3585 with_tls_buf::<D, ()>(|buf| {
3586 buf.bytes.clear();
3587 buf.bytes.shrink_to_fit();
3588 buf.encode_handles.clear();
3589 buf.encode_handles.shrink_to_fit();
3590 buf.decode_handles.clear();
3591 buf.decode_handles.shrink_to_fit();
3592 });
3593}
3594
3595#[inline]
3599pub fn with_tls_encoded<T: TypeMarker, D: ResourceDialect, Out>(
3600 val: impl Encode<T, D>,
3601 f: impl FnOnce(
3602 &mut Vec<u8>,
3603 &mut Vec<<D::ProxyChannel as ProxyChannelFor<D>>::HandleDisposition>,
3604 ) -> Result<Out>,
3605) -> Result<Out> {
3606 with_tls_encode_buf::<Result<Out>, D>(|bytes, handles| {
3607 Encoder::<D>::encode(bytes, handles, val)?;
3608 f(bytes, handles)
3609 })
3610}
3611
3612#[cfg(test)]
3617mod test {
3618 use super::*;
3619 use crate::handle::{AsHandleRef, convert_handle_dispositions_to_infos};
3620 use crate::time::{BootInstant, BootTicks, MonotonicInstant, MonotonicTicks};
3621 use assert_matches::assert_matches;
3622 use std::fmt;
3623
3624 const CONTEXTS: [Context; 1] = [Context { wire_format_version: WireFormatVersion::V2 }];
3625
3626 const OBJECT_TYPE_NONE: u32 = crate::handle::ObjectType::NONE.into_raw();
3627 const SAME_RIGHTS: u32 = crate::handle::Rights::SAME_RIGHTS.bits();
3628
3629 #[track_caller]
3630 fn to_infos(dispositions: &mut Vec<HandleDisposition<'_>>) -> Vec<HandleInfo> {
3631 convert_handle_dispositions_to_infos(mem::take(dispositions)).unwrap()
3632 }
3633
3634 #[track_caller]
3635 pub fn encode_decode<T: TypeMarker>(
3636 ctx: Context,
3637 start: impl Encode<T, DefaultFuchsiaResourceDialect>,
3638 ) -> T::Owned
3639 where
3640 T::Owned: Decode<T, DefaultFuchsiaResourceDialect>,
3641 {
3642 let buf = &mut Vec::new();
3643 let handle_buf = &mut Vec::new();
3644 Encoder::encode_with_context::<T>(ctx, buf, handle_buf, start).expect("Encoding failed");
3645 let mut out = T::Owned::new_empty();
3646 Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<T>(
3647 ctx,
3648 buf,
3649 &mut to_infos(handle_buf),
3650 &mut out,
3651 )
3652 .expect("Decoding failed");
3653 out
3654 }
3655
3656 #[track_caller]
3657 fn encode_assert_bytes<T: TypeMarker>(
3658 ctx: Context,
3659 data: impl Encode<T, DefaultFuchsiaResourceDialect>,
3660 encoded_bytes: &[u8],
3661 ) {
3662 let buf = &mut Vec::new();
3663 let handle_buf = &mut Vec::new();
3664 Encoder::encode_with_context::<T>(ctx, buf, handle_buf, data).expect("Encoding failed");
3665 assert_eq!(buf, encoded_bytes);
3666 }
3667
3668 #[track_caller]
3669 fn identity<T>(data: &T::Owned)
3670 where
3671 T: ValueTypeMarker,
3672 T::Owned: fmt::Debug + PartialEq + Decode<T, DefaultFuchsiaResourceDialect>,
3673 for<'a> T::Borrowed<'a>: Encode<T, DefaultFuchsiaResourceDialect>,
3674 {
3675 for ctx in CONTEXTS {
3676 assert_eq!(*data, encode_decode(ctx, T::borrow(data)));
3677 }
3678 }
3679
3680 #[track_caller]
3681 fn identities<T>(values: &[T::Owned])
3682 where
3683 T: ValueTypeMarker,
3684 T::Owned: fmt::Debug + PartialEq + Decode<T, DefaultFuchsiaResourceDialect>,
3685 for<'a> T::Borrowed<'a>: Encode<T, DefaultFuchsiaResourceDialect>,
3686 {
3687 for value in values {
3688 identity::<T>(value);
3689 }
3690 }
3691
3692 #[test]
3693 fn encode_decode_byte() {
3694 identities::<u8>(&[0u8, 57u8, 255u8]);
3695 identities::<i8>(&[0i8, -57i8, 12i8]);
3696 identity::<Optional<Vector<i32, 3>>>(&None::<Vec<i32>>);
3697 }
3698
3699 #[test]
3700 fn encode_decode_multibyte() {
3701 identities::<u64>(&[0u64, 1u64, u64::MAX, u64::MIN]);
3702 identities::<i64>(&[0i64, 1i64, i64::MAX, i64::MIN]);
3703 identities::<f32>(&[0f32, 1f32, f32::MAX, f32::MIN]);
3704 identities::<f64>(&[0f64, 1f64, f64::MAX, f64::MIN]);
3705 }
3706
3707 #[test]
3708 fn encode_decode_nan() {
3709 for ctx in CONTEXTS {
3710 assert!(encode_decode::<f32>(ctx, f32::NAN).is_nan());
3711 assert!(encode_decode::<f64>(ctx, f64::NAN).is_nan());
3712 }
3713 }
3714
3715 #[test]
3716 fn encode_decode_instants() {
3717 let monotonic = MonotonicInstant::from_nanos(987654321);
3718 let boot = BootInstant::from_nanos(987654321);
3719 let monotonic_ticks = MonotonicTicks::from_raw(111111111);
3720 let boot_ticks = BootTicks::from_raw(22222222);
3721 for ctx in CONTEXTS {
3722 assert_eq!(encode_decode::<BootInstant>(ctx, boot), boot);
3723 assert_eq!(encode_decode::<MonotonicInstant>(ctx, monotonic), monotonic);
3724 assert_eq!(encode_decode::<BootTicks>(ctx, boot_ticks), boot_ticks);
3725 assert_eq!(encode_decode::<MonotonicTicks>(ctx, monotonic_ticks), monotonic_ticks);
3726 }
3727 }
3728
3729 #[test]
3730 fn encode_decode_out_of_line() {
3731 type V<T> = UnboundedVector<T>;
3732 type S = UnboundedString;
3733 type O<T> = Optional<T>;
3734
3735 identity::<V<i32>>(&Vec::<i32>::new());
3736 identity::<V<i32>>(&vec![1, 2, 3]);
3737 identity::<O<V<i32>>>(&None::<Vec<i32>>);
3738 identity::<O<V<i32>>>(&Some(Vec::<i32>::new()));
3739 identity::<O<V<i32>>>(&Some(vec![1, 2, 3]));
3740 identity::<O<V<V<i32>>>>(&Some(vec![vec![1, 2, 3]]));
3741 identity::<O<V<O<V<i32>>>>>(&Some(vec![Some(vec![1, 2, 3])]));
3742 identity::<S>(&"".to_string());
3743 identity::<S>(&"foo".to_string());
3744 identity::<O<S>>(&None::<String>);
3745 identity::<O<S>>(&Some("".to_string()));
3746 identity::<O<S>>(&Some("foo".to_string()));
3747 identity::<O<V<O<S>>>>(&Some(vec![None, Some("foo".to_string())]));
3748 identity::<V<S>>(&vec!["foo".to_string(), "bar".to_string()]);
3749 }
3750
3751 #[test]
3752 fn array_of_arrays() {
3753 identity::<Array<Array<u32, 5>, 2>>(&[[1, 2, 3, 4, 5], [5, 4, 3, 2, 1]]);
3754 }
3755
3756 fn slice_identity<T>(start: &[T::Owned])
3757 where
3758 T: ValueTypeMarker,
3759 T::Owned: fmt::Debug + PartialEq + Decode<T, DefaultFuchsiaResourceDialect>,
3760 for<'a> T::Borrowed<'a>: Encode<T, DefaultFuchsiaResourceDialect>,
3761 {
3762 for ctx in CONTEXTS {
3763 let decoded = encode_decode::<UnboundedVector<T>>(ctx, start);
3764 assert_eq!(start, UnboundedVector::<T>::borrow(&decoded));
3765 }
3766 }
3767
3768 #[test]
3769 fn encode_slices_of_primitives() {
3770 slice_identity::<u8>(&[]);
3771 slice_identity::<u8>(&[0]);
3772 slice_identity::<u8>(&[1, 2, 3, 4, 5, 255]);
3773
3774 slice_identity::<i8>(&[]);
3775 slice_identity::<i8>(&[0]);
3776 slice_identity::<i8>(&[1, 2, 3, 4, 5, -128, 127]);
3777
3778 slice_identity::<u64>(&[]);
3779 slice_identity::<u64>(&[0]);
3780 slice_identity::<u64>(&[1, 2, 3, 4, 5, u64::MAX]);
3781
3782 slice_identity::<f32>(&[]);
3783 slice_identity::<f32>(&[0.0]);
3784 slice_identity::<f32>(&[1.0, 2.0, 3.0, 4.0, 5.0, f32::MIN, f32::MAX]);
3785
3786 slice_identity::<f64>(&[]);
3787 slice_identity::<f64>(&[0.0]);
3788 slice_identity::<f64>(&[1.0, 2.0, 3.0, 4.0, 5.0, f64::MIN, f64::MAX]);
3789 }
3790
3791 #[test]
3792 fn result_encode_empty_ok_value() {
3793 for ctx in CONTEXTS {
3794 encode_assert_bytes::<EmptyPayload>(ctx, (), &[]);
3796 }
3797 encode_assert_bytes::<ResultType<EmptyStruct, i32>>(
3800 Context { wire_format_version: WireFormatVersion::V2 },
3801 Ok::<(), i32>(()),
3802 &[
3803 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, ],
3808 );
3809 }
3810
3811 #[test]
3812 fn result_decode_empty_ok_value() {
3813 let mut result = Err(0);
3814 Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<ResultType<EmptyStruct, u32>>(
3815 Context { wire_format_version: WireFormatVersion::V2 },
3816 &[
3817 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, ],
3820 &mut [],
3821 &mut result,
3822 )
3823 .expect("Decoding failed");
3824 assert_matches!(result, Ok(()));
3825 }
3826
3827 #[test]
3828 fn encode_decode_result() {
3829 type Res = ResultType<UnboundedString, u32>;
3830 for ctx in CONTEXTS {
3831 assert_eq!(encode_decode::<Res>(ctx, Ok::<&str, u32>("foo")), Ok("foo".to_string()));
3832 assert_eq!(encode_decode::<Res>(ctx, Err::<&str, u32>(5)), Err(5));
3833 }
3834 }
3835
3836 #[test]
3837 fn result_validates_num_bytes() {
3838 type Res = ResultType<u64, u64>;
3839 for ctx in CONTEXTS {
3840 for ordinal in [1, 2] {
3841 let bytes = [
3843 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, ];
3848 let mut out = new_empty!(Res, DefaultFuchsiaResourceDialect);
3849 assert_matches!(
3850 Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<Res>(
3851 ctx,
3852 &bytes,
3853 &mut [],
3854 &mut out
3855 ),
3856 Err(Error::InvalidNumBytesInEnvelope)
3857 );
3858 }
3859 }
3860 }
3861
3862 #[test]
3863 fn result_validates_num_handles() {
3864 type Res = ResultType<u64, u64>;
3865 for ctx in CONTEXTS {
3866 for ordinal in [1, 2] {
3867 let bytes = [
3869 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, ];
3874 let mut out = new_empty!(Res, DefaultFuchsiaResourceDialect);
3875 assert_matches!(
3876 Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<Res>(
3877 ctx,
3878 &bytes,
3879 &mut [],
3880 &mut out
3881 ),
3882 Err(Error::InvalidNumHandlesInEnvelope)
3883 );
3884 }
3885 }
3886 }
3887
3888 #[test]
3889 fn decode_result_unknown_tag() {
3890 type Res = ResultType<u32, u32>;
3891 let ctx = Context { wire_format_version: WireFormatVersion::V2 };
3892
3893 let bytes: &[u8] = &[
3894 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3896 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
3898 ];
3899 let handle_buf = &mut Vec::<HandleInfo>::new();
3900
3901 let mut out = new_empty!(Res, DefaultFuchsiaResourceDialect);
3902 let res = Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<Res>(
3903 ctx, bytes, handle_buf, &mut out,
3904 );
3905 assert_matches!(res, Err(Error::UnknownUnionTag));
3906 }
3907
3908 #[test]
3909 fn decode_result_success_invalid_empty_struct() {
3910 type Res = ResultType<EmptyStruct, u32>;
3911 let ctx = Context { wire_format_version: WireFormatVersion::V2 };
3912
3913 let bytes: &[u8] = &[
3914 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3916 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
3918 ];
3919 let handle_buf = &mut Vec::<HandleInfo>::new();
3920
3921 let mut out = new_empty!(Res, DefaultFuchsiaResourceDialect);
3922 let res = Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<Res>(
3923 ctx, bytes, handle_buf, &mut out,
3924 );
3925 assert_matches!(res, Err(Error::Invalid));
3926 }
3927
3928 #[test]
3929 fn encode_decode_transaction_msg() {
3930 for ctx in CONTEXTS {
3931 let header = TransactionHeader {
3932 tx_id: 4,
3933 ordinal: 6,
3934 at_rest_flags: [2, 0],
3935 dynamic_flags: 0,
3936 magic_number: 1,
3937 };
3938 type Body = UnboundedString;
3939 let body = "hello";
3940
3941 let start = TransactionMessage { header, body };
3942
3943 let buf = &mut Vec::new();
3944 let handle_buf = &mut Vec::new();
3945 Encoder::<DefaultFuchsiaResourceDialect>::encode_with_context::<
3946 TransactionMessageType<Body>,
3947 >(ctx, buf, handle_buf, start)
3948 .expect("Encoding failed");
3949
3950 let (out_header, out_buf) =
3951 decode_transaction_header(buf).expect("Decoding header failed");
3952 assert_eq!(header, out_header);
3953
3954 let mut body_out = String::new();
3955 Decoder::<DefaultFuchsiaResourceDialect>::decode_into::<Body>(
3956 &header,
3957 out_buf,
3958 &mut to_infos(handle_buf),
3959 &mut body_out,
3960 )
3961 .expect("Decoding body failed");
3962 assert_eq!(body, body_out);
3963 }
3964 }
3965
3966 #[test]
3967 fn direct_encode_transaction_header_strict() {
3968 let bytes = &[
3969 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
3972 let header = TransactionHeader {
3973 tx_id: 4,
3974 ordinal: 6,
3975 at_rest_flags: [0; 2],
3976 dynamic_flags: DynamicFlags::empty().bits(),
3977 magic_number: 1,
3978 };
3979
3980 for ctx in CONTEXTS {
3981 encode_assert_bytes::<TransactionHeader>(ctx, &header, bytes);
3982 }
3983 }
3984
3985 #[test]
3986 fn direct_decode_transaction_header_strict() {
3987 let bytes = &[
3988 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
3991 let header = TransactionHeader {
3992 tx_id: 4,
3993 ordinal: 6,
3994 at_rest_flags: [0; 2],
3995 dynamic_flags: DynamicFlags::empty().bits(),
3996 magic_number: 1,
3997 };
3998
3999 for ctx in CONTEXTS {
4000 let mut out = new_empty!(TransactionHeader, DefaultFuchsiaResourceDialect);
4001 Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<TransactionHeader>(
4002 ctx,
4003 bytes,
4004 &mut [],
4005 &mut out,
4006 )
4007 .expect("Decoding failed");
4008 assert_eq!(out, header);
4009 }
4010 }
4011
4012 #[test]
4013 fn direct_encode_transaction_header_flexible() {
4014 let bytes = &[
4015 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
4018 let header = TransactionHeader {
4019 tx_id: 4,
4020 ordinal: 6,
4021 at_rest_flags: [0; 2],
4022 dynamic_flags: DynamicFlags::FLEXIBLE.bits(),
4023 magic_number: 1,
4024 };
4025
4026 for ctx in CONTEXTS {
4027 encode_assert_bytes::<TransactionHeader>(ctx, &header, bytes);
4028 }
4029 }
4030
4031 #[test]
4032 fn direct_decode_transaction_header_flexible() {
4033 let bytes = &[
4034 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
4037 let header = TransactionHeader {
4038 tx_id: 4,
4039 ordinal: 6,
4040 at_rest_flags: [0; 2],
4041 dynamic_flags: DynamicFlags::FLEXIBLE.bits(),
4042 magic_number: 1,
4043 };
4044
4045 for ctx in CONTEXTS {
4046 let mut out = new_empty!(TransactionHeader, DefaultFuchsiaResourceDialect);
4047 Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<TransactionHeader>(
4048 ctx,
4049 bytes,
4050 &mut [],
4051 &mut out,
4052 )
4053 .expect("Decoding failed");
4054 assert_eq!(out, header);
4055 }
4056 }
4057
4058 #[test]
4059 fn extra_data_is_disallowed() {
4060 for ctx in CONTEXTS {
4061 assert_matches!(
4062 Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<EmptyPayload>(
4063 ctx,
4064 &[0],
4065 &mut [],
4066 &mut ()
4067 ),
4068 Err(Error::ExtraBytes)
4069 );
4070 assert_matches!(
4071 Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<EmptyPayload>(
4072 ctx,
4073 &[],
4074 &mut [HandleInfo::new(Handle::invalid(), ObjectType::NONE, Rights::NONE,)],
4075 &mut ()
4076 ),
4077 Err(Error::ExtraHandles)
4078 );
4079 }
4080 }
4081
4082 #[test]
4083 fn encode_default_context() {
4084 let buf = &mut Vec::new();
4085 Encoder::<DefaultFuchsiaResourceDialect>::encode::<u8>(buf, &mut Vec::new(), 1u8)
4086 .expect("Encoding failed");
4087 assert_eq!(buf, &[1u8, 0, 0, 0, 0, 0, 0, 0]);
4088 }
4089
4090 #[test]
4091 fn encode_handle() {
4092 type T = HandleType<Handle, OBJECT_TYPE_NONE, SAME_RIGHTS>;
4093 for ctx in CONTEXTS {
4094 let handle = crate::handle::Event::create().into_handle();
4095 let raw_handle = handle.raw_handle();
4096 let buf = &mut Vec::new();
4097 let handle_buf = &mut Vec::new();
4098 Encoder::<DefaultFuchsiaResourceDialect>::encode_with_context::<T>(
4099 ctx, buf, handle_buf, handle,
4100 )
4101 .expect("Encoding failed");
4102
4103 assert_eq!(handle_buf.len(), 1);
4104 assert!(handle_buf[0].is_move());
4105 assert_eq!(handle_buf[0].raw_handle(), raw_handle);
4106
4107 let mut handle_out = new_empty!(T);
4108 Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<T>(
4109 ctx,
4110 buf,
4111 &mut to_infos(handle_buf),
4112 &mut handle_out,
4113 )
4114 .expect("Decoding failed");
4115 assert_eq!(
4116 handle_out.raw_handle(),
4117 raw_handle,
4118 "decoded handle must match encoded handle"
4119 );
4120 }
4121 }
4122
4123 #[test]
4124 fn decode_too_few_handles() {
4125 type T = HandleType<Handle, OBJECT_TYPE_NONE, SAME_RIGHTS>;
4126 for ctx in CONTEXTS {
4127 let bytes: &[u8] = &[0xff; 8];
4128 let handle_buf = &mut Vec::new();
4129 let mut handle_out = Handle::invalid();
4130 let res = Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<T>(
4131 ctx,
4132 bytes,
4133 handle_buf,
4134 &mut handle_out,
4135 );
4136 assert_matches!(res, Err(Error::OutOfHandles));
4137 }
4138 }
4139
4140 #[test]
4141 fn encode_epitaph() {
4142 for ctx in CONTEXTS {
4143 let buf = &mut Vec::new();
4144 let handle_buf = &mut Vec::new();
4145 Encoder::<DefaultFuchsiaResourceDialect>::encode_with_context::<EpitaphBody>(
4146 ctx,
4147 buf,
4148 handle_buf,
4149 &EpitaphBody { error: zx_status::Status::UNAVAILABLE },
4150 )
4151 .expect("encoding failed");
4152 assert_eq!(buf, &[0xe4, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00]);
4153
4154 let mut out = new_empty!(EpitaphBody, DefaultFuchsiaResourceDialect);
4155 Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<EpitaphBody>(
4156 ctx,
4157 buf,
4158 &mut to_infos(handle_buf),
4159 &mut out,
4160 )
4161 .expect("Decoding failed");
4162 assert_eq!(EpitaphBody { error: zx_status::Status::UNAVAILABLE }, out);
4163 }
4164 }
4165}