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