Skip to main content

netlink_bindings/team/
mod.rs

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