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