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