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