Skip to main content

netlink_bindings/sunrpc/
mod.rs

1#![doc = "SUNRPC cache upcall support over generic netlink.\n"]
2#![allow(clippy::all)]
3#![allow(unused_imports)]
4#![allow(unused_assignments)]
5#![allow(non_snake_case)]
6#![allow(unused_variables)]
7#![allow(irrefutable_let_patterns)]
8#![allow(unreachable_code)]
9#![allow(unreachable_patterns)]
10use crate::builtin::{BuiltinBitfield32, BuiltinNfgenmsg, Nlmsghdr, PushDummy};
11use crate::{
12    consts,
13    traits::{NetlinkRequest, Protocol},
14    utils::*,
15};
16pub const PROTONAME: &str = "sunrpc";
17pub const PROTONAME_CSTR: &CStr = c"sunrpc";
18#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
19#[derive(Debug, Clone, Copy)]
20pub enum CacheType {
21    IpMap = 1 << 0,
22    UnixGid = 1 << 1,
23}
24impl CacheType {
25    pub fn from_value(value: u64) -> Option<Self> {
26        Some(match value {
27            n if n == 1 << 0 => Self::IpMap,
28            n if n == 1 << 1 => Self::UnixGid,
29            _ => return None,
30        })
31    }
32}
33#[derive(Clone)]
34pub enum CacheNotify {
35    #[doc = "Associated type: [`CacheType`] (enum)"]
36    CacheType(u32),
37}
38impl<'a> IterableCacheNotify<'a> {
39    #[doc = "Associated type: [`CacheType`] (enum)"]
40    pub fn get_cache_type(&self) -> Result<u32, ErrorContext> {
41        let mut iter = self.clone();
42        iter.pos = 0;
43        for attr in iter {
44            if let Ok(CacheNotify::CacheType(val)) = attr {
45                return Ok(val);
46            }
47        }
48        Err(ErrorContext::new_missing(
49            "CacheNotify",
50            "CacheType",
51            self.orig_loc,
52            self.buf.as_ptr() as usize,
53        ))
54    }
55}
56impl CacheNotify {
57    pub fn new<'a>(buf: &'a [u8]) -> IterableCacheNotify<'a> {
58        IterableCacheNotify::with_loc(buf, buf.as_ptr() as usize)
59    }
60    fn attr_from_type(r#type: u16) -> Option<&'static str> {
61        let res = match r#type {
62            1u16 => "CacheType",
63            _ => return None,
64        };
65        Some(res)
66    }
67}
68#[derive(Clone, Copy, Default)]
69pub struct IterableCacheNotify<'a> {
70    buf: &'a [u8],
71    pos: usize,
72    orig_loc: usize,
73}
74impl<'a> IterableCacheNotify<'a> {
75    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
76        Self {
77            buf,
78            pos: 0,
79            orig_loc,
80        }
81    }
82    pub fn get_buf(&self) -> &'a [u8] {
83        self.buf
84    }
85}
86impl<'a> Iterator for IterableCacheNotify<'a> {
87    type Item = Result<CacheNotify, ErrorContext>;
88    fn next(&mut self) -> Option<Self::Item> {
89        let mut pos;
90        let mut r#type;
91        loop {
92            pos = self.pos;
93            r#type = None;
94            if self.buf.len() == self.pos {
95                return None;
96            }
97            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
98                self.pos = self.buf.len();
99                break;
100            };
101            r#type = Some(header.r#type);
102            let res = match header.r#type {
103                1u16 => CacheNotify::CacheType({
104                    let res = parse_u32(next);
105                    let Some(val) = res else { break };
106                    val
107                }),
108                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
109                n => continue,
110            };
111            return Some(Ok(res));
112        }
113        Some(Err(ErrorContext::new(
114            "CacheNotify",
115            r#type.and_then(|t| CacheNotify::attr_from_type(t)),
116            self.orig_loc,
117            self.buf.as_ptr().wrapping_add(pos) as usize,
118        )))
119    }
120}
121impl std::fmt::Debug for IterableCacheNotify<'_> {
122    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
123        let mut fmt = f.debug_struct("CacheNotify");
124        for attr in self.clone() {
125            let attr = match attr {
126                Ok(a) => a,
127                Err(err) => {
128                    fmt.finish()?;
129                    f.write_str("Err(")?;
130                    err.fmt(f)?;
131                    return f.write_str(")");
132                }
133            };
134            match attr {
135                CacheNotify::CacheType(val) => {
136                    fmt.field("CacheType", &FormatFlags(val.into(), CacheType::from_value))
137                }
138            };
139        }
140        fmt.finish()
141    }
142}
143impl IterableCacheNotify<'_> {
144    pub fn lookup_attr(
145        &self,
146        offset: usize,
147        missing_type: Option<u16>,
148    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
149        let mut stack = Vec::new();
150        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
151        if missing_type.is_some() && cur == offset {
152            stack.push(("CacheNotify", offset));
153            return (
154                stack,
155                missing_type.and_then(|t| CacheNotify::attr_from_type(t)),
156            );
157        }
158        if cur > offset || cur + self.buf.len() < offset {
159            return (stack, None);
160        }
161        let mut attrs = self.clone();
162        let mut last_off = cur + attrs.pos;
163        while let Some(attr) = attrs.next() {
164            let Ok(attr) = attr else { break };
165            match attr {
166                CacheNotify::CacheType(val) => {
167                    if last_off == offset {
168                        stack.push(("CacheType", last_off));
169                        break;
170                    }
171                }
172                _ => {}
173            };
174            last_off = cur + attrs.pos;
175        }
176        if !stack.is_empty() {
177            stack.push(("CacheNotify", cur));
178        }
179        (stack, None)
180    }
181}
182#[derive(Clone)]
183pub enum IpMap<'a> {
184    Seqno(u64),
185    Class(&'a CStr),
186    Addr(&'a CStr),
187    Domain(&'a CStr),
188    Negative(()),
189    Expiry(u64),
190}
191impl<'a> IterableIpMap<'a> {
192    pub fn get_seqno(&self) -> Result<u64, ErrorContext> {
193        let mut iter = self.clone();
194        iter.pos = 0;
195        for attr in iter {
196            if let Ok(IpMap::Seqno(val)) = attr {
197                return Ok(val);
198            }
199        }
200        Err(ErrorContext::new_missing(
201            "IpMap",
202            "Seqno",
203            self.orig_loc,
204            self.buf.as_ptr() as usize,
205        ))
206    }
207    pub fn get_class(&self) -> Result<&'a CStr, ErrorContext> {
208        let mut iter = self.clone();
209        iter.pos = 0;
210        for attr in iter {
211            if let Ok(IpMap::Class(val)) = attr {
212                return Ok(val);
213            }
214        }
215        Err(ErrorContext::new_missing(
216            "IpMap",
217            "Class",
218            self.orig_loc,
219            self.buf.as_ptr() as usize,
220        ))
221    }
222    pub fn get_addr(&self) -> Result<&'a CStr, ErrorContext> {
223        let mut iter = self.clone();
224        iter.pos = 0;
225        for attr in iter {
226            if let Ok(IpMap::Addr(val)) = attr {
227                return Ok(val);
228            }
229        }
230        Err(ErrorContext::new_missing(
231            "IpMap",
232            "Addr",
233            self.orig_loc,
234            self.buf.as_ptr() as usize,
235        ))
236    }
237    pub fn get_domain(&self) -> Result<&'a CStr, ErrorContext> {
238        let mut iter = self.clone();
239        iter.pos = 0;
240        for attr in iter {
241            if let Ok(IpMap::Domain(val)) = attr {
242                return Ok(val);
243            }
244        }
245        Err(ErrorContext::new_missing(
246            "IpMap",
247            "Domain",
248            self.orig_loc,
249            self.buf.as_ptr() as usize,
250        ))
251    }
252    pub fn get_negative(&self) -> Result<(), ErrorContext> {
253        let mut iter = self.clone();
254        iter.pos = 0;
255        for attr in iter {
256            if let Ok(IpMap::Negative(val)) = attr {
257                return Ok(val);
258            }
259        }
260        Err(ErrorContext::new_missing(
261            "IpMap",
262            "Negative",
263            self.orig_loc,
264            self.buf.as_ptr() as usize,
265        ))
266    }
267    pub fn get_expiry(&self) -> Result<u64, ErrorContext> {
268        let mut iter = self.clone();
269        iter.pos = 0;
270        for attr in iter {
271            if let Ok(IpMap::Expiry(val)) = attr {
272                return Ok(val);
273            }
274        }
275        Err(ErrorContext::new_missing(
276            "IpMap",
277            "Expiry",
278            self.orig_loc,
279            self.buf.as_ptr() as usize,
280        ))
281    }
282}
283impl IpMap<'_> {
284    pub fn new<'a>(buf: &'a [u8]) -> IterableIpMap<'a> {
285        IterableIpMap::with_loc(buf, buf.as_ptr() as usize)
286    }
287    fn attr_from_type(r#type: u16) -> Option<&'static str> {
288        let res = match r#type {
289            1u16 => "Seqno",
290            2u16 => "Class",
291            3u16 => "Addr",
292            4u16 => "Domain",
293            5u16 => "Negative",
294            6u16 => "Expiry",
295            _ => return None,
296        };
297        Some(res)
298    }
299}
300#[derive(Clone, Copy, Default)]
301pub struct IterableIpMap<'a> {
302    buf: &'a [u8],
303    pos: usize,
304    orig_loc: usize,
305}
306impl<'a> IterableIpMap<'a> {
307    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
308        Self {
309            buf,
310            pos: 0,
311            orig_loc,
312        }
313    }
314    pub fn get_buf(&self) -> &'a [u8] {
315        self.buf
316    }
317}
318impl<'a> Iterator for IterableIpMap<'a> {
319    type Item = Result<IpMap<'a>, ErrorContext>;
320    fn next(&mut self) -> Option<Self::Item> {
321        let mut pos;
322        let mut r#type;
323        loop {
324            pos = self.pos;
325            r#type = None;
326            if self.buf.len() == self.pos {
327                return None;
328            }
329            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
330                self.pos = self.buf.len();
331                break;
332            };
333            r#type = Some(header.r#type);
334            let res = match header.r#type {
335                1u16 => IpMap::Seqno({
336                    let res = parse_u64(next);
337                    let Some(val) = res else { break };
338                    val
339                }),
340                2u16 => IpMap::Class({
341                    let res = CStr::from_bytes_with_nul(next).ok();
342                    let Some(val) = res else { break };
343                    val
344                }),
345                3u16 => IpMap::Addr({
346                    let res = CStr::from_bytes_with_nul(next).ok();
347                    let Some(val) = res else { break };
348                    val
349                }),
350                4u16 => IpMap::Domain({
351                    let res = CStr::from_bytes_with_nul(next).ok();
352                    let Some(val) = res else { break };
353                    val
354                }),
355                5u16 => IpMap::Negative(()),
356                6u16 => IpMap::Expiry({
357                    let res = parse_u64(next);
358                    let Some(val) = res else { break };
359                    val
360                }),
361                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
362                n => continue,
363            };
364            return Some(Ok(res));
365        }
366        Some(Err(ErrorContext::new(
367            "IpMap",
368            r#type.and_then(|t| IpMap::attr_from_type(t)),
369            self.orig_loc,
370            self.buf.as_ptr().wrapping_add(pos) as usize,
371        )))
372    }
373}
374impl<'a> std::fmt::Debug for IterableIpMap<'_> {
375    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
376        let mut fmt = f.debug_struct("IpMap");
377        for attr in self.clone() {
378            let attr = match attr {
379                Ok(a) => a,
380                Err(err) => {
381                    fmt.finish()?;
382                    f.write_str("Err(")?;
383                    err.fmt(f)?;
384                    return f.write_str(")");
385                }
386            };
387            match attr {
388                IpMap::Seqno(val) => fmt.field("Seqno", &val),
389                IpMap::Class(val) => fmt.field("Class", &val),
390                IpMap::Addr(val) => fmt.field("Addr", &val),
391                IpMap::Domain(val) => fmt.field("Domain", &val),
392                IpMap::Negative(val) => fmt.field("Negative", &val),
393                IpMap::Expiry(val) => fmt.field("Expiry", &val),
394            };
395        }
396        fmt.finish()
397    }
398}
399impl IterableIpMap<'_> {
400    pub fn lookup_attr(
401        &self,
402        offset: usize,
403        missing_type: Option<u16>,
404    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
405        let mut stack = Vec::new();
406        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
407        if missing_type.is_some() && cur == offset {
408            stack.push(("IpMap", offset));
409            return (stack, missing_type.and_then(|t| IpMap::attr_from_type(t)));
410        }
411        if cur > offset || cur + self.buf.len() < offset {
412            return (stack, None);
413        }
414        let mut attrs = self.clone();
415        let mut last_off = cur + attrs.pos;
416        while let Some(attr) = attrs.next() {
417            let Ok(attr) = attr else { break };
418            match attr {
419                IpMap::Seqno(val) => {
420                    if last_off == offset {
421                        stack.push(("Seqno", last_off));
422                        break;
423                    }
424                }
425                IpMap::Class(val) => {
426                    if last_off == offset {
427                        stack.push(("Class", last_off));
428                        break;
429                    }
430                }
431                IpMap::Addr(val) => {
432                    if last_off == offset {
433                        stack.push(("Addr", last_off));
434                        break;
435                    }
436                }
437                IpMap::Domain(val) => {
438                    if last_off == offset {
439                        stack.push(("Domain", last_off));
440                        break;
441                    }
442                }
443                IpMap::Negative(val) => {
444                    if last_off == offset {
445                        stack.push(("Negative", last_off));
446                        break;
447                    }
448                }
449                IpMap::Expiry(val) => {
450                    if last_off == offset {
451                        stack.push(("Expiry", last_off));
452                        break;
453                    }
454                }
455                _ => {}
456            };
457            last_off = cur + attrs.pos;
458        }
459        if !stack.is_empty() {
460            stack.push(("IpMap", cur));
461        }
462        (stack, None)
463    }
464}
465#[derive(Clone)]
466pub enum IpMapReqs<'a> {
467    #[doc = "Attribute may repeat multiple times (treat it as array)"]
468    Requests(IterableIpMap<'a>),
469}
470impl<'a> IterableIpMapReqs<'a> {
471    #[doc = "Attribute may repeat multiple times (treat it as array)"]
472    pub fn get_requests(&self) -> MultiAttrIterable<Self, IpMapReqs<'a>, IterableIpMap<'a>> {
473        MultiAttrIterable::new(self.clone(), |variant| {
474            if let IpMapReqs::Requests(val) = variant {
475                Some(val)
476            } else {
477                None
478            }
479        })
480    }
481}
482impl IpMapReqs<'_> {
483    pub fn new<'a>(buf: &'a [u8]) -> IterableIpMapReqs<'a> {
484        IterableIpMapReqs::with_loc(buf, buf.as_ptr() as usize)
485    }
486    fn attr_from_type(r#type: u16) -> Option<&'static str> {
487        let res = match r#type {
488            1u16 => "Requests",
489            _ => return None,
490        };
491        Some(res)
492    }
493}
494#[derive(Clone, Copy, Default)]
495pub struct IterableIpMapReqs<'a> {
496    buf: &'a [u8],
497    pos: usize,
498    orig_loc: usize,
499}
500impl<'a> IterableIpMapReqs<'a> {
501    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
502        Self {
503            buf,
504            pos: 0,
505            orig_loc,
506        }
507    }
508    pub fn get_buf(&self) -> &'a [u8] {
509        self.buf
510    }
511}
512impl<'a> Iterator for IterableIpMapReqs<'a> {
513    type Item = Result<IpMapReqs<'a>, ErrorContext>;
514    fn next(&mut self) -> Option<Self::Item> {
515        let mut pos;
516        let mut r#type;
517        loop {
518            pos = self.pos;
519            r#type = None;
520            if self.buf.len() == self.pos {
521                return None;
522            }
523            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
524                self.pos = self.buf.len();
525                break;
526            };
527            r#type = Some(header.r#type);
528            let res = match header.r#type {
529                1u16 => IpMapReqs::Requests({
530                    let res = Some(IterableIpMap::with_loc(next, self.orig_loc));
531                    let Some(val) = res else { break };
532                    val
533                }),
534                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
535                n => continue,
536            };
537            return Some(Ok(res));
538        }
539        Some(Err(ErrorContext::new(
540            "IpMapReqs",
541            r#type.and_then(|t| IpMapReqs::attr_from_type(t)),
542            self.orig_loc,
543            self.buf.as_ptr().wrapping_add(pos) as usize,
544        )))
545    }
546}
547impl<'a> std::fmt::Debug for IterableIpMapReqs<'_> {
548    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
549        let mut fmt = f.debug_struct("IpMapReqs");
550        for attr in self.clone() {
551            let attr = match attr {
552                Ok(a) => a,
553                Err(err) => {
554                    fmt.finish()?;
555                    f.write_str("Err(")?;
556                    err.fmt(f)?;
557                    return f.write_str(")");
558                }
559            };
560            match attr {
561                IpMapReqs::Requests(val) => fmt.field("Requests", &val),
562            };
563        }
564        fmt.finish()
565    }
566}
567impl IterableIpMapReqs<'_> {
568    pub fn lookup_attr(
569        &self,
570        offset: usize,
571        missing_type: Option<u16>,
572    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
573        let mut stack = Vec::new();
574        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
575        if missing_type.is_some() && cur == offset {
576            stack.push(("IpMapReqs", offset));
577            return (
578                stack,
579                missing_type.and_then(|t| IpMapReqs::attr_from_type(t)),
580            );
581        }
582        if cur > offset || cur + self.buf.len() < offset {
583            return (stack, None);
584        }
585        let mut attrs = self.clone();
586        let mut last_off = cur + attrs.pos;
587        let mut missing = None;
588        while let Some(attr) = attrs.next() {
589            let Ok(attr) = attr else { break };
590            match attr {
591                IpMapReqs::Requests(val) => {
592                    (stack, missing) = val.lookup_attr(offset, missing_type);
593                    if !stack.is_empty() {
594                        break;
595                    }
596                }
597                _ => {}
598            };
599            last_off = cur + attrs.pos;
600        }
601        if !stack.is_empty() {
602            stack.push(("IpMapReqs", cur));
603        }
604        (stack, missing)
605    }
606}
607#[derive(Clone)]
608pub enum UnixGid {
609    Seqno(u64),
610    Uid(u32),
611    #[doc = "Attribute may repeat multiple times (treat it as array)"]
612    Gids(u32),
613    Negative(()),
614    Expiry(u64),
615}
616impl<'a> IterableUnixGid<'a> {
617    pub fn get_seqno(&self) -> Result<u64, ErrorContext> {
618        let mut iter = self.clone();
619        iter.pos = 0;
620        for attr in iter {
621            if let Ok(UnixGid::Seqno(val)) = attr {
622                return Ok(val);
623            }
624        }
625        Err(ErrorContext::new_missing(
626            "UnixGid",
627            "Seqno",
628            self.orig_loc,
629            self.buf.as_ptr() as usize,
630        ))
631    }
632    pub fn get_uid(&self) -> Result<u32, ErrorContext> {
633        let mut iter = self.clone();
634        iter.pos = 0;
635        for attr in iter {
636            if let Ok(UnixGid::Uid(val)) = attr {
637                return Ok(val);
638            }
639        }
640        Err(ErrorContext::new_missing(
641            "UnixGid",
642            "Uid",
643            self.orig_loc,
644            self.buf.as_ptr() as usize,
645        ))
646    }
647    #[doc = "Attribute may repeat multiple times (treat it as array)"]
648    pub fn get_gids(&self) -> MultiAttrIterable<Self, UnixGid, u32> {
649        MultiAttrIterable::new(self.clone(), |variant| {
650            if let UnixGid::Gids(val) = variant {
651                Some(val)
652            } else {
653                None
654            }
655        })
656    }
657    pub fn get_negative(&self) -> Result<(), ErrorContext> {
658        let mut iter = self.clone();
659        iter.pos = 0;
660        for attr in iter {
661            if let Ok(UnixGid::Negative(val)) = attr {
662                return Ok(val);
663            }
664        }
665        Err(ErrorContext::new_missing(
666            "UnixGid",
667            "Negative",
668            self.orig_loc,
669            self.buf.as_ptr() as usize,
670        ))
671    }
672    pub fn get_expiry(&self) -> Result<u64, ErrorContext> {
673        let mut iter = self.clone();
674        iter.pos = 0;
675        for attr in iter {
676            if let Ok(UnixGid::Expiry(val)) = attr {
677                return Ok(val);
678            }
679        }
680        Err(ErrorContext::new_missing(
681            "UnixGid",
682            "Expiry",
683            self.orig_loc,
684            self.buf.as_ptr() as usize,
685        ))
686    }
687}
688impl UnixGid {
689    pub fn new<'a>(buf: &'a [u8]) -> IterableUnixGid<'a> {
690        IterableUnixGid::with_loc(buf, buf.as_ptr() as usize)
691    }
692    fn attr_from_type(r#type: u16) -> Option<&'static str> {
693        let res = match r#type {
694            1u16 => "Seqno",
695            2u16 => "Uid",
696            3u16 => "Gids",
697            4u16 => "Negative",
698            5u16 => "Expiry",
699            _ => return None,
700        };
701        Some(res)
702    }
703}
704#[derive(Clone, Copy, Default)]
705pub struct IterableUnixGid<'a> {
706    buf: &'a [u8],
707    pos: usize,
708    orig_loc: usize,
709}
710impl<'a> IterableUnixGid<'a> {
711    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
712        Self {
713            buf,
714            pos: 0,
715            orig_loc,
716        }
717    }
718    pub fn get_buf(&self) -> &'a [u8] {
719        self.buf
720    }
721}
722impl<'a> Iterator for IterableUnixGid<'a> {
723    type Item = Result<UnixGid, ErrorContext>;
724    fn next(&mut self) -> Option<Self::Item> {
725        let mut pos;
726        let mut r#type;
727        loop {
728            pos = self.pos;
729            r#type = None;
730            if self.buf.len() == self.pos {
731                return None;
732            }
733            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
734                self.pos = self.buf.len();
735                break;
736            };
737            r#type = Some(header.r#type);
738            let res = match header.r#type {
739                1u16 => UnixGid::Seqno({
740                    let res = parse_u64(next);
741                    let Some(val) = res else { break };
742                    val
743                }),
744                2u16 => UnixGid::Uid({
745                    let res = parse_u32(next);
746                    let Some(val) = res else { break };
747                    val
748                }),
749                3u16 => UnixGid::Gids({
750                    let res = parse_u32(next);
751                    let Some(val) = res else { break };
752                    val
753                }),
754                4u16 => UnixGid::Negative(()),
755                5u16 => UnixGid::Expiry({
756                    let res = parse_u64(next);
757                    let Some(val) = res else { break };
758                    val
759                }),
760                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
761                n => continue,
762            };
763            return Some(Ok(res));
764        }
765        Some(Err(ErrorContext::new(
766            "UnixGid",
767            r#type.and_then(|t| UnixGid::attr_from_type(t)),
768            self.orig_loc,
769            self.buf.as_ptr().wrapping_add(pos) as usize,
770        )))
771    }
772}
773impl std::fmt::Debug for IterableUnixGid<'_> {
774    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
775        let mut fmt = f.debug_struct("UnixGid");
776        for attr in self.clone() {
777            let attr = match attr {
778                Ok(a) => a,
779                Err(err) => {
780                    fmt.finish()?;
781                    f.write_str("Err(")?;
782                    err.fmt(f)?;
783                    return f.write_str(")");
784                }
785            };
786            match attr {
787                UnixGid::Seqno(val) => fmt.field("Seqno", &val),
788                UnixGid::Uid(val) => fmt.field("Uid", &val),
789                UnixGid::Gids(val) => fmt.field("Gids", &val),
790                UnixGid::Negative(val) => fmt.field("Negative", &val),
791                UnixGid::Expiry(val) => fmt.field("Expiry", &val),
792            };
793        }
794        fmt.finish()
795    }
796}
797impl IterableUnixGid<'_> {
798    pub fn lookup_attr(
799        &self,
800        offset: usize,
801        missing_type: Option<u16>,
802    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
803        let mut stack = Vec::new();
804        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
805        if missing_type.is_some() && cur == offset {
806            stack.push(("UnixGid", offset));
807            return (stack, missing_type.and_then(|t| UnixGid::attr_from_type(t)));
808        }
809        if cur > offset || cur + self.buf.len() < offset {
810            return (stack, None);
811        }
812        let mut attrs = self.clone();
813        let mut last_off = cur + attrs.pos;
814        while let Some(attr) = attrs.next() {
815            let Ok(attr) = attr else { break };
816            match attr {
817                UnixGid::Seqno(val) => {
818                    if last_off == offset {
819                        stack.push(("Seqno", last_off));
820                        break;
821                    }
822                }
823                UnixGid::Uid(val) => {
824                    if last_off == offset {
825                        stack.push(("Uid", last_off));
826                        break;
827                    }
828                }
829                UnixGid::Gids(val) => {
830                    if last_off == offset {
831                        stack.push(("Gids", last_off));
832                        break;
833                    }
834                }
835                UnixGid::Negative(val) => {
836                    if last_off == offset {
837                        stack.push(("Negative", last_off));
838                        break;
839                    }
840                }
841                UnixGid::Expiry(val) => {
842                    if last_off == offset {
843                        stack.push(("Expiry", last_off));
844                        break;
845                    }
846                }
847                _ => {}
848            };
849            last_off = cur + attrs.pos;
850        }
851        if !stack.is_empty() {
852            stack.push(("UnixGid", cur));
853        }
854        (stack, None)
855    }
856}
857#[derive(Clone)]
858pub enum UnixGidReqs<'a> {
859    #[doc = "Attribute may repeat multiple times (treat it as array)"]
860    Requests(IterableUnixGid<'a>),
861}
862impl<'a> IterableUnixGidReqs<'a> {
863    #[doc = "Attribute may repeat multiple times (treat it as array)"]
864    pub fn get_requests(&self) -> MultiAttrIterable<Self, UnixGidReqs<'a>, IterableUnixGid<'a>> {
865        MultiAttrIterable::new(self.clone(), |variant| {
866            if let UnixGidReqs::Requests(val) = variant {
867                Some(val)
868            } else {
869                None
870            }
871        })
872    }
873}
874impl UnixGidReqs<'_> {
875    pub fn new<'a>(buf: &'a [u8]) -> IterableUnixGidReqs<'a> {
876        IterableUnixGidReqs::with_loc(buf, buf.as_ptr() as usize)
877    }
878    fn attr_from_type(r#type: u16) -> Option<&'static str> {
879        let res = match r#type {
880            1u16 => "Requests",
881            _ => return None,
882        };
883        Some(res)
884    }
885}
886#[derive(Clone, Copy, Default)]
887pub struct IterableUnixGidReqs<'a> {
888    buf: &'a [u8],
889    pos: usize,
890    orig_loc: usize,
891}
892impl<'a> IterableUnixGidReqs<'a> {
893    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
894        Self {
895            buf,
896            pos: 0,
897            orig_loc,
898        }
899    }
900    pub fn get_buf(&self) -> &'a [u8] {
901        self.buf
902    }
903}
904impl<'a> Iterator for IterableUnixGidReqs<'a> {
905    type Item = Result<UnixGidReqs<'a>, ErrorContext>;
906    fn next(&mut self) -> Option<Self::Item> {
907        let mut pos;
908        let mut r#type;
909        loop {
910            pos = self.pos;
911            r#type = None;
912            if self.buf.len() == self.pos {
913                return None;
914            }
915            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
916                self.pos = self.buf.len();
917                break;
918            };
919            r#type = Some(header.r#type);
920            let res = match header.r#type {
921                1u16 => UnixGidReqs::Requests({
922                    let res = Some(IterableUnixGid::with_loc(next, self.orig_loc));
923                    let Some(val) = res else { break };
924                    val
925                }),
926                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
927                n => continue,
928            };
929            return Some(Ok(res));
930        }
931        Some(Err(ErrorContext::new(
932            "UnixGidReqs",
933            r#type.and_then(|t| UnixGidReqs::attr_from_type(t)),
934            self.orig_loc,
935            self.buf.as_ptr().wrapping_add(pos) as usize,
936        )))
937    }
938}
939impl<'a> std::fmt::Debug for IterableUnixGidReqs<'_> {
940    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
941        let mut fmt = f.debug_struct("UnixGidReqs");
942        for attr in self.clone() {
943            let attr = match attr {
944                Ok(a) => a,
945                Err(err) => {
946                    fmt.finish()?;
947                    f.write_str("Err(")?;
948                    err.fmt(f)?;
949                    return f.write_str(")");
950                }
951            };
952            match attr {
953                UnixGidReqs::Requests(val) => fmt.field("Requests", &val),
954            };
955        }
956        fmt.finish()
957    }
958}
959impl IterableUnixGidReqs<'_> {
960    pub fn lookup_attr(
961        &self,
962        offset: usize,
963        missing_type: Option<u16>,
964    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
965        let mut stack = Vec::new();
966        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
967        if missing_type.is_some() && cur == offset {
968            stack.push(("UnixGidReqs", offset));
969            return (
970                stack,
971                missing_type.and_then(|t| UnixGidReqs::attr_from_type(t)),
972            );
973        }
974        if cur > offset || cur + self.buf.len() < offset {
975            return (stack, None);
976        }
977        let mut attrs = self.clone();
978        let mut last_off = cur + attrs.pos;
979        let mut missing = None;
980        while let Some(attr) = attrs.next() {
981            let Ok(attr) = attr else { break };
982            match attr {
983                UnixGidReqs::Requests(val) => {
984                    (stack, missing) = val.lookup_attr(offset, missing_type);
985                    if !stack.is_empty() {
986                        break;
987                    }
988                }
989                _ => {}
990            };
991            last_off = cur + attrs.pos;
992        }
993        if !stack.is_empty() {
994            stack.push(("UnixGidReqs", cur));
995        }
996        (stack, missing)
997    }
998}
999#[derive(Clone)]
1000pub enum CacheFlush {
1001    #[doc = "Associated type: [`CacheType`] (1 bit per enumeration)"]
1002    Mask(u32),
1003}
1004impl<'a> IterableCacheFlush<'a> {
1005    #[doc = "Associated type: [`CacheType`] (1 bit per enumeration)"]
1006    pub fn get_mask(&self) -> Result<u32, ErrorContext> {
1007        let mut iter = self.clone();
1008        iter.pos = 0;
1009        for attr in iter {
1010            if let Ok(CacheFlush::Mask(val)) = attr {
1011                return Ok(val);
1012            }
1013        }
1014        Err(ErrorContext::new_missing(
1015            "CacheFlush",
1016            "Mask",
1017            self.orig_loc,
1018            self.buf.as_ptr() as usize,
1019        ))
1020    }
1021}
1022impl CacheFlush {
1023    pub fn new<'a>(buf: &'a [u8]) -> IterableCacheFlush<'a> {
1024        IterableCacheFlush::with_loc(buf, buf.as_ptr() as usize)
1025    }
1026    fn attr_from_type(r#type: u16) -> Option<&'static str> {
1027        let res = match r#type {
1028            1u16 => "Mask",
1029            _ => return None,
1030        };
1031        Some(res)
1032    }
1033}
1034#[derive(Clone, Copy, Default)]
1035pub struct IterableCacheFlush<'a> {
1036    buf: &'a [u8],
1037    pos: usize,
1038    orig_loc: usize,
1039}
1040impl<'a> IterableCacheFlush<'a> {
1041    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1042        Self {
1043            buf,
1044            pos: 0,
1045            orig_loc,
1046        }
1047    }
1048    pub fn get_buf(&self) -> &'a [u8] {
1049        self.buf
1050    }
1051}
1052impl<'a> Iterator for IterableCacheFlush<'a> {
1053    type Item = Result<CacheFlush, ErrorContext>;
1054    fn next(&mut self) -> Option<Self::Item> {
1055        let mut pos;
1056        let mut r#type;
1057        loop {
1058            pos = self.pos;
1059            r#type = None;
1060            if self.buf.len() == self.pos {
1061                return None;
1062            }
1063            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1064                self.pos = self.buf.len();
1065                break;
1066            };
1067            r#type = Some(header.r#type);
1068            let res = match header.r#type {
1069                1u16 => CacheFlush::Mask({
1070                    let res = parse_u32(next);
1071                    let Some(val) = res else { break };
1072                    val
1073                }),
1074                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1075                n => continue,
1076            };
1077            return Some(Ok(res));
1078        }
1079        Some(Err(ErrorContext::new(
1080            "CacheFlush",
1081            r#type.and_then(|t| CacheFlush::attr_from_type(t)),
1082            self.orig_loc,
1083            self.buf.as_ptr().wrapping_add(pos) as usize,
1084        )))
1085    }
1086}
1087impl std::fmt::Debug for IterableCacheFlush<'_> {
1088    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1089        let mut fmt = f.debug_struct("CacheFlush");
1090        for attr in self.clone() {
1091            let attr = match attr {
1092                Ok(a) => a,
1093                Err(err) => {
1094                    fmt.finish()?;
1095                    f.write_str("Err(")?;
1096                    err.fmt(f)?;
1097                    return f.write_str(")");
1098                }
1099            };
1100            match attr {
1101                CacheFlush::Mask(val) => {
1102                    fmt.field("Mask", &FormatFlags(val.into(), CacheType::from_value))
1103                }
1104            };
1105        }
1106        fmt.finish()
1107    }
1108}
1109impl IterableCacheFlush<'_> {
1110    pub fn lookup_attr(
1111        &self,
1112        offset: usize,
1113        missing_type: Option<u16>,
1114    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1115        let mut stack = Vec::new();
1116        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1117        if missing_type.is_some() && cur == offset {
1118            stack.push(("CacheFlush", offset));
1119            return (
1120                stack,
1121                missing_type.and_then(|t| CacheFlush::attr_from_type(t)),
1122            );
1123        }
1124        if cur > offset || cur + self.buf.len() < offset {
1125            return (stack, None);
1126        }
1127        let mut attrs = self.clone();
1128        let mut last_off = cur + attrs.pos;
1129        while let Some(attr) = attrs.next() {
1130            let Ok(attr) = attr else { break };
1131            match attr {
1132                CacheFlush::Mask(val) => {
1133                    if last_off == offset {
1134                        stack.push(("Mask", last_off));
1135                        break;
1136                    }
1137                }
1138                _ => {}
1139            };
1140            last_off = cur + attrs.pos;
1141        }
1142        if !stack.is_empty() {
1143            stack.push(("CacheFlush", cur));
1144        }
1145        (stack, None)
1146    }
1147}
1148pub struct PushCacheNotify<Prev: Pusher> {
1149    pub(crate) prev: Option<Prev>,
1150    pub(crate) header_offset: Option<usize>,
1151}
1152impl<Prev: Pusher> Pusher for PushCacheNotify<Prev> {
1153    fn as_vec_mut(&mut self) -> &mut Vec<u8> {
1154        self.prev.as_mut().unwrap().as_vec_mut()
1155    }
1156    fn as_vec(&self) -> &Vec<u8> {
1157        self.prev.as_ref().unwrap().as_vec()
1158    }
1159}
1160impl<Prev: Pusher> PushCacheNotify<Prev> {
1161    pub fn new(prev: Prev) -> Self {
1162        Self {
1163            prev: Some(prev),
1164            header_offset: None,
1165        }
1166    }
1167    pub fn end_nested(mut self) -> Prev {
1168        let mut prev = self.prev.take().unwrap();
1169        if let Some(header_offset) = &self.header_offset {
1170            finalize_nested_header(prev.as_vec_mut(), *header_offset);
1171        }
1172        prev
1173    }
1174    #[doc = "Associated type: [`CacheType`] (enum)"]
1175    pub fn push_cache_type(mut self, value: u32) -> Self {
1176        push_header(self.as_vec_mut(), 1u16, 4 as u16);
1177        self.as_vec_mut().extend(value.to_ne_bytes());
1178        self
1179    }
1180}
1181impl<Prev: Pusher> Drop for PushCacheNotify<Prev> {
1182    fn drop(&mut self) {
1183        if let Some(prev) = &mut self.prev {
1184            if let Some(header_offset) = &self.header_offset {
1185                finalize_nested_header(prev.as_vec_mut(), *header_offset);
1186            }
1187        }
1188    }
1189}
1190pub struct PushIpMap<Prev: Pusher> {
1191    pub(crate) prev: Option<Prev>,
1192    pub(crate) header_offset: Option<usize>,
1193}
1194impl<Prev: Pusher> Pusher for PushIpMap<Prev> {
1195    fn as_vec_mut(&mut self) -> &mut Vec<u8> {
1196        self.prev.as_mut().unwrap().as_vec_mut()
1197    }
1198    fn as_vec(&self) -> &Vec<u8> {
1199        self.prev.as_ref().unwrap().as_vec()
1200    }
1201}
1202impl<Prev: Pusher> PushIpMap<Prev> {
1203    pub fn new(prev: Prev) -> Self {
1204        Self {
1205            prev: Some(prev),
1206            header_offset: None,
1207        }
1208    }
1209    pub fn end_nested(mut self) -> Prev {
1210        let mut prev = self.prev.take().unwrap();
1211        if let Some(header_offset) = &self.header_offset {
1212            finalize_nested_header(prev.as_vec_mut(), *header_offset);
1213        }
1214        prev
1215    }
1216    pub fn push_seqno(mut self, value: u64) -> Self {
1217        push_header(self.as_vec_mut(), 1u16, 8 as u16);
1218        self.as_vec_mut().extend(value.to_ne_bytes());
1219        self
1220    }
1221    pub fn push_class(mut self, value: &CStr) -> Self {
1222        push_header(
1223            self.as_vec_mut(),
1224            2u16,
1225            value.to_bytes_with_nul().len() as u16,
1226        );
1227        self.as_vec_mut().extend(value.to_bytes_with_nul());
1228        self
1229    }
1230    pub fn push_class_bytes(mut self, value: &[u8]) -> Self {
1231        push_header(self.as_vec_mut(), 2u16, (value.len() + 1) as u16);
1232        self.as_vec_mut().extend(value);
1233        self.as_vec_mut().push(0);
1234        self
1235    }
1236    pub fn push_addr(mut self, value: &CStr) -> Self {
1237        push_header(
1238            self.as_vec_mut(),
1239            3u16,
1240            value.to_bytes_with_nul().len() as u16,
1241        );
1242        self.as_vec_mut().extend(value.to_bytes_with_nul());
1243        self
1244    }
1245    pub fn push_addr_bytes(mut self, value: &[u8]) -> Self {
1246        push_header(self.as_vec_mut(), 3u16, (value.len() + 1) as u16);
1247        self.as_vec_mut().extend(value);
1248        self.as_vec_mut().push(0);
1249        self
1250    }
1251    pub fn push_domain(mut self, value: &CStr) -> Self {
1252        push_header(
1253            self.as_vec_mut(),
1254            4u16,
1255            value.to_bytes_with_nul().len() as u16,
1256        );
1257        self.as_vec_mut().extend(value.to_bytes_with_nul());
1258        self
1259    }
1260    pub fn push_domain_bytes(mut self, value: &[u8]) -> Self {
1261        push_header(self.as_vec_mut(), 4u16, (value.len() + 1) as u16);
1262        self.as_vec_mut().extend(value);
1263        self.as_vec_mut().push(0);
1264        self
1265    }
1266    pub fn push_negative(mut self, value: ()) -> Self {
1267        push_header(self.as_vec_mut(), 5u16, 0 as u16);
1268        self
1269    }
1270    pub fn push_expiry(mut self, value: u64) -> Self {
1271        push_header(self.as_vec_mut(), 6u16, 8 as u16);
1272        self.as_vec_mut().extend(value.to_ne_bytes());
1273        self
1274    }
1275}
1276impl<Prev: Pusher> Drop for PushIpMap<Prev> {
1277    fn drop(&mut self) {
1278        if let Some(prev) = &mut self.prev {
1279            if let Some(header_offset) = &self.header_offset {
1280                finalize_nested_header(prev.as_vec_mut(), *header_offset);
1281            }
1282        }
1283    }
1284}
1285pub struct PushIpMapReqs<Prev: Pusher> {
1286    pub(crate) prev: Option<Prev>,
1287    pub(crate) header_offset: Option<usize>,
1288}
1289impl<Prev: Pusher> Pusher for PushIpMapReqs<Prev> {
1290    fn as_vec_mut(&mut self) -> &mut Vec<u8> {
1291        self.prev.as_mut().unwrap().as_vec_mut()
1292    }
1293    fn as_vec(&self) -> &Vec<u8> {
1294        self.prev.as_ref().unwrap().as_vec()
1295    }
1296}
1297impl<Prev: Pusher> PushIpMapReqs<Prev> {
1298    pub fn new(prev: Prev) -> Self {
1299        Self {
1300            prev: Some(prev),
1301            header_offset: None,
1302        }
1303    }
1304    pub fn end_nested(mut self) -> Prev {
1305        let mut prev = self.prev.take().unwrap();
1306        if let Some(header_offset) = &self.header_offset {
1307            finalize_nested_header(prev.as_vec_mut(), *header_offset);
1308        }
1309        prev
1310    }
1311    #[doc = "Attribute may repeat multiple times (treat it as array)"]
1312    pub fn nested_requests(mut self) -> PushIpMap<Self> {
1313        let header_offset = push_nested_header(self.as_vec_mut(), 1u16);
1314        PushIpMap {
1315            prev: Some(self),
1316            header_offset: Some(header_offset),
1317        }
1318    }
1319}
1320impl<Prev: Pusher> Drop for PushIpMapReqs<Prev> {
1321    fn drop(&mut self) {
1322        if let Some(prev) = &mut self.prev {
1323            if let Some(header_offset) = &self.header_offset {
1324                finalize_nested_header(prev.as_vec_mut(), *header_offset);
1325            }
1326        }
1327    }
1328}
1329pub struct PushUnixGid<Prev: Pusher> {
1330    pub(crate) prev: Option<Prev>,
1331    pub(crate) header_offset: Option<usize>,
1332}
1333impl<Prev: Pusher> Pusher for PushUnixGid<Prev> {
1334    fn as_vec_mut(&mut self) -> &mut Vec<u8> {
1335        self.prev.as_mut().unwrap().as_vec_mut()
1336    }
1337    fn as_vec(&self) -> &Vec<u8> {
1338        self.prev.as_ref().unwrap().as_vec()
1339    }
1340}
1341impl<Prev: Pusher> PushUnixGid<Prev> {
1342    pub fn new(prev: Prev) -> Self {
1343        Self {
1344            prev: Some(prev),
1345            header_offset: None,
1346        }
1347    }
1348    pub fn end_nested(mut self) -> Prev {
1349        let mut prev = self.prev.take().unwrap();
1350        if let Some(header_offset) = &self.header_offset {
1351            finalize_nested_header(prev.as_vec_mut(), *header_offset);
1352        }
1353        prev
1354    }
1355    pub fn push_seqno(mut self, value: u64) -> Self {
1356        push_header(self.as_vec_mut(), 1u16, 8 as u16);
1357        self.as_vec_mut().extend(value.to_ne_bytes());
1358        self
1359    }
1360    pub fn push_uid(mut self, value: u32) -> Self {
1361        push_header(self.as_vec_mut(), 2u16, 4 as u16);
1362        self.as_vec_mut().extend(value.to_ne_bytes());
1363        self
1364    }
1365    #[doc = "Attribute may repeat multiple times (treat it as array)"]
1366    pub fn push_gids(mut self, value: u32) -> Self {
1367        push_header(self.as_vec_mut(), 3u16, 4 as u16);
1368        self.as_vec_mut().extend(value.to_ne_bytes());
1369        self
1370    }
1371    pub fn push_negative(mut self, value: ()) -> Self {
1372        push_header(self.as_vec_mut(), 4u16, 0 as u16);
1373        self
1374    }
1375    pub fn push_expiry(mut self, value: u64) -> Self {
1376        push_header(self.as_vec_mut(), 5u16, 8 as u16);
1377        self.as_vec_mut().extend(value.to_ne_bytes());
1378        self
1379    }
1380}
1381impl<Prev: Pusher> Drop for PushUnixGid<Prev> {
1382    fn drop(&mut self) {
1383        if let Some(prev) = &mut self.prev {
1384            if let Some(header_offset) = &self.header_offset {
1385                finalize_nested_header(prev.as_vec_mut(), *header_offset);
1386            }
1387        }
1388    }
1389}
1390pub struct PushUnixGidReqs<Prev: Pusher> {
1391    pub(crate) prev: Option<Prev>,
1392    pub(crate) header_offset: Option<usize>,
1393}
1394impl<Prev: Pusher> Pusher for PushUnixGidReqs<Prev> {
1395    fn as_vec_mut(&mut self) -> &mut Vec<u8> {
1396        self.prev.as_mut().unwrap().as_vec_mut()
1397    }
1398    fn as_vec(&self) -> &Vec<u8> {
1399        self.prev.as_ref().unwrap().as_vec()
1400    }
1401}
1402impl<Prev: Pusher> PushUnixGidReqs<Prev> {
1403    pub fn new(prev: Prev) -> Self {
1404        Self {
1405            prev: Some(prev),
1406            header_offset: None,
1407        }
1408    }
1409    pub fn end_nested(mut self) -> Prev {
1410        let mut prev = self.prev.take().unwrap();
1411        if let Some(header_offset) = &self.header_offset {
1412            finalize_nested_header(prev.as_vec_mut(), *header_offset);
1413        }
1414        prev
1415    }
1416    #[doc = "Attribute may repeat multiple times (treat it as array)"]
1417    pub fn nested_requests(mut self) -> PushUnixGid<Self> {
1418        let header_offset = push_nested_header(self.as_vec_mut(), 1u16);
1419        PushUnixGid {
1420            prev: Some(self),
1421            header_offset: Some(header_offset),
1422        }
1423    }
1424}
1425impl<Prev: Pusher> Drop for PushUnixGidReqs<Prev> {
1426    fn drop(&mut self) {
1427        if let Some(prev) = &mut self.prev {
1428            if let Some(header_offset) = &self.header_offset {
1429                finalize_nested_header(prev.as_vec_mut(), *header_offset);
1430            }
1431        }
1432    }
1433}
1434pub struct PushCacheFlush<Prev: Pusher> {
1435    pub(crate) prev: Option<Prev>,
1436    pub(crate) header_offset: Option<usize>,
1437}
1438impl<Prev: Pusher> Pusher for PushCacheFlush<Prev> {
1439    fn as_vec_mut(&mut self) -> &mut Vec<u8> {
1440        self.prev.as_mut().unwrap().as_vec_mut()
1441    }
1442    fn as_vec(&self) -> &Vec<u8> {
1443        self.prev.as_ref().unwrap().as_vec()
1444    }
1445}
1446impl<Prev: Pusher> PushCacheFlush<Prev> {
1447    pub fn new(prev: Prev) -> Self {
1448        Self {
1449            prev: Some(prev),
1450            header_offset: None,
1451        }
1452    }
1453    pub fn end_nested(mut self) -> Prev {
1454        let mut prev = self.prev.take().unwrap();
1455        if let Some(header_offset) = &self.header_offset {
1456            finalize_nested_header(prev.as_vec_mut(), *header_offset);
1457        }
1458        prev
1459    }
1460    #[doc = "Associated type: [`CacheType`] (1 bit per enumeration)"]
1461    pub fn push_mask(mut self, value: u32) -> Self {
1462        push_header(self.as_vec_mut(), 1u16, 4 as u16);
1463        self.as_vec_mut().extend(value.to_ne_bytes());
1464        self
1465    }
1466}
1467impl<Prev: Pusher> Drop for PushCacheFlush<Prev> {
1468    fn drop(&mut self) {
1469        if let Some(prev) = &mut self.prev {
1470            if let Some(header_offset) = &self.header_offset {
1471                finalize_nested_header(prev.as_vec_mut(), *header_offset);
1472            }
1473        }
1474    }
1475}
1476#[doc = "Notify attributes:\n- [`.get_cache_type()`](IterableCacheNotify::get_cache_type)\n"]
1477#[derive(Debug)]
1478pub struct OpCacheNotifyNotif;
1479impl OpCacheNotifyNotif {
1480    pub const CMD: u8 = 1u8;
1481    pub fn decode_notif<'a>(buf: &'a [u8]) -> IterableCacheNotify<'a> {
1482        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1483        IterableCacheNotify::with_loc(attrs, buf.as_ptr() as usize)
1484    }
1485}
1486pub struct NotifGroup;
1487impl NotifGroup {
1488    pub const NONE: &str = "none";
1489    pub const NONE_CSTR: &CStr = c"none";
1490    #[doc = "Notifications:\n- [`OpCacheNotifyNotif`]\n"]
1491    pub const EXPORTD: &str = "exportd";
1492    #[doc = "Notifications:\n- [`OpCacheNotifyNotif`]\n"]
1493    pub const EXPORTD_CSTR: &CStr = c"exportd";
1494}
1495#[doc = "Dump all pending ip_map requests\n\nFlags: admin-perm\n\nReply attributes:\n- [.get_requests()](IterableIpMapReqs::get_requests)\n\n"]
1496#[derive(Debug)]
1497pub struct OpIpMapGetReqsDump<'r> {
1498    request: Request<'r>,
1499}
1500impl<'r> OpIpMapGetReqsDump<'r> {
1501    pub fn new(mut request: Request<'r>) -> Self {
1502        Self::write_header(request.buf_mut());
1503        Self {
1504            request: request.set_dump(),
1505        }
1506    }
1507    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushIpMapReqs<&'buf mut Vec<u8>> {
1508        Self::write_header(buf);
1509        PushIpMapReqs::new(buf)
1510    }
1511    pub fn encode(&mut self) -> PushIpMapReqs<&mut Vec<u8>> {
1512        PushIpMapReqs::new(self.request.buf_mut())
1513    }
1514    pub fn into_encoder(self) -> PushIpMapReqs<RequestBuf<'r>> {
1515        PushIpMapReqs::new(self.request.buf)
1516    }
1517    pub fn decode_request<'a>(buf: &'a [u8]) -> IterableIpMapReqs<'a> {
1518        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1519        IterableIpMapReqs::with_loc(attrs, buf.as_ptr() as usize)
1520    }
1521    fn write_header<Prev: Pusher>(prev: &mut Prev) {
1522        let mut header = BuiltinNfgenmsg::new();
1523        header.cmd = 2u8;
1524        header.version = 1u8;
1525        prev.as_vec_mut().extend(header.as_slice());
1526    }
1527}
1528impl NetlinkRequest for OpIpMapGetReqsDump<'_> {
1529    fn protocol(&self) -> Protocol {
1530        Protocol::Generic("sunrpc".as_bytes())
1531    }
1532    fn flags(&self) -> u16 {
1533        self.request.flags
1534    }
1535    fn payload(&self) -> &[u8] {
1536        self.request.buf()
1537    }
1538    type ReplyType<'buf> = IterableIpMapReqs<'buf>;
1539    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1540        Self::decode_request(buf)
1541    }
1542    fn lookup(
1543        buf: &[u8],
1544        offset: usize,
1545        missing_type: Option<u16>,
1546    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1547        Self::decode_request(buf).lookup_attr(offset, missing_type)
1548    }
1549}
1550#[doc = "Respond to one or more ip_map requests\n\nFlags: admin-perm\n\nRequest attributes:\n- [.nested_requests()](PushIpMapReqs::nested_requests)\n\n"]
1551#[derive(Debug)]
1552pub struct OpIpMapSetReqsDo<'r> {
1553    request: Request<'r>,
1554}
1555impl<'r> OpIpMapSetReqsDo<'r> {
1556    pub fn new(mut request: Request<'r>) -> Self {
1557        Self::write_header(request.buf_mut());
1558        Self { request: request }
1559    }
1560    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushIpMapReqs<&'buf mut Vec<u8>> {
1561        Self::write_header(buf);
1562        PushIpMapReqs::new(buf)
1563    }
1564    pub fn encode(&mut self) -> PushIpMapReqs<&mut Vec<u8>> {
1565        PushIpMapReqs::new(self.request.buf_mut())
1566    }
1567    pub fn into_encoder(self) -> PushIpMapReqs<RequestBuf<'r>> {
1568        PushIpMapReqs::new(self.request.buf)
1569    }
1570    pub fn decode_request<'a>(buf: &'a [u8]) -> IterableIpMapReqs<'a> {
1571        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1572        IterableIpMapReqs::with_loc(attrs, buf.as_ptr() as usize)
1573    }
1574    fn write_header<Prev: Pusher>(prev: &mut Prev) {
1575        let mut header = BuiltinNfgenmsg::new();
1576        header.cmd = 3u8;
1577        header.version = 1u8;
1578        prev.as_vec_mut().extend(header.as_slice());
1579    }
1580}
1581impl NetlinkRequest for OpIpMapSetReqsDo<'_> {
1582    fn protocol(&self) -> Protocol {
1583        Protocol::Generic("sunrpc".as_bytes())
1584    }
1585    fn flags(&self) -> u16 {
1586        self.request.flags
1587    }
1588    fn payload(&self) -> &[u8] {
1589        self.request.buf()
1590    }
1591    type ReplyType<'buf> = IterableIpMapReqs<'buf>;
1592    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1593        Self::decode_request(buf)
1594    }
1595    fn lookup(
1596        buf: &[u8],
1597        offset: usize,
1598        missing_type: Option<u16>,
1599    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1600        Self::decode_request(buf).lookup_attr(offset, missing_type)
1601    }
1602}
1603#[doc = "Dump all pending unix_gid requests\n\nFlags: admin-perm\n\nReply attributes:\n- [.get_requests()](IterableUnixGidReqs::get_requests)\n\n"]
1604#[derive(Debug)]
1605pub struct OpUnixGidGetReqsDump<'r> {
1606    request: Request<'r>,
1607}
1608impl<'r> OpUnixGidGetReqsDump<'r> {
1609    pub fn new(mut request: Request<'r>) -> Self {
1610        Self::write_header(request.buf_mut());
1611        Self {
1612            request: request.set_dump(),
1613        }
1614    }
1615    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushUnixGidReqs<&'buf mut Vec<u8>> {
1616        Self::write_header(buf);
1617        PushUnixGidReqs::new(buf)
1618    }
1619    pub fn encode(&mut self) -> PushUnixGidReqs<&mut Vec<u8>> {
1620        PushUnixGidReqs::new(self.request.buf_mut())
1621    }
1622    pub fn into_encoder(self) -> PushUnixGidReqs<RequestBuf<'r>> {
1623        PushUnixGidReqs::new(self.request.buf)
1624    }
1625    pub fn decode_request<'a>(buf: &'a [u8]) -> IterableUnixGidReqs<'a> {
1626        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1627        IterableUnixGidReqs::with_loc(attrs, buf.as_ptr() as usize)
1628    }
1629    fn write_header<Prev: Pusher>(prev: &mut Prev) {
1630        let mut header = BuiltinNfgenmsg::new();
1631        header.cmd = 4u8;
1632        header.version = 1u8;
1633        prev.as_vec_mut().extend(header.as_slice());
1634    }
1635}
1636impl NetlinkRequest for OpUnixGidGetReqsDump<'_> {
1637    fn protocol(&self) -> Protocol {
1638        Protocol::Generic("sunrpc".as_bytes())
1639    }
1640    fn flags(&self) -> u16 {
1641        self.request.flags
1642    }
1643    fn payload(&self) -> &[u8] {
1644        self.request.buf()
1645    }
1646    type ReplyType<'buf> = IterableUnixGidReqs<'buf>;
1647    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1648        Self::decode_request(buf)
1649    }
1650    fn lookup(
1651        buf: &[u8],
1652        offset: usize,
1653        missing_type: Option<u16>,
1654    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1655        Self::decode_request(buf).lookup_attr(offset, missing_type)
1656    }
1657}
1658#[doc = "Respond to one or more unix_gid requests\n\nFlags: admin-perm\n\nRequest attributes:\n- [.nested_requests()](PushUnixGidReqs::nested_requests)\n\n"]
1659#[derive(Debug)]
1660pub struct OpUnixGidSetReqsDo<'r> {
1661    request: Request<'r>,
1662}
1663impl<'r> OpUnixGidSetReqsDo<'r> {
1664    pub fn new(mut request: Request<'r>) -> Self {
1665        Self::write_header(request.buf_mut());
1666        Self { request: request }
1667    }
1668    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushUnixGidReqs<&'buf mut Vec<u8>> {
1669        Self::write_header(buf);
1670        PushUnixGidReqs::new(buf)
1671    }
1672    pub fn encode(&mut self) -> PushUnixGidReqs<&mut Vec<u8>> {
1673        PushUnixGidReqs::new(self.request.buf_mut())
1674    }
1675    pub fn into_encoder(self) -> PushUnixGidReqs<RequestBuf<'r>> {
1676        PushUnixGidReqs::new(self.request.buf)
1677    }
1678    pub fn decode_request<'a>(buf: &'a [u8]) -> IterableUnixGidReqs<'a> {
1679        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1680        IterableUnixGidReqs::with_loc(attrs, buf.as_ptr() as usize)
1681    }
1682    fn write_header<Prev: Pusher>(prev: &mut Prev) {
1683        let mut header = BuiltinNfgenmsg::new();
1684        header.cmd = 5u8;
1685        header.version = 1u8;
1686        prev.as_vec_mut().extend(header.as_slice());
1687    }
1688}
1689impl NetlinkRequest for OpUnixGidSetReqsDo<'_> {
1690    fn protocol(&self) -> Protocol {
1691        Protocol::Generic("sunrpc".as_bytes())
1692    }
1693    fn flags(&self) -> u16 {
1694        self.request.flags
1695    }
1696    fn payload(&self) -> &[u8] {
1697        self.request.buf()
1698    }
1699    type ReplyType<'buf> = IterableUnixGidReqs<'buf>;
1700    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1701        Self::decode_request(buf)
1702    }
1703    fn lookup(
1704        buf: &[u8],
1705        offset: usize,
1706        missing_type: Option<u16>,
1707    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1708        Self::decode_request(buf).lookup_attr(offset, missing_type)
1709    }
1710}
1711#[doc = "Flush sunrpc caches (ip_map and/or unix_gid)\n\nFlags: admin-perm\n\nRequest attributes:\n- [.push_mask()](PushCacheFlush::push_mask)\n\n"]
1712#[derive(Debug)]
1713pub struct OpCacheFlushDo<'r> {
1714    request: Request<'r>,
1715}
1716impl<'r> OpCacheFlushDo<'r> {
1717    pub fn new(mut request: Request<'r>) -> Self {
1718        Self::write_header(request.buf_mut());
1719        Self { request: request }
1720    }
1721    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushCacheFlush<&'buf mut Vec<u8>> {
1722        Self::write_header(buf);
1723        PushCacheFlush::new(buf)
1724    }
1725    pub fn encode(&mut self) -> PushCacheFlush<&mut Vec<u8>> {
1726        PushCacheFlush::new(self.request.buf_mut())
1727    }
1728    pub fn into_encoder(self) -> PushCacheFlush<RequestBuf<'r>> {
1729        PushCacheFlush::new(self.request.buf)
1730    }
1731    pub fn decode_request<'a>(buf: &'a [u8]) -> IterableCacheFlush<'a> {
1732        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1733        IterableCacheFlush::with_loc(attrs, buf.as_ptr() as usize)
1734    }
1735    fn write_header<Prev: Pusher>(prev: &mut Prev) {
1736        let mut header = BuiltinNfgenmsg::new();
1737        header.cmd = 6u8;
1738        header.version = 1u8;
1739        prev.as_vec_mut().extend(header.as_slice());
1740    }
1741}
1742impl NetlinkRequest for OpCacheFlushDo<'_> {
1743    fn protocol(&self) -> Protocol {
1744        Protocol::Generic("sunrpc".as_bytes())
1745    }
1746    fn flags(&self) -> u16 {
1747        self.request.flags
1748    }
1749    fn payload(&self) -> &[u8] {
1750        self.request.buf()
1751    }
1752    type ReplyType<'buf> = IterableCacheFlush<'buf>;
1753    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1754        Self::decode_request(buf)
1755    }
1756    fn lookup(
1757        buf: &[u8],
1758        offset: usize,
1759        missing_type: Option<u16>,
1760    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1761        Self::decode_request(buf).lookup_attr(offset, missing_type)
1762    }
1763}
1764use crate::traits::LookupFn;
1765use crate::utils::RequestBuf;
1766#[derive(Debug)]
1767pub struct Request<'buf> {
1768    buf: RequestBuf<'buf>,
1769    flags: u16,
1770    writeback: Option<&'buf mut Option<RequestInfo>>,
1771}
1772#[allow(unused)]
1773#[derive(Debug, Clone)]
1774pub struct RequestInfo {
1775    protocol: Protocol,
1776    flags: u16,
1777    name: &'static str,
1778    lookup: LookupFn,
1779}
1780impl Request<'static> {
1781    pub fn new() -> Self {
1782        Self::new_from_buf(Vec::new())
1783    }
1784    pub fn new_from_buf(buf: Vec<u8>) -> Self {
1785        Self {
1786            flags: 0,
1787            buf: RequestBuf::Own(buf),
1788            writeback: None,
1789        }
1790    }
1791    pub fn into_buf(self) -> Vec<u8> {
1792        match self.buf {
1793            RequestBuf::Own(buf) => buf,
1794            _ => unreachable!(),
1795        }
1796    }
1797}
1798impl<'buf> Request<'buf> {
1799    pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
1800        buf.clear();
1801        Self::new_extend(buf)
1802    }
1803    pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
1804        Self {
1805            flags: 0,
1806            buf: RequestBuf::Ref(buf),
1807            writeback: None,
1808        }
1809    }
1810    fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
1811        let Some(writeback) = &mut self.writeback else {
1812            return;
1813        };
1814        **writeback = Some(RequestInfo {
1815            protocol,
1816            flags: self.flags,
1817            name,
1818            lookup,
1819        })
1820    }
1821    pub fn buf(&self) -> &Vec<u8> {
1822        self.buf.buf()
1823    }
1824    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
1825        self.buf.buf_mut()
1826    }
1827    #[doc = "Set `NLM_F_CREATE` flag"]
1828    pub fn set_create(mut self) -> Self {
1829        self.flags |= consts::NLM_F_CREATE as u16;
1830        self
1831    }
1832    #[doc = "Set `NLM_F_EXCL` flag"]
1833    pub fn set_excl(mut self) -> Self {
1834        self.flags |= consts::NLM_F_EXCL as u16;
1835        self
1836    }
1837    #[doc = "Set `NLM_F_REPLACE` flag"]
1838    pub fn set_replace(mut self) -> Self {
1839        self.flags |= consts::NLM_F_REPLACE as u16;
1840        self
1841    }
1842    #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
1843    pub fn set_change(self) -> Self {
1844        self.set_create().set_replace()
1845    }
1846    #[doc = "Set `NLM_F_APPEND` flag"]
1847    pub fn set_append(mut self) -> Self {
1848        self.flags |= consts::NLM_F_APPEND as u16;
1849        self
1850    }
1851    #[doc = "Set `self.flags |= flags`"]
1852    pub fn set_flags(mut self, flags: u16) -> Self {
1853        self.flags |= flags;
1854        self
1855    }
1856    #[doc = "Set `self.flags ^= self.flags & flags`"]
1857    pub fn unset_flags(mut self, flags: u16) -> Self {
1858        self.flags ^= self.flags & flags;
1859        self
1860    }
1861    #[doc = "Set `NLM_F_DUMP` flag"]
1862    fn set_dump(mut self) -> Self {
1863        self.flags |= consts::NLM_F_DUMP as u16;
1864        self
1865    }
1866    #[doc = "Dump all pending ip_map requests\n\nFlags: admin-perm\n\nReply attributes:\n- [.get_requests()](IterableIpMapReqs::get_requests)\n\n"]
1867    pub fn op_ip_map_get_reqs_dump(self) -> OpIpMapGetReqsDump<'buf> {
1868        let mut res = OpIpMapGetReqsDump::new(self);
1869        res.request.do_writeback(
1870            res.protocol(),
1871            "op-ip-map-get-reqs-dump",
1872            OpIpMapGetReqsDump::lookup,
1873        );
1874        res
1875    }
1876    #[doc = "Respond to one or more ip_map requests\n\nFlags: admin-perm\n\nRequest attributes:\n- [.nested_requests()](PushIpMapReqs::nested_requests)\n\n"]
1877    pub fn op_ip_map_set_reqs_do(self) -> OpIpMapSetReqsDo<'buf> {
1878        let mut res = OpIpMapSetReqsDo::new(self);
1879        res.request.do_writeback(
1880            res.protocol(),
1881            "op-ip-map-set-reqs-do",
1882            OpIpMapSetReqsDo::lookup,
1883        );
1884        res
1885    }
1886    #[doc = "Dump all pending unix_gid requests\n\nFlags: admin-perm\n\nReply attributes:\n- [.get_requests()](IterableUnixGidReqs::get_requests)\n\n"]
1887    pub fn op_unix_gid_get_reqs_dump(self) -> OpUnixGidGetReqsDump<'buf> {
1888        let mut res = OpUnixGidGetReqsDump::new(self);
1889        res.request.do_writeback(
1890            res.protocol(),
1891            "op-unix-gid-get-reqs-dump",
1892            OpUnixGidGetReqsDump::lookup,
1893        );
1894        res
1895    }
1896    #[doc = "Respond to one or more unix_gid requests\n\nFlags: admin-perm\n\nRequest attributes:\n- [.nested_requests()](PushUnixGidReqs::nested_requests)\n\n"]
1897    pub fn op_unix_gid_set_reqs_do(self) -> OpUnixGidSetReqsDo<'buf> {
1898        let mut res = OpUnixGidSetReqsDo::new(self);
1899        res.request.do_writeback(
1900            res.protocol(),
1901            "op-unix-gid-set-reqs-do",
1902            OpUnixGidSetReqsDo::lookup,
1903        );
1904        res
1905    }
1906    #[doc = "Flush sunrpc caches (ip_map and/or unix_gid)\n\nFlags: admin-perm\n\nRequest attributes:\n- [.push_mask()](PushCacheFlush::push_mask)\n\n"]
1907    pub fn op_cache_flush_do(self) -> OpCacheFlushDo<'buf> {
1908        let mut res = OpCacheFlushDo::new(self);
1909        res.request
1910            .do_writeback(res.protocol(), "op-cache-flush-do", OpCacheFlushDo::lookup);
1911        res
1912    }
1913}
1914#[cfg(test)]
1915mod generated_tests {
1916    use super::*;
1917    #[test]
1918    fn tests() {
1919        let _ = IterableCacheNotify::get_cache_type;
1920        let _ = IterableIpMapReqs::get_requests;
1921        let _ = IterableUnixGidReqs::get_requests;
1922        let _ = OpCacheNotifyNotif;
1923        let _ = PushCacheFlush::<&mut Vec<u8>>::push_mask;
1924        let _ = PushIpMapReqs::<&mut Vec<u8>>::nested_requests;
1925        let _ = PushUnixGidReqs::<&mut Vec<u8>>::nested_requests;
1926    }
1927}