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