Skip to main content

fidl_fuchsia_ebpf__common/
fidl_fuchsia_ebpf__common.rs

1// WARNING: This file is machine generated by fidlgen.
2
3#![warn(clippy::all)]
4#![allow(unused_parens, unused_mut, unused_imports, nonstandard_style)]
5
6use bitflags::bitflags;
7use fidl::encoding::{MessageBufFor, ProxyChannelBox, ResourceDialect};
8use futures::future::{self, MaybeDone, TryFutureExt};
9use zx_status;
10
11/// Maximum allowed number of instructions in an eBPF program.
12pub const MAX_PROGRAM_INSTRUCTIONS: u32 = 4096;
13
14/// Maximum number of maps an eBPF program can use.
15pub const MAX_PROGRAM_MAPS: u32 = 4096;
16
17/// The signal raised on a [`ProgramHandle`] to indicate that the program
18/// should be dropped.
19pub const PROGRAM_DEFUNCT_SIGNAL: u32 = 16777216;
20
21bitflags! {
22    /// Map flags.
23    #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
24    pub struct MapFlags: u32 {
25        /// Memory is not pre-allocated.
26        const NO_PREALLOC = 1;
27        /// `bpf()` syscall can read from the map, but can't write to it.
28        const SYSCALL_READ_ONLY = 2;
29        /// `bpf()` syscall can write to the map, but can't read it.
30        const SYSCALL_WRITE_ONLY = 4;
31        /// The map can be mapped in a Starnix process's address space.
32        const MMAPABLE = 8;
33    }
34}
35
36impl MapFlags {
37    #[inline(always)]
38    pub fn from_bits_allow_unknown(bits: u32) -> Self {
39        Self::from_bits_retain(bits)
40    }
41
42    #[inline(always)]
43    pub fn has_unknown_bits(&self) -> bool {
44        self.get_unknown_bits() != 0
45    }
46
47    #[inline(always)]
48    pub fn get_unknown_bits(&self) -> u32 {
49        self.bits() & !Self::all().bits()
50    }
51}
52
53/// Type of an eBPF maps.
54#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
55#[repr(u32)]
56pub enum MapType {
57    /// An array map. Equivalent to `BPF_MAP_TYPE_ARRAY`.
58    Array = 1,
59    /// A hash map. Equivalent to `BPF_MAP_TYPE_HASH`.
60    HashMap = 2,
61    /// A hash map. Equivalent to `BPF_MAP_TYPE_RINGBUF`.
62    RingBuffer = 3,
63    /// A per-CPU array. Equivalent to `BPF_MAP_TYPE_PERCPU_ARRAY`.
64    PercpuArray = 4,
65    /// A per-CPU hash map. Equivalent to `BPF_MAP_TYPE_PERCPU_HASH`.
66    PercpuHash = 5,
67    /// A device-map that holds references to network devices. Equivalent to
68    /// `BPF_MAP_TYPE_DEVMAP`.
69    DevmapHash = 6,
70    /// A longest prefix match trie. Equivalent to `BPF_MAP_TYPE_LPM_TRIE`.
71    LpmTrie = 7,
72    /// A LRU hash map. Equivalent to `BPF_MAP_TYPE_LRU_HASH`.
73    LruHash = 8,
74    /// A socket storage map. Equivalent to `BPF_MAP_TYPE_SK_STORAGE`.
75    SkStorage = 9,
76}
77
78impl MapType {
79    #[inline]
80    pub fn from_primitive(prim: u32) -> Option<Self> {
81        match prim {
82            1 => Some(Self::Array),
83            2 => Some(Self::HashMap),
84            3 => Some(Self::RingBuffer),
85            4 => Some(Self::PercpuArray),
86            5 => Some(Self::PercpuHash),
87            6 => Some(Self::DevmapHash),
88            7 => Some(Self::LpmTrie),
89            8 => Some(Self::LruHash),
90            9 => Some(Self::SkStorage),
91            _ => None,
92        }
93    }
94
95    #[inline]
96    pub const fn into_primitive(self) -> u32 {
97        self as u32
98    }
99}
100
101/// An identifier of a struct that may be passed to an eBPF program.
102#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
103pub enum StructId {
104    SkBuff,
105    XdpMd,
106    BpfUserPtRegs,
107    BpfSock,
108    BpfSockOpt,
109    BpfSockAddr,
110    BpfFuse,
111    #[doc(hidden)]
112    __SourceBreaking {
113        unknown_ordinal: u32,
114    },
115}
116
117/// Pattern that matches an unknown `StructId` member.
118#[macro_export]
119macro_rules! StructIdUnknown {
120    () => {
121        _
122    };
123}
124
125impl StructId {
126    #[inline]
127    pub fn from_primitive(prim: u32) -> Option<Self> {
128        match prim {
129            1 => Some(Self::SkBuff),
130            2 => Some(Self::XdpMd),
131            3 => Some(Self::BpfUserPtRegs),
132            4 => Some(Self::BpfSock),
133            5 => Some(Self::BpfSockOpt),
134            6 => Some(Self::BpfSockAddr),
135            7 => Some(Self::BpfFuse),
136            _ => None,
137        }
138    }
139
140    #[inline]
141    pub fn from_primitive_allow_unknown(prim: u32) -> Self {
142        match prim {
143            1 => Self::SkBuff,
144            2 => Self::XdpMd,
145            3 => Self::BpfUserPtRegs,
146            4 => Self::BpfSock,
147            5 => Self::BpfSockOpt,
148            6 => Self::BpfSockAddr,
149            7 => Self::BpfFuse,
150            unknown_ordinal => Self::__SourceBreaking { unknown_ordinal },
151        }
152    }
153
154    #[inline]
155    pub fn unknown() -> Self {
156        Self::__SourceBreaking { unknown_ordinal: 0xffffffff }
157    }
158
159    #[inline]
160    pub const fn into_primitive(self) -> u32 {
161        match self {
162            Self::SkBuff => 1,
163            Self::XdpMd => 2,
164            Self::BpfUserPtRegs => 3,
165            Self::BpfSock => 4,
166            Self::BpfSockOpt => 5,
167            Self::BpfSockAddr => 6,
168            Self::BpfFuse => 7,
169            Self::__SourceBreaking { unknown_ordinal } => unknown_ordinal,
170        }
171    }
172
173    #[inline]
174    pub fn is_unknown(&self) -> bool {
175        match self {
176            Self::__SourceBreaking { unknown_ordinal: _ } => true,
177            _ => false,
178        }
179    }
180}
181
182/// Schema of an eBPF map.
183#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
184pub struct MapSchema {
185    /// Map type.
186    pub type_: MapType,
187    /// Key size in bytes.
188    pub key_size: u32,
189    /// Value size in bytes.
190    pub value_size: u32,
191    /// Maximum number of entries in the map.
192    pub max_entries: u32,
193    /// Map flags.
194    pub flags: MapFlags,
195}
196
197impl fidl::Persistable for MapSchema {}
198
199/// An ID used to uniquely identify an eBPF program. The ID is the KOID of the
200/// [`ProgramHandle`].
201#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
202#[repr(C)]
203pub struct ProgramId {
204    pub id: u64,
205}
206
207impl fidl::Persistable for ProgramId {}
208
209/// Describes location of an instruction that accesses a struct field.
210///
211/// This is used as auxiliary information passed from the verifier to the
212/// linker. The linker may update these instructions.
213#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
214pub struct StructAccess {
215    /// Index of the instruction in the program.
216    pub pc: u32,
217    /// Id of the struct being accessed.
218    pub struct_id: StructId,
219    /// Offset of the field being accessed.
220    pub field_offset: u32,
221    /// Indicates that the instruction loads a 32-bit pointer field. These
222    /// loads must be remapped to 64-bit fields.
223    pub is_32_bit_ptr_load: bool,
224}
225
226impl fidl::Persistable for StructAccess {}
227
228mod internal {
229    use super::*;
230    unsafe impl fidl::encoding::TypeMarker for MapFlags {
231        type Owned = Self;
232
233        #[inline(always)]
234        fn inline_align(_context: fidl::encoding::Context) -> usize {
235            4
236        }
237
238        #[inline(always)]
239        fn inline_size(_context: fidl::encoding::Context) -> usize {
240            4
241        }
242    }
243
244    impl fidl::encoding::ValueTypeMarker for MapFlags {
245        type Borrowed<'a> = Self;
246        #[inline(always)]
247        fn borrow(value: &<Self as fidl::encoding::TypeMarker>::Owned) -> Self::Borrowed<'_> {
248            *value
249        }
250    }
251
252    unsafe impl<D: fidl::encoding::ResourceDialect> fidl::encoding::Encode<Self, D> for MapFlags {
253        #[inline]
254        unsafe fn encode(
255            self,
256            encoder: &mut fidl::encoding::Encoder<'_, D>,
257            offset: usize,
258            _depth: fidl::encoding::Depth,
259        ) -> fidl::Result<()> {
260            encoder.debug_check_bounds::<Self>(offset);
261            encoder.write_num(self.bits(), offset);
262            Ok(())
263        }
264    }
265
266    impl<D: fidl::encoding::ResourceDialect> fidl::encoding::Decode<Self, D> for MapFlags {
267        #[inline(always)]
268        fn new_empty() -> Self {
269            Self::empty()
270        }
271
272        #[inline]
273        unsafe fn decode(
274            &mut self,
275            decoder: &mut fidl::encoding::Decoder<'_, D>,
276            offset: usize,
277            _depth: fidl::encoding::Depth,
278        ) -> fidl::Result<()> {
279            decoder.debug_check_bounds::<Self>(offset);
280            let prim = decoder.read_num::<u32>(offset);
281            *self = Self::from_bits_allow_unknown(prim);
282            Ok(())
283        }
284    }
285    unsafe impl fidl::encoding::TypeMarker for MapType {
286        type Owned = Self;
287
288        #[inline(always)]
289        fn inline_align(_context: fidl::encoding::Context) -> usize {
290            std::mem::align_of::<u32>()
291        }
292
293        #[inline(always)]
294        fn inline_size(_context: fidl::encoding::Context) -> usize {
295            std::mem::size_of::<u32>()
296        }
297
298        #[inline(always)]
299        fn encode_is_copy() -> bool {
300            true
301        }
302
303        #[inline(always)]
304        fn decode_is_copy() -> bool {
305            false
306        }
307    }
308
309    impl fidl::encoding::ValueTypeMarker for MapType {
310        type Borrowed<'a> = Self;
311        #[inline(always)]
312        fn borrow(value: &<Self as fidl::encoding::TypeMarker>::Owned) -> Self::Borrowed<'_> {
313            *value
314        }
315    }
316
317    unsafe impl<D: fidl::encoding::ResourceDialect> fidl::encoding::Encode<Self, D> for MapType {
318        #[inline]
319        unsafe fn encode(
320            self,
321            encoder: &mut fidl::encoding::Encoder<'_, D>,
322            offset: usize,
323            _depth: fidl::encoding::Depth,
324        ) -> fidl::Result<()> {
325            encoder.debug_check_bounds::<Self>(offset);
326            encoder.write_num(self.into_primitive(), offset);
327            Ok(())
328        }
329    }
330
331    impl<D: fidl::encoding::ResourceDialect> fidl::encoding::Decode<Self, D> for MapType {
332        #[inline(always)]
333        fn new_empty() -> Self {
334            Self::Array
335        }
336
337        #[inline]
338        unsafe fn decode(
339            &mut self,
340            decoder: &mut fidl::encoding::Decoder<'_, D>,
341            offset: usize,
342            _depth: fidl::encoding::Depth,
343        ) -> fidl::Result<()> {
344            decoder.debug_check_bounds::<Self>(offset);
345            let prim = decoder.read_num::<u32>(offset);
346
347            *self = Self::from_primitive(prim).ok_or(fidl::Error::InvalidEnumValue)?;
348            Ok(())
349        }
350    }
351    unsafe impl fidl::encoding::TypeMarker for StructId {
352        type Owned = Self;
353
354        #[inline(always)]
355        fn inline_align(_context: fidl::encoding::Context) -> usize {
356            std::mem::align_of::<u32>()
357        }
358
359        #[inline(always)]
360        fn inline_size(_context: fidl::encoding::Context) -> usize {
361            std::mem::size_of::<u32>()
362        }
363
364        #[inline(always)]
365        fn encode_is_copy() -> bool {
366            false
367        }
368
369        #[inline(always)]
370        fn decode_is_copy() -> bool {
371            false
372        }
373    }
374
375    impl fidl::encoding::ValueTypeMarker for StructId {
376        type Borrowed<'a> = Self;
377        #[inline(always)]
378        fn borrow(value: &<Self as fidl::encoding::TypeMarker>::Owned) -> Self::Borrowed<'_> {
379            *value
380        }
381    }
382
383    unsafe impl<D: fidl::encoding::ResourceDialect> fidl::encoding::Encode<Self, D> for StructId {
384        #[inline]
385        unsafe fn encode(
386            self,
387            encoder: &mut fidl::encoding::Encoder<'_, D>,
388            offset: usize,
389            _depth: fidl::encoding::Depth,
390        ) -> fidl::Result<()> {
391            encoder.debug_check_bounds::<Self>(offset);
392            encoder.write_num(self.into_primitive(), offset);
393            Ok(())
394        }
395    }
396
397    impl<D: fidl::encoding::ResourceDialect> fidl::encoding::Decode<Self, D> for StructId {
398        #[inline(always)]
399        fn new_empty() -> Self {
400            Self::unknown()
401        }
402
403        #[inline]
404        unsafe fn decode(
405            &mut self,
406            decoder: &mut fidl::encoding::Decoder<'_, D>,
407            offset: usize,
408            _depth: fidl::encoding::Depth,
409        ) -> fidl::Result<()> {
410            decoder.debug_check_bounds::<Self>(offset);
411            let prim = decoder.read_num::<u32>(offset);
412
413            *self = Self::from_primitive_allow_unknown(prim);
414            Ok(())
415        }
416    }
417
418    impl fidl::encoding::ValueTypeMarker for MapSchema {
419        type Borrowed<'a> = &'a Self;
420        fn borrow(value: &<Self as fidl::encoding::TypeMarker>::Owned) -> Self::Borrowed<'_> {
421            value
422        }
423    }
424
425    unsafe impl fidl::encoding::TypeMarker for MapSchema {
426        type Owned = Self;
427
428        #[inline(always)]
429        fn inline_align(_context: fidl::encoding::Context) -> usize {
430            4
431        }
432
433        #[inline(always)]
434        fn inline_size(_context: fidl::encoding::Context) -> usize {
435            20
436        }
437    }
438
439    unsafe impl<D: fidl::encoding::ResourceDialect> fidl::encoding::Encode<MapSchema, D>
440        for &MapSchema
441    {
442        #[inline]
443        unsafe fn encode(
444            self,
445            encoder: &mut fidl::encoding::Encoder<'_, D>,
446            offset: usize,
447            _depth: fidl::encoding::Depth,
448        ) -> fidl::Result<()> {
449            encoder.debug_check_bounds::<MapSchema>(offset);
450            // Delegate to tuple encoding.
451            fidl::encoding::Encode::<MapSchema, D>::encode(
452                (
453                    <MapType as fidl::encoding::ValueTypeMarker>::borrow(&self.type_),
454                    <u32 as fidl::encoding::ValueTypeMarker>::borrow(&self.key_size),
455                    <u32 as fidl::encoding::ValueTypeMarker>::borrow(&self.value_size),
456                    <u32 as fidl::encoding::ValueTypeMarker>::borrow(&self.max_entries),
457                    <MapFlags as fidl::encoding::ValueTypeMarker>::borrow(&self.flags),
458                ),
459                encoder,
460                offset,
461                _depth,
462            )
463        }
464    }
465    unsafe impl<
466        D: fidl::encoding::ResourceDialect,
467        T0: fidl::encoding::Encode<MapType, D>,
468        T1: fidl::encoding::Encode<u32, D>,
469        T2: fidl::encoding::Encode<u32, D>,
470        T3: fidl::encoding::Encode<u32, D>,
471        T4: fidl::encoding::Encode<MapFlags, D>,
472    > fidl::encoding::Encode<MapSchema, D> for (T0, T1, T2, T3, T4)
473    {
474        #[inline]
475        unsafe fn encode(
476            self,
477            encoder: &mut fidl::encoding::Encoder<'_, D>,
478            offset: usize,
479            depth: fidl::encoding::Depth,
480        ) -> fidl::Result<()> {
481            encoder.debug_check_bounds::<MapSchema>(offset);
482            // Zero out padding regions. There's no need to apply masks
483            // because the unmasked parts will be overwritten by fields.
484            // Write the fields.
485            self.0.encode(encoder, offset + 0, depth)?;
486            self.1.encode(encoder, offset + 4, depth)?;
487            self.2.encode(encoder, offset + 8, depth)?;
488            self.3.encode(encoder, offset + 12, depth)?;
489            self.4.encode(encoder, offset + 16, depth)?;
490            Ok(())
491        }
492    }
493
494    impl<D: fidl::encoding::ResourceDialect> fidl::encoding::Decode<Self, D> for MapSchema {
495        #[inline(always)]
496        fn new_empty() -> Self {
497            Self {
498                type_: fidl::new_empty!(MapType, D),
499                key_size: fidl::new_empty!(u32, D),
500                value_size: fidl::new_empty!(u32, D),
501                max_entries: fidl::new_empty!(u32, D),
502                flags: fidl::new_empty!(MapFlags, D),
503            }
504        }
505
506        #[inline]
507        unsafe fn decode(
508            &mut self,
509            decoder: &mut fidl::encoding::Decoder<'_, D>,
510            offset: usize,
511            _depth: fidl::encoding::Depth,
512        ) -> fidl::Result<()> {
513            decoder.debug_check_bounds::<Self>(offset);
514            // Verify that padding bytes are zero.
515            fidl::decode!(MapType, D, &mut self.type_, decoder, offset + 0, _depth)?;
516            fidl::decode!(u32, D, &mut self.key_size, decoder, offset + 4, _depth)?;
517            fidl::decode!(u32, D, &mut self.value_size, decoder, offset + 8, _depth)?;
518            fidl::decode!(u32, D, &mut self.max_entries, decoder, offset + 12, _depth)?;
519            fidl::decode!(MapFlags, D, &mut self.flags, decoder, offset + 16, _depth)?;
520            Ok(())
521        }
522    }
523
524    impl fidl::encoding::ValueTypeMarker for ProgramId {
525        type Borrowed<'a> = &'a Self;
526        fn borrow(value: &<Self as fidl::encoding::TypeMarker>::Owned) -> Self::Borrowed<'_> {
527            value
528        }
529    }
530
531    unsafe impl fidl::encoding::TypeMarker for ProgramId {
532        type Owned = Self;
533
534        #[inline(always)]
535        fn inline_align(_context: fidl::encoding::Context) -> usize {
536            8
537        }
538
539        #[inline(always)]
540        fn inline_size(_context: fidl::encoding::Context) -> usize {
541            8
542        }
543        #[inline(always)]
544        fn encode_is_copy() -> bool {
545            true
546        }
547
548        #[inline(always)]
549        fn decode_is_copy() -> bool {
550            true
551        }
552    }
553
554    unsafe impl<D: fidl::encoding::ResourceDialect> fidl::encoding::Encode<ProgramId, D>
555        for &ProgramId
556    {
557        #[inline]
558        unsafe fn encode(
559            self,
560            encoder: &mut fidl::encoding::Encoder<'_, D>,
561            offset: usize,
562            _depth: fidl::encoding::Depth,
563        ) -> fidl::Result<()> {
564            encoder.debug_check_bounds::<ProgramId>(offset);
565            unsafe {
566                // Copy the object into the buffer.
567                let buf_ptr = encoder.buf.as_mut_ptr().add(offset);
568                (buf_ptr as *mut ProgramId).write_unaligned((self as *const ProgramId).read());
569                // Zero out padding regions. Unlike `fidl_struct_impl_noncopy!`, this must be
570                // done second because the memcpy will write garbage to these bytes.
571            }
572            Ok(())
573        }
574    }
575    unsafe impl<D: fidl::encoding::ResourceDialect, T0: fidl::encoding::Encode<u64, D>>
576        fidl::encoding::Encode<ProgramId, D> for (T0,)
577    {
578        #[inline]
579        unsafe fn encode(
580            self,
581            encoder: &mut fidl::encoding::Encoder<'_, D>,
582            offset: usize,
583            depth: fidl::encoding::Depth,
584        ) -> fidl::Result<()> {
585            encoder.debug_check_bounds::<ProgramId>(offset);
586            // Zero out padding regions. There's no need to apply masks
587            // because the unmasked parts will be overwritten by fields.
588            // Write the fields.
589            self.0.encode(encoder, offset + 0, depth)?;
590            Ok(())
591        }
592    }
593
594    impl<D: fidl::encoding::ResourceDialect> fidl::encoding::Decode<Self, D> for ProgramId {
595        #[inline(always)]
596        fn new_empty() -> Self {
597            Self { id: fidl::new_empty!(u64, D) }
598        }
599
600        #[inline]
601        unsafe fn decode(
602            &mut self,
603            decoder: &mut fidl::encoding::Decoder<'_, D>,
604            offset: usize,
605            _depth: fidl::encoding::Depth,
606        ) -> fidl::Result<()> {
607            decoder.debug_check_bounds::<Self>(offset);
608            let buf_ptr = unsafe { decoder.buf.as_ptr().add(offset) };
609            // Verify that padding bytes are zero.
610            // Copy from the buffer into the object.
611            unsafe {
612                std::ptr::copy_nonoverlapping(buf_ptr, self as *mut Self as *mut u8, 8);
613            }
614            Ok(())
615        }
616    }
617
618    impl fidl::encoding::ValueTypeMarker for StructAccess {
619        type Borrowed<'a> = &'a Self;
620        fn borrow(value: &<Self as fidl::encoding::TypeMarker>::Owned) -> Self::Borrowed<'_> {
621            value
622        }
623    }
624
625    unsafe impl fidl::encoding::TypeMarker for StructAccess {
626        type Owned = Self;
627
628        #[inline(always)]
629        fn inline_align(_context: fidl::encoding::Context) -> usize {
630            4
631        }
632
633        #[inline(always)]
634        fn inline_size(_context: fidl::encoding::Context) -> usize {
635            16
636        }
637    }
638
639    unsafe impl<D: fidl::encoding::ResourceDialect> fidl::encoding::Encode<StructAccess, D>
640        for &StructAccess
641    {
642        #[inline]
643        unsafe fn encode(
644            self,
645            encoder: &mut fidl::encoding::Encoder<'_, D>,
646            offset: usize,
647            _depth: fidl::encoding::Depth,
648        ) -> fidl::Result<()> {
649            encoder.debug_check_bounds::<StructAccess>(offset);
650            // Delegate to tuple encoding.
651            fidl::encoding::Encode::<StructAccess, D>::encode(
652                (
653                    <u32 as fidl::encoding::ValueTypeMarker>::borrow(&self.pc),
654                    <StructId as fidl::encoding::ValueTypeMarker>::borrow(&self.struct_id),
655                    <u32 as fidl::encoding::ValueTypeMarker>::borrow(&self.field_offset),
656                    <bool as fidl::encoding::ValueTypeMarker>::borrow(&self.is_32_bit_ptr_load),
657                ),
658                encoder,
659                offset,
660                _depth,
661            )
662        }
663    }
664    unsafe impl<
665        D: fidl::encoding::ResourceDialect,
666        T0: fidl::encoding::Encode<u32, D>,
667        T1: fidl::encoding::Encode<StructId, D>,
668        T2: fidl::encoding::Encode<u32, D>,
669        T3: fidl::encoding::Encode<bool, D>,
670    > fidl::encoding::Encode<StructAccess, D> for (T0, T1, T2, T3)
671    {
672        #[inline]
673        unsafe fn encode(
674            self,
675            encoder: &mut fidl::encoding::Encoder<'_, D>,
676            offset: usize,
677            depth: fidl::encoding::Depth,
678        ) -> fidl::Result<()> {
679            encoder.debug_check_bounds::<StructAccess>(offset);
680            // Zero out padding regions. There's no need to apply masks
681            // because the unmasked parts will be overwritten by fields.
682            unsafe {
683                let ptr = encoder.buf.as_mut_ptr().add(offset).offset(12);
684                (ptr as *mut u32).write_unaligned(0);
685            }
686            // Write the fields.
687            self.0.encode(encoder, offset + 0, depth)?;
688            self.1.encode(encoder, offset + 4, depth)?;
689            self.2.encode(encoder, offset + 8, depth)?;
690            self.3.encode(encoder, offset + 12, depth)?;
691            Ok(())
692        }
693    }
694
695    impl<D: fidl::encoding::ResourceDialect> fidl::encoding::Decode<Self, D> for StructAccess {
696        #[inline(always)]
697        fn new_empty() -> Self {
698            Self {
699                pc: fidl::new_empty!(u32, D),
700                struct_id: fidl::new_empty!(StructId, D),
701                field_offset: fidl::new_empty!(u32, D),
702                is_32_bit_ptr_load: fidl::new_empty!(bool, D),
703            }
704        }
705
706        #[inline]
707        unsafe fn decode(
708            &mut self,
709            decoder: &mut fidl::encoding::Decoder<'_, D>,
710            offset: usize,
711            _depth: fidl::encoding::Depth,
712        ) -> fidl::Result<()> {
713            decoder.debug_check_bounds::<Self>(offset);
714            // Verify that padding bytes are zero.
715            let ptr = unsafe { decoder.buf.as_ptr().add(offset).offset(12) };
716            let padval = unsafe { (ptr as *const u32).read_unaligned() };
717            let mask = 0xffffff00u32;
718            let maskedval = padval & mask;
719            if maskedval != 0 {
720                return Err(fidl::Error::NonZeroPadding {
721                    padding_start: offset + 12 + ((mask as u64).trailing_zeros() / 8) as usize,
722                });
723            }
724            fidl::decode!(u32, D, &mut self.pc, decoder, offset + 0, _depth)?;
725            fidl::decode!(StructId, D, &mut self.struct_id, decoder, offset + 4, _depth)?;
726            fidl::decode!(u32, D, &mut self.field_offset, decoder, offset + 8, _depth)?;
727            fidl::decode!(bool, D, &mut self.is_32_bit_ptr_load, decoder, offset + 12, _depth)?;
728            Ok(())
729        }
730    }
731}