Skip to main content

netlink_bindings/dev-energymodel/
mod.rs

1#![doc = "Energy model netlink interface to notify its changes.\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 = "dev-energymodel";
17pub const PROTONAME_CSTR: &CStr = c"dev-energymodel";
18#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
19#[derive(Debug, Clone, Copy)]
20pub enum PerfStateFlags {
21    #[doc = "The performance state is inefficient. There is in this perf-domain,\nanother performance state with a higher frequency but a lower or equal\npower cost.\n"]
22    PerfStateInefficient = 1 << 0,
23}
24impl PerfStateFlags {
25    pub fn from_value(value: u64) -> Option<Self> {
26        Some(match value {
27            n if n == 1 << 0 => Self::PerfStateInefficient,
28            _ => return None,
29        })
30    }
31}
32#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
33#[derive(Debug, Clone, Copy)]
34pub enum PerfDomainFlags {
35    #[doc = "The power values are in micro-Watts or some other scale.\n"]
36    PerfDomainMicrowatts = 1 << 0,
37    #[doc = "Skip inefficient states when estimating energy consumption.\n"]
38    PerfDomainSkipInefficiencies = 1 << 1,
39    #[doc = "The power values are artificial and might be created by platform missing\nreal power information.\n"]
40    PerfDomainArtificial = 1 << 2,
41}
42impl PerfDomainFlags {
43    pub fn from_value(value: u64) -> Option<Self> {
44        Some(match value {
45            n if n == 1 << 0 => Self::PerfDomainMicrowatts,
46            n if n == 1 << 1 => Self::PerfDomainSkipInefficiencies,
47            n if n == 1 << 2 => Self::PerfDomainArtificial,
48            _ => return None,
49        })
50    }
51}
52#[derive(Clone)]
53pub enum PerfDomain<'a> {
54    Pad(&'a [u8]),
55    #[doc = "A unique ID number for each performance domain.\n"]
56    PerfDomainId(u32),
57    #[doc = "Bitmask of performance domain flags.\n\nAssociated type: [`PerfDomainFlags`] (enum)"]
58    Flags(u64),
59    #[doc = "CPUs that belong to this performance domain.\n\nAttribute may repeat multiple times (treat it as array)"]
60    Cpus(u64),
61}
62impl<'a> IterablePerfDomain<'a> {
63    pub fn get_pad(&self) -> Result<&'a [u8], ErrorContext> {
64        let mut iter = self.clone();
65        iter.pos = 0;
66        for attr in iter {
67            if let Ok(PerfDomain::Pad(val)) = attr {
68                return Ok(val);
69            }
70        }
71        Err(ErrorContext::new_missing(
72            "PerfDomain",
73            "Pad",
74            self.orig_loc,
75            self.buf.as_ptr() as usize,
76        ))
77    }
78    #[doc = "A unique ID number for each performance domain.\n"]
79    pub fn get_perf_domain_id(&self) -> Result<u32, ErrorContext> {
80        let mut iter = self.clone();
81        iter.pos = 0;
82        for attr in iter {
83            if let Ok(PerfDomain::PerfDomainId(val)) = attr {
84                return Ok(val);
85            }
86        }
87        Err(ErrorContext::new_missing(
88            "PerfDomain",
89            "PerfDomainId",
90            self.orig_loc,
91            self.buf.as_ptr() as usize,
92        ))
93    }
94    #[doc = "Bitmask of performance domain flags.\n\nAssociated type: [`PerfDomainFlags`] (enum)"]
95    pub fn get_flags(&self) -> Result<u64, ErrorContext> {
96        let mut iter = self.clone();
97        iter.pos = 0;
98        for attr in iter {
99            if let Ok(PerfDomain::Flags(val)) = attr {
100                return Ok(val);
101            }
102        }
103        Err(ErrorContext::new_missing(
104            "PerfDomain",
105            "Flags",
106            self.orig_loc,
107            self.buf.as_ptr() as usize,
108        ))
109    }
110    #[doc = "CPUs that belong to this performance domain.\n\nAttribute may repeat multiple times (treat it as array)"]
111    pub fn get_cpus(&self) -> MultiAttrIterable<Self, PerfDomain<'a>, u64> {
112        MultiAttrIterable::new(self.clone(), |variant| {
113            if let PerfDomain::Cpus(val) = variant {
114                Some(val)
115            } else {
116                None
117            }
118        })
119    }
120}
121impl PerfDomain<'_> {
122    pub fn new<'a>(buf: &'a [u8]) -> IterablePerfDomain<'a> {
123        IterablePerfDomain::with_loc(buf, buf.as_ptr() as usize)
124    }
125    fn attr_from_type(r#type: u16) -> Option<&'static str> {
126        let res = match r#type {
127            1u16 => "Pad",
128            2u16 => "PerfDomainId",
129            3u16 => "Flags",
130            4u16 => "Cpus",
131            _ => return None,
132        };
133        Some(res)
134    }
135}
136#[derive(Clone, Copy, Default)]
137pub struct IterablePerfDomain<'a> {
138    buf: &'a [u8],
139    pos: usize,
140    orig_loc: usize,
141}
142impl<'a> IterablePerfDomain<'a> {
143    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
144        Self {
145            buf,
146            pos: 0,
147            orig_loc,
148        }
149    }
150    pub fn get_buf(&self) -> &'a [u8] {
151        self.buf
152    }
153}
154impl<'a> Iterator for IterablePerfDomain<'a> {
155    type Item = Result<PerfDomain<'a>, ErrorContext>;
156    fn next(&mut self) -> Option<Self::Item> {
157        let mut pos;
158        let mut r#type;
159        loop {
160            pos = self.pos;
161            r#type = None;
162            if self.buf.len() == self.pos {
163                return None;
164            }
165            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
166                self.pos = self.buf.len();
167                break;
168            };
169            r#type = Some(header.r#type);
170            let res = match header.r#type {
171                1u16 => PerfDomain::Pad({
172                    let res = Some(next);
173                    let Some(val) = res else { break };
174                    val
175                }),
176                2u16 => PerfDomain::PerfDomainId({
177                    let res = parse_u32(next);
178                    let Some(val) = res else { break };
179                    val
180                }),
181                3u16 => PerfDomain::Flags({
182                    let res = parse_u64(next);
183                    let Some(val) = res else { break };
184                    val
185                }),
186                4u16 => PerfDomain::Cpus({
187                    let res = parse_u64(next);
188                    let Some(val) = res else { break };
189                    val
190                }),
191                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
192                n => continue,
193            };
194            return Some(Ok(res));
195        }
196        Some(Err(ErrorContext::new(
197            "PerfDomain",
198            r#type.and_then(|t| PerfDomain::attr_from_type(t)),
199            self.orig_loc,
200            self.buf.as_ptr().wrapping_add(pos) as usize,
201        )))
202    }
203}
204impl<'a> std::fmt::Debug for IterablePerfDomain<'_> {
205    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
206        let mut fmt = f.debug_struct("PerfDomain");
207        for attr in self.clone() {
208            let attr = match attr {
209                Ok(a) => a,
210                Err(err) => {
211                    fmt.finish()?;
212                    f.write_str("Err(")?;
213                    err.fmt(f)?;
214                    return f.write_str(")");
215                }
216            };
217            match attr {
218                PerfDomain::Pad(val) => fmt.field("Pad", &val),
219                PerfDomain::PerfDomainId(val) => fmt.field("PerfDomainId", &val),
220                PerfDomain::Flags(val) => fmt.field(
221                    "Flags",
222                    &FormatFlags(val.into(), PerfDomainFlags::from_value),
223                ),
224                PerfDomain::Cpus(val) => fmt.field("Cpus", &val),
225            };
226        }
227        fmt.finish()
228    }
229}
230impl IterablePerfDomain<'_> {
231    pub fn lookup_attr(
232        &self,
233        offset: usize,
234        missing_type: Option<u16>,
235    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
236        let mut stack = Vec::new();
237        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
238        if missing_type.is_some() && cur == offset {
239            stack.push(("PerfDomain", offset));
240            return (
241                stack,
242                missing_type.and_then(|t| PerfDomain::attr_from_type(t)),
243            );
244        }
245        if cur > offset || cur + self.buf.len() < offset {
246            return (stack, None);
247        }
248        let mut attrs = self.clone();
249        let mut last_off = cur + attrs.pos;
250        while let Some(attr) = attrs.next() {
251            let Ok(attr) = attr else { break };
252            match attr {
253                PerfDomain::Pad(val) => {
254                    if last_off == offset {
255                        stack.push(("Pad", last_off));
256                        break;
257                    }
258                }
259                PerfDomain::PerfDomainId(val) => {
260                    if last_off == offset {
261                        stack.push(("PerfDomainId", last_off));
262                        break;
263                    }
264                }
265                PerfDomain::Flags(val) => {
266                    if last_off == offset {
267                        stack.push(("Flags", last_off));
268                        break;
269                    }
270                }
271                PerfDomain::Cpus(val) => {
272                    if last_off == offset {
273                        stack.push(("Cpus", last_off));
274                        break;
275                    }
276                }
277                _ => {}
278            };
279            last_off = cur + attrs.pos;
280        }
281        if !stack.is_empty() {
282            stack.push(("PerfDomain", cur));
283        }
284        (stack, None)
285    }
286}
287#[derive(Clone)]
288pub enum PerfTable<'a> {
289    #[doc = "A unique ID number for each performance domain.\n"]
290    PerfDomainId(u32),
291    #[doc = "Attribute may repeat multiple times (treat it as array)"]
292    PerfState(IterablePerfState<'a>),
293}
294impl<'a> IterablePerfTable<'a> {
295    #[doc = "A unique ID number for each performance domain.\n"]
296    pub fn get_perf_domain_id(&self) -> Result<u32, ErrorContext> {
297        let mut iter = self.clone();
298        iter.pos = 0;
299        for attr in iter {
300            if let Ok(PerfTable::PerfDomainId(val)) = attr {
301                return Ok(val);
302            }
303        }
304        Err(ErrorContext::new_missing(
305            "PerfTable",
306            "PerfDomainId",
307            self.orig_loc,
308            self.buf.as_ptr() as usize,
309        ))
310    }
311    #[doc = "Attribute may repeat multiple times (treat it as array)"]
312    pub fn get_perf_state(&self) -> MultiAttrIterable<Self, PerfTable<'a>, IterablePerfState<'a>> {
313        MultiAttrIterable::new(self.clone(), |variant| {
314            if let PerfTable::PerfState(val) = variant {
315                Some(val)
316            } else {
317                None
318            }
319        })
320    }
321}
322impl PerfTable<'_> {
323    pub fn new<'a>(buf: &'a [u8]) -> IterablePerfTable<'a> {
324        IterablePerfTable::with_loc(buf, buf.as_ptr() as usize)
325    }
326    fn attr_from_type(r#type: u16) -> Option<&'static str> {
327        let res = match r#type {
328            1u16 => "PerfDomainId",
329            2u16 => "PerfState",
330            _ => return None,
331        };
332        Some(res)
333    }
334}
335#[derive(Clone, Copy, Default)]
336pub struct IterablePerfTable<'a> {
337    buf: &'a [u8],
338    pos: usize,
339    orig_loc: usize,
340}
341impl<'a> IterablePerfTable<'a> {
342    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
343        Self {
344            buf,
345            pos: 0,
346            orig_loc,
347        }
348    }
349    pub fn get_buf(&self) -> &'a [u8] {
350        self.buf
351    }
352}
353impl<'a> Iterator for IterablePerfTable<'a> {
354    type Item = Result<PerfTable<'a>, ErrorContext>;
355    fn next(&mut self) -> Option<Self::Item> {
356        let mut pos;
357        let mut r#type;
358        loop {
359            pos = self.pos;
360            r#type = None;
361            if self.buf.len() == self.pos {
362                return None;
363            }
364            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
365                self.pos = self.buf.len();
366                break;
367            };
368            r#type = Some(header.r#type);
369            let res = match header.r#type {
370                1u16 => PerfTable::PerfDomainId({
371                    let res = parse_u32(next);
372                    let Some(val) = res else { break };
373                    val
374                }),
375                2u16 => PerfTable::PerfState({
376                    let res = Some(IterablePerfState::with_loc(next, self.orig_loc));
377                    let Some(val) = res else { break };
378                    val
379                }),
380                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
381                n => continue,
382            };
383            return Some(Ok(res));
384        }
385        Some(Err(ErrorContext::new(
386            "PerfTable",
387            r#type.and_then(|t| PerfTable::attr_from_type(t)),
388            self.orig_loc,
389            self.buf.as_ptr().wrapping_add(pos) as usize,
390        )))
391    }
392}
393impl<'a> std::fmt::Debug for IterablePerfTable<'_> {
394    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
395        let mut fmt = f.debug_struct("PerfTable");
396        for attr in self.clone() {
397            let attr = match attr {
398                Ok(a) => a,
399                Err(err) => {
400                    fmt.finish()?;
401                    f.write_str("Err(")?;
402                    err.fmt(f)?;
403                    return f.write_str(")");
404                }
405            };
406            match attr {
407                PerfTable::PerfDomainId(val) => fmt.field("PerfDomainId", &val),
408                PerfTable::PerfState(val) => fmt.field("PerfState", &val),
409            };
410        }
411        fmt.finish()
412    }
413}
414impl IterablePerfTable<'_> {
415    pub fn lookup_attr(
416        &self,
417        offset: usize,
418        missing_type: Option<u16>,
419    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
420        let mut stack = Vec::new();
421        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
422        if missing_type.is_some() && cur == offset {
423            stack.push(("PerfTable", offset));
424            return (
425                stack,
426                missing_type.and_then(|t| PerfTable::attr_from_type(t)),
427            );
428        }
429        if cur > offset || cur + self.buf.len() < offset {
430            return (stack, None);
431        }
432        let mut attrs = self.clone();
433        let mut last_off = cur + attrs.pos;
434        let mut missing = None;
435        while let Some(attr) = attrs.next() {
436            let Ok(attr) = attr else { break };
437            match attr {
438                PerfTable::PerfDomainId(val) => {
439                    if last_off == offset {
440                        stack.push(("PerfDomainId", last_off));
441                        break;
442                    }
443                }
444                PerfTable::PerfState(val) => {
445                    (stack, missing) = val.lookup_attr(offset, missing_type);
446                    if !stack.is_empty() {
447                        break;
448                    }
449                }
450                _ => {}
451            };
452            last_off = cur + attrs.pos;
453        }
454        if !stack.is_empty() {
455            stack.push(("PerfTable", cur));
456        }
457        (stack, missing)
458    }
459}
460#[derive(Clone)]
461pub enum PerfState<'a> {
462    Pad(&'a [u8]),
463    #[doc = "CPU performance (capacity) at a given frequency.\n"]
464    Performance(u64),
465    #[doc = "The frequency in KHz, for consistency with CPUFreq.\n"]
466    Frequency(u64),
467    #[doc = "The power consumed at this level (by 1 CPU or by a registered device).\nIt can be a total power: static and dynamic.\n"]
468    Power(u64),
469    #[doc = "The cost coefficient associated with this level, used during energy\ncalculation. Equal to: power \\* max_frequency / frequency.\n"]
470    Cost(u64),
471    #[doc = "Bitmask of performance state flags.\n\nAssociated type: [`PerfStateFlags`] (enum)"]
472    Flags(u64),
473}
474impl<'a> IterablePerfState<'a> {
475    pub fn get_pad(&self) -> Result<&'a [u8], ErrorContext> {
476        let mut iter = self.clone();
477        iter.pos = 0;
478        for attr in iter {
479            if let Ok(PerfState::Pad(val)) = attr {
480                return Ok(val);
481            }
482        }
483        Err(ErrorContext::new_missing(
484            "PerfState",
485            "Pad",
486            self.orig_loc,
487            self.buf.as_ptr() as usize,
488        ))
489    }
490    #[doc = "CPU performance (capacity) at a given frequency.\n"]
491    pub fn get_performance(&self) -> Result<u64, ErrorContext> {
492        let mut iter = self.clone();
493        iter.pos = 0;
494        for attr in iter {
495            if let Ok(PerfState::Performance(val)) = attr {
496                return Ok(val);
497            }
498        }
499        Err(ErrorContext::new_missing(
500            "PerfState",
501            "Performance",
502            self.orig_loc,
503            self.buf.as_ptr() as usize,
504        ))
505    }
506    #[doc = "The frequency in KHz, for consistency with CPUFreq.\n"]
507    pub fn get_frequency(&self) -> Result<u64, ErrorContext> {
508        let mut iter = self.clone();
509        iter.pos = 0;
510        for attr in iter {
511            if let Ok(PerfState::Frequency(val)) = attr {
512                return Ok(val);
513            }
514        }
515        Err(ErrorContext::new_missing(
516            "PerfState",
517            "Frequency",
518            self.orig_loc,
519            self.buf.as_ptr() as usize,
520        ))
521    }
522    #[doc = "The power consumed at this level (by 1 CPU or by a registered device).\nIt can be a total power: static and dynamic.\n"]
523    pub fn get_power(&self) -> Result<u64, ErrorContext> {
524        let mut iter = self.clone();
525        iter.pos = 0;
526        for attr in iter {
527            if let Ok(PerfState::Power(val)) = attr {
528                return Ok(val);
529            }
530        }
531        Err(ErrorContext::new_missing(
532            "PerfState",
533            "Power",
534            self.orig_loc,
535            self.buf.as_ptr() as usize,
536        ))
537    }
538    #[doc = "The cost coefficient associated with this level, used during energy\ncalculation. Equal to: power \\* max_frequency / frequency.\n"]
539    pub fn get_cost(&self) -> Result<u64, ErrorContext> {
540        let mut iter = self.clone();
541        iter.pos = 0;
542        for attr in iter {
543            if let Ok(PerfState::Cost(val)) = attr {
544                return Ok(val);
545            }
546        }
547        Err(ErrorContext::new_missing(
548            "PerfState",
549            "Cost",
550            self.orig_loc,
551            self.buf.as_ptr() as usize,
552        ))
553    }
554    #[doc = "Bitmask of performance state flags.\n\nAssociated type: [`PerfStateFlags`] (enum)"]
555    pub fn get_flags(&self) -> Result<u64, ErrorContext> {
556        let mut iter = self.clone();
557        iter.pos = 0;
558        for attr in iter {
559            if let Ok(PerfState::Flags(val)) = attr {
560                return Ok(val);
561            }
562        }
563        Err(ErrorContext::new_missing(
564            "PerfState",
565            "Flags",
566            self.orig_loc,
567            self.buf.as_ptr() as usize,
568        ))
569    }
570}
571impl PerfState<'_> {
572    pub fn new<'a>(buf: &'a [u8]) -> IterablePerfState<'a> {
573        IterablePerfState::with_loc(buf, buf.as_ptr() as usize)
574    }
575    fn attr_from_type(r#type: u16) -> Option<&'static str> {
576        let res = match r#type {
577            1u16 => "Pad",
578            2u16 => "Performance",
579            3u16 => "Frequency",
580            4u16 => "Power",
581            5u16 => "Cost",
582            6u16 => "Flags",
583            _ => return None,
584        };
585        Some(res)
586    }
587}
588#[derive(Clone, Copy, Default)]
589pub struct IterablePerfState<'a> {
590    buf: &'a [u8],
591    pos: usize,
592    orig_loc: usize,
593}
594impl<'a> IterablePerfState<'a> {
595    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
596        Self {
597            buf,
598            pos: 0,
599            orig_loc,
600        }
601    }
602    pub fn get_buf(&self) -> &'a [u8] {
603        self.buf
604    }
605}
606impl<'a> Iterator for IterablePerfState<'a> {
607    type Item = Result<PerfState<'a>, ErrorContext>;
608    fn next(&mut self) -> Option<Self::Item> {
609        let mut pos;
610        let mut r#type;
611        loop {
612            pos = self.pos;
613            r#type = None;
614            if self.buf.len() == self.pos {
615                return None;
616            }
617            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
618                self.pos = self.buf.len();
619                break;
620            };
621            r#type = Some(header.r#type);
622            let res = match header.r#type {
623                1u16 => PerfState::Pad({
624                    let res = Some(next);
625                    let Some(val) = res else { break };
626                    val
627                }),
628                2u16 => PerfState::Performance({
629                    let res = parse_u64(next);
630                    let Some(val) = res else { break };
631                    val
632                }),
633                3u16 => PerfState::Frequency({
634                    let res = parse_u64(next);
635                    let Some(val) = res else { break };
636                    val
637                }),
638                4u16 => PerfState::Power({
639                    let res = parse_u64(next);
640                    let Some(val) = res else { break };
641                    val
642                }),
643                5u16 => PerfState::Cost({
644                    let res = parse_u64(next);
645                    let Some(val) = res else { break };
646                    val
647                }),
648                6u16 => PerfState::Flags({
649                    let res = parse_u64(next);
650                    let Some(val) = res else { break };
651                    val
652                }),
653                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
654                n => continue,
655            };
656            return Some(Ok(res));
657        }
658        Some(Err(ErrorContext::new(
659            "PerfState",
660            r#type.and_then(|t| PerfState::attr_from_type(t)),
661            self.orig_loc,
662            self.buf.as_ptr().wrapping_add(pos) as usize,
663        )))
664    }
665}
666impl<'a> std::fmt::Debug for IterablePerfState<'_> {
667    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
668        let mut fmt = f.debug_struct("PerfState");
669        for attr in self.clone() {
670            let attr = match attr {
671                Ok(a) => a,
672                Err(err) => {
673                    fmt.finish()?;
674                    f.write_str("Err(")?;
675                    err.fmt(f)?;
676                    return f.write_str(")");
677                }
678            };
679            match attr {
680                PerfState::Pad(val) => fmt.field("Pad", &val),
681                PerfState::Performance(val) => fmt.field("Performance", &val),
682                PerfState::Frequency(val) => fmt.field("Frequency", &val),
683                PerfState::Power(val) => fmt.field("Power", &val),
684                PerfState::Cost(val) => fmt.field("Cost", &val),
685                PerfState::Flags(val) => fmt.field(
686                    "Flags",
687                    &FormatFlags(val.into(), PerfStateFlags::from_value),
688                ),
689            };
690        }
691        fmt.finish()
692    }
693}
694impl IterablePerfState<'_> {
695    pub fn lookup_attr(
696        &self,
697        offset: usize,
698        missing_type: Option<u16>,
699    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
700        let mut stack = Vec::new();
701        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
702        if missing_type.is_some() && cur == offset {
703            stack.push(("PerfState", offset));
704            return (
705                stack,
706                missing_type.and_then(|t| PerfState::attr_from_type(t)),
707            );
708        }
709        if cur > offset || cur + self.buf.len() < offset {
710            return (stack, None);
711        }
712        let mut attrs = self.clone();
713        let mut last_off = cur + attrs.pos;
714        while let Some(attr) = attrs.next() {
715            let Ok(attr) = attr else { break };
716            match attr {
717                PerfState::Pad(val) => {
718                    if last_off == offset {
719                        stack.push(("Pad", last_off));
720                        break;
721                    }
722                }
723                PerfState::Performance(val) => {
724                    if last_off == offset {
725                        stack.push(("Performance", last_off));
726                        break;
727                    }
728                }
729                PerfState::Frequency(val) => {
730                    if last_off == offset {
731                        stack.push(("Frequency", last_off));
732                        break;
733                    }
734                }
735                PerfState::Power(val) => {
736                    if last_off == offset {
737                        stack.push(("Power", last_off));
738                        break;
739                    }
740                }
741                PerfState::Cost(val) => {
742                    if last_off == offset {
743                        stack.push(("Cost", last_off));
744                        break;
745                    }
746                }
747                PerfState::Flags(val) => {
748                    if last_off == offset {
749                        stack.push(("Flags", last_off));
750                        break;
751                    }
752                }
753                _ => {}
754            };
755            last_off = cur + attrs.pos;
756        }
757        if !stack.is_empty() {
758            stack.push(("PerfState", cur));
759        }
760        (stack, None)
761    }
762}
763pub struct PushPerfDomain<Prev: Rec> {
764    pub(crate) prev: Option<Prev>,
765    pub(crate) header_offset: Option<usize>,
766}
767impl<Prev: Rec> Rec for PushPerfDomain<Prev> {
768    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
769        self.prev.as_mut().unwrap().as_rec_mut()
770    }
771    fn as_rec(&self) -> &Vec<u8> {
772        self.prev.as_ref().unwrap().as_rec()
773    }
774}
775impl<Prev: Rec> PushPerfDomain<Prev> {
776    pub fn new(prev: Prev) -> Self {
777        Self {
778            prev: Some(prev),
779            header_offset: None,
780        }
781    }
782    pub fn end_nested(mut self) -> Prev {
783        let mut prev = self.prev.take().unwrap();
784        if let Some(header_offset) = &self.header_offset {
785            finalize_nested_header(prev.as_rec_mut(), *header_offset);
786        }
787        prev
788    }
789    pub fn push_pad(mut self, value: &[u8]) -> Self {
790        push_header(self.as_rec_mut(), 1u16, value.len() as u16);
791        self.as_rec_mut().extend(value);
792        self
793    }
794    #[doc = "A unique ID number for each performance domain.\n"]
795    pub fn push_perf_domain_id(mut self, value: u32) -> Self {
796        push_header(self.as_rec_mut(), 2u16, 4 as u16);
797        self.as_rec_mut().extend(value.to_ne_bytes());
798        self
799    }
800    #[doc = "Bitmask of performance domain flags.\n\nAssociated type: [`PerfDomainFlags`] (enum)"]
801    pub fn push_flags(mut self, value: u64) -> Self {
802        push_header(self.as_rec_mut(), 3u16, 8 as u16);
803        self.as_rec_mut().extend(value.to_ne_bytes());
804        self
805    }
806    #[doc = "CPUs that belong to this performance domain.\n\nAttribute may repeat multiple times (treat it as array)"]
807    pub fn push_cpus(mut self, value: u64) -> Self {
808        push_header(self.as_rec_mut(), 4u16, 8 as u16);
809        self.as_rec_mut().extend(value.to_ne_bytes());
810        self
811    }
812}
813impl<Prev: Rec> Drop for PushPerfDomain<Prev> {
814    fn drop(&mut self) {
815        if let Some(prev) = &mut self.prev {
816            if let Some(header_offset) = &self.header_offset {
817                finalize_nested_header(prev.as_rec_mut(), *header_offset);
818            }
819        }
820    }
821}
822pub struct PushPerfTable<Prev: Rec> {
823    pub(crate) prev: Option<Prev>,
824    pub(crate) header_offset: Option<usize>,
825}
826impl<Prev: Rec> Rec for PushPerfTable<Prev> {
827    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
828        self.prev.as_mut().unwrap().as_rec_mut()
829    }
830    fn as_rec(&self) -> &Vec<u8> {
831        self.prev.as_ref().unwrap().as_rec()
832    }
833}
834impl<Prev: Rec> PushPerfTable<Prev> {
835    pub fn new(prev: Prev) -> Self {
836        Self {
837            prev: Some(prev),
838            header_offset: None,
839        }
840    }
841    pub fn end_nested(mut self) -> Prev {
842        let mut prev = self.prev.take().unwrap();
843        if let Some(header_offset) = &self.header_offset {
844            finalize_nested_header(prev.as_rec_mut(), *header_offset);
845        }
846        prev
847    }
848    #[doc = "A unique ID number for each performance domain.\n"]
849    pub fn push_perf_domain_id(mut self, value: u32) -> Self {
850        push_header(self.as_rec_mut(), 1u16, 4 as u16);
851        self.as_rec_mut().extend(value.to_ne_bytes());
852        self
853    }
854    #[doc = "Attribute may repeat multiple times (treat it as array)"]
855    pub fn nested_perf_state(mut self) -> PushPerfState<Self> {
856        let header_offset = push_nested_header(self.as_rec_mut(), 2u16);
857        PushPerfState {
858            prev: Some(self),
859            header_offset: Some(header_offset),
860        }
861    }
862}
863impl<Prev: Rec> Drop for PushPerfTable<Prev> {
864    fn drop(&mut self) {
865        if let Some(prev) = &mut self.prev {
866            if let Some(header_offset) = &self.header_offset {
867                finalize_nested_header(prev.as_rec_mut(), *header_offset);
868            }
869        }
870    }
871}
872pub struct PushPerfState<Prev: Rec> {
873    pub(crate) prev: Option<Prev>,
874    pub(crate) header_offset: Option<usize>,
875}
876impl<Prev: Rec> Rec for PushPerfState<Prev> {
877    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
878        self.prev.as_mut().unwrap().as_rec_mut()
879    }
880    fn as_rec(&self) -> &Vec<u8> {
881        self.prev.as_ref().unwrap().as_rec()
882    }
883}
884impl<Prev: Rec> PushPerfState<Prev> {
885    pub fn new(prev: Prev) -> Self {
886        Self {
887            prev: Some(prev),
888            header_offset: None,
889        }
890    }
891    pub fn end_nested(mut self) -> Prev {
892        let mut prev = self.prev.take().unwrap();
893        if let Some(header_offset) = &self.header_offset {
894            finalize_nested_header(prev.as_rec_mut(), *header_offset);
895        }
896        prev
897    }
898    pub fn push_pad(mut self, value: &[u8]) -> Self {
899        push_header(self.as_rec_mut(), 1u16, value.len() as u16);
900        self.as_rec_mut().extend(value);
901        self
902    }
903    #[doc = "CPU performance (capacity) at a given frequency.\n"]
904    pub fn push_performance(mut self, value: u64) -> Self {
905        push_header(self.as_rec_mut(), 2u16, 8 as u16);
906        self.as_rec_mut().extend(value.to_ne_bytes());
907        self
908    }
909    #[doc = "The frequency in KHz, for consistency with CPUFreq.\n"]
910    pub fn push_frequency(mut self, value: u64) -> Self {
911        push_header(self.as_rec_mut(), 3u16, 8 as u16);
912        self.as_rec_mut().extend(value.to_ne_bytes());
913        self
914    }
915    #[doc = "The power consumed at this level (by 1 CPU or by a registered device).\nIt can be a total power: static and dynamic.\n"]
916    pub fn push_power(mut self, value: u64) -> Self {
917        push_header(self.as_rec_mut(), 4u16, 8 as u16);
918        self.as_rec_mut().extend(value.to_ne_bytes());
919        self
920    }
921    #[doc = "The cost coefficient associated with this level, used during energy\ncalculation. Equal to: power \\* max_frequency / frequency.\n"]
922    pub fn push_cost(mut self, value: u64) -> Self {
923        push_header(self.as_rec_mut(), 5u16, 8 as u16);
924        self.as_rec_mut().extend(value.to_ne_bytes());
925        self
926    }
927    #[doc = "Bitmask of performance state flags.\n\nAssociated type: [`PerfStateFlags`] (enum)"]
928    pub fn push_flags(mut self, value: u64) -> Self {
929        push_header(self.as_rec_mut(), 6u16, 8 as u16);
930        self.as_rec_mut().extend(value.to_ne_bytes());
931        self
932    }
933}
934impl<Prev: Rec> Drop for PushPerfState<Prev> {
935    fn drop(&mut self) {
936        if let Some(prev) = &mut self.prev {
937            if let Some(header_offset) = &self.header_offset {
938                finalize_nested_header(prev.as_rec_mut(), *header_offset);
939            }
940        }
941    }
942}
943#[doc = "Notify attributes:\n- [`.get_perf_domain_id()`](IterablePerfTable::get_perf_domain_id)\n- [`.get_perf_state()`](IterablePerfTable::get_perf_state)\n"]
944#[derive(Debug)]
945pub struct OpPerfDomainCreatedNotif;
946impl OpPerfDomainCreatedNotif {
947    pub const CMD: u8 = 3u8;
948    pub fn decode_notif<'a>(buf: &'a [u8]) -> IterablePerfTable<'a> {
949        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
950        IterablePerfTable::with_loc(attrs, buf.as_ptr() as usize)
951    }
952}
953#[doc = "Notify attributes:\n- [`.get_perf_domain_id()`](IterablePerfTable::get_perf_domain_id)\n- [`.get_perf_state()`](IterablePerfTable::get_perf_state)\n"]
954#[derive(Debug)]
955pub struct OpPerfDomainUpdatedNotif;
956impl OpPerfDomainUpdatedNotif {
957    pub const CMD: u8 = 4u8;
958    pub fn decode_notif<'a>(buf: &'a [u8]) -> IterablePerfTable<'a> {
959        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
960        IterablePerfTable::with_loc(attrs, buf.as_ptr() as usize)
961    }
962}
963#[doc = "Notify attributes:\n- [`.get_perf_domain_id()`](IterablePerfTable::get_perf_domain_id)\n"]
964#[derive(Debug)]
965pub struct OpPerfDomainDeletedNotif;
966impl OpPerfDomainDeletedNotif {
967    pub const CMD: u8 = 5u8;
968    pub fn decode_notif<'a>(buf: &'a [u8]) -> IterablePerfTable<'a> {
969        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
970        IterablePerfTable::with_loc(attrs, buf.as_ptr() as usize)
971    }
972}
973pub struct NotifGroup;
974impl NotifGroup {
975    #[doc = "Notifications:\n- [`OpPerfDomainCreatedNotif`]\n- [`OpPerfDomainUpdatedNotif`]\n- [`OpPerfDomainDeletedNotif`]\n"]
976    pub const EVENT: &str = "event";
977    #[doc = "Notifications:\n- [`OpPerfDomainCreatedNotif`]\n- [`OpPerfDomainUpdatedNotif`]\n- [`OpPerfDomainDeletedNotif`]\n"]
978    pub const EVENT_CSTR: &CStr = c"event";
979}
980#[doc = "Get the list of information for all performance domains.\n\nReply attributes:\n- [.get_perf_domain_id()](IterablePerfDomain::get_perf_domain_id)\n- [.get_flags()](IterablePerfDomain::get_flags)\n- [.get_cpus()](IterablePerfDomain::get_cpus)\n\n"]
981#[derive(Debug)]
982pub struct OpGetPerfDomainsDump<'r> {
983    request: Request<'r>,
984}
985impl<'r> OpGetPerfDomainsDump<'r> {
986    pub fn new(mut request: Request<'r>) -> Self {
987        Self::write_header(request.buf_mut());
988        Self {
989            request: request.set_dump(),
990        }
991    }
992    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushPerfDomain<&'buf mut Vec<u8>> {
993        Self::write_header(buf);
994        PushPerfDomain::new(buf)
995    }
996    pub fn encode(&mut self) -> PushPerfDomain<&mut Vec<u8>> {
997        PushPerfDomain::new(self.request.buf_mut())
998    }
999    pub fn into_encoder(self) -> PushPerfDomain<RequestBuf<'r>> {
1000        PushPerfDomain::new(self.request.buf)
1001    }
1002    pub fn decode_request<'a>(buf: &'a [u8]) -> IterablePerfDomain<'a> {
1003        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1004        IterablePerfDomain::with_loc(attrs, buf.as_ptr() as usize)
1005    }
1006    fn write_header<Prev: Rec>(prev: &mut Prev) {
1007        let mut header = BuiltinNfgenmsg::new();
1008        header.cmd = 1u8;
1009        header.version = 1u8;
1010        prev.as_rec_mut().extend(header.as_slice());
1011    }
1012}
1013impl NetlinkRequest for OpGetPerfDomainsDump<'_> {
1014    fn protocol(&self) -> Protocol {
1015        Protocol::Generic("dev-energymodel".as_bytes())
1016    }
1017    fn flags(&self) -> u16 {
1018        self.request.flags
1019    }
1020    fn payload(&self) -> &[u8] {
1021        self.request.buf()
1022    }
1023    type ReplyType<'buf> = IterablePerfDomain<'buf>;
1024    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1025        Self::decode_request(buf)
1026    }
1027    fn lookup(
1028        buf: &[u8],
1029        offset: usize,
1030        missing_type: Option<u16>,
1031    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1032        Self::decode_request(buf).lookup_attr(offset, missing_type)
1033    }
1034}
1035#[doc = "Get the list of information for all performance domains.\n\nRequest attributes:\n- [.push_perf_domain_id()](PushPerfDomain::push_perf_domain_id)\n\nReply attributes:\n- [.get_perf_domain_id()](IterablePerfDomain::get_perf_domain_id)\n- [.get_flags()](IterablePerfDomain::get_flags)\n- [.get_cpus()](IterablePerfDomain::get_cpus)\n\n"]
1036#[derive(Debug)]
1037pub struct OpGetPerfDomainsDo<'r> {
1038    request: Request<'r>,
1039}
1040impl<'r> OpGetPerfDomainsDo<'r> {
1041    pub fn new(mut request: Request<'r>) -> Self {
1042        Self::write_header(request.buf_mut());
1043        Self { request: request }
1044    }
1045    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushPerfDomain<&'buf mut Vec<u8>> {
1046        Self::write_header(buf);
1047        PushPerfDomain::new(buf)
1048    }
1049    pub fn encode(&mut self) -> PushPerfDomain<&mut Vec<u8>> {
1050        PushPerfDomain::new(self.request.buf_mut())
1051    }
1052    pub fn into_encoder(self) -> PushPerfDomain<RequestBuf<'r>> {
1053        PushPerfDomain::new(self.request.buf)
1054    }
1055    pub fn decode_request<'a>(buf: &'a [u8]) -> IterablePerfDomain<'a> {
1056        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1057        IterablePerfDomain::with_loc(attrs, buf.as_ptr() as usize)
1058    }
1059    fn write_header<Prev: Rec>(prev: &mut Prev) {
1060        let mut header = BuiltinNfgenmsg::new();
1061        header.cmd = 1u8;
1062        header.version = 1u8;
1063        prev.as_rec_mut().extend(header.as_slice());
1064    }
1065}
1066impl NetlinkRequest for OpGetPerfDomainsDo<'_> {
1067    fn protocol(&self) -> Protocol {
1068        Protocol::Generic("dev-energymodel".as_bytes())
1069    }
1070    fn flags(&self) -> u16 {
1071        self.request.flags
1072    }
1073    fn payload(&self) -> &[u8] {
1074        self.request.buf()
1075    }
1076    type ReplyType<'buf> = IterablePerfDomain<'buf>;
1077    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1078        Self::decode_request(buf)
1079    }
1080    fn lookup(
1081        buf: &[u8],
1082        offset: usize,
1083        missing_type: Option<u16>,
1084    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1085        Self::decode_request(buf).lookup_attr(offset, missing_type)
1086    }
1087}
1088#[doc = "Get the energy model table of a performance domain.\n\nRequest attributes:\n- [.push_perf_domain_id()](PushPerfTable::push_perf_domain_id)\n\nReply attributes:\n- [.get_perf_domain_id()](IterablePerfTable::get_perf_domain_id)\n- [.get_perf_state()](IterablePerfTable::get_perf_state)\n\n"]
1089#[derive(Debug)]
1090pub struct OpGetPerfTableDo<'r> {
1091    request: Request<'r>,
1092}
1093impl<'r> OpGetPerfTableDo<'r> {
1094    pub fn new(mut request: Request<'r>) -> Self {
1095        Self::write_header(request.buf_mut());
1096        Self { request: request }
1097    }
1098    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushPerfTable<&'buf mut Vec<u8>> {
1099        Self::write_header(buf);
1100        PushPerfTable::new(buf)
1101    }
1102    pub fn encode(&mut self) -> PushPerfTable<&mut Vec<u8>> {
1103        PushPerfTable::new(self.request.buf_mut())
1104    }
1105    pub fn into_encoder(self) -> PushPerfTable<RequestBuf<'r>> {
1106        PushPerfTable::new(self.request.buf)
1107    }
1108    pub fn decode_request<'a>(buf: &'a [u8]) -> IterablePerfTable<'a> {
1109        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1110        IterablePerfTable::with_loc(attrs, buf.as_ptr() as usize)
1111    }
1112    fn write_header<Prev: Rec>(prev: &mut Prev) {
1113        let mut header = BuiltinNfgenmsg::new();
1114        header.cmd = 2u8;
1115        header.version = 1u8;
1116        prev.as_rec_mut().extend(header.as_slice());
1117    }
1118}
1119impl NetlinkRequest for OpGetPerfTableDo<'_> {
1120    fn protocol(&self) -> Protocol {
1121        Protocol::Generic("dev-energymodel".as_bytes())
1122    }
1123    fn flags(&self) -> u16 {
1124        self.request.flags
1125    }
1126    fn payload(&self) -> &[u8] {
1127        self.request.buf()
1128    }
1129    type ReplyType<'buf> = IterablePerfTable<'buf>;
1130    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1131        Self::decode_request(buf)
1132    }
1133    fn lookup(
1134        buf: &[u8],
1135        offset: usize,
1136        missing_type: Option<u16>,
1137    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1138        Self::decode_request(buf).lookup_attr(offset, missing_type)
1139    }
1140}
1141use crate::traits::LookupFn;
1142use crate::utils::RequestBuf;
1143#[derive(Debug)]
1144pub struct Request<'buf> {
1145    buf: RequestBuf<'buf>,
1146    flags: u16,
1147    writeback: Option<&'buf mut Option<RequestInfo>>,
1148}
1149#[allow(unused)]
1150#[derive(Debug, Clone)]
1151pub struct RequestInfo {
1152    protocol: Protocol,
1153    flags: u16,
1154    name: &'static str,
1155    lookup: LookupFn,
1156}
1157impl Request<'static> {
1158    pub fn new() -> Self {
1159        Self::new_from_buf(Vec::new())
1160    }
1161    pub fn new_from_buf(buf: Vec<u8>) -> Self {
1162        Self {
1163            flags: 0,
1164            buf: RequestBuf::Own(buf),
1165            writeback: None,
1166        }
1167    }
1168    pub fn into_buf(self) -> Vec<u8> {
1169        match self.buf {
1170            RequestBuf::Own(buf) => buf,
1171            _ => unreachable!(),
1172        }
1173    }
1174}
1175impl<'buf> Request<'buf> {
1176    pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
1177        buf.clear();
1178        Self::new_extend(buf)
1179    }
1180    pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
1181        Self {
1182            flags: 0,
1183            buf: RequestBuf::Ref(buf),
1184            writeback: None,
1185        }
1186    }
1187    fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
1188        let Some(writeback) = &mut self.writeback else {
1189            return;
1190        };
1191        **writeback = Some(RequestInfo {
1192            protocol,
1193            flags: self.flags,
1194            name,
1195            lookup,
1196        })
1197    }
1198    pub fn buf(&self) -> &Vec<u8> {
1199        self.buf.buf()
1200    }
1201    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
1202        self.buf.buf_mut()
1203    }
1204    #[doc = "Set `NLM_F_CREATE` flag"]
1205    pub fn set_create(mut self) -> Self {
1206        self.flags |= consts::NLM_F_CREATE as u16;
1207        self
1208    }
1209    #[doc = "Set `NLM_F_EXCL` flag"]
1210    pub fn set_excl(mut self) -> Self {
1211        self.flags |= consts::NLM_F_EXCL as u16;
1212        self
1213    }
1214    #[doc = "Set `NLM_F_REPLACE` flag"]
1215    pub fn set_replace(mut self) -> Self {
1216        self.flags |= consts::NLM_F_REPLACE as u16;
1217        self
1218    }
1219    #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
1220    pub fn set_change(self) -> Self {
1221        self.set_create().set_replace()
1222    }
1223    #[doc = "Set `NLM_F_APPEND` flag"]
1224    pub fn set_append(mut self) -> Self {
1225        self.flags |= consts::NLM_F_APPEND as u16;
1226        self
1227    }
1228    #[doc = "Set `self.flags |= flags`"]
1229    pub fn set_flags(mut self, flags: u16) -> Self {
1230        self.flags |= flags;
1231        self
1232    }
1233    #[doc = "Set `self.flags ^= self.flags & flags`"]
1234    pub fn unset_flags(mut self, flags: u16) -> Self {
1235        self.flags ^= self.flags & flags;
1236        self
1237    }
1238    #[doc = "Set `NLM_F_DUMP` flag"]
1239    fn set_dump(mut self) -> Self {
1240        self.flags |= consts::NLM_F_DUMP as u16;
1241        self
1242    }
1243    #[doc = "Get the list of information for all performance domains.\n\nReply attributes:\n- [.get_perf_domain_id()](IterablePerfDomain::get_perf_domain_id)\n- [.get_flags()](IterablePerfDomain::get_flags)\n- [.get_cpus()](IterablePerfDomain::get_cpus)\n\n"]
1244    pub fn op_get_perf_domains_dump(self) -> OpGetPerfDomainsDump<'buf> {
1245        let mut res = OpGetPerfDomainsDump::new(self);
1246        res.request.do_writeback(
1247            res.protocol(),
1248            "op-get-perf-domains-dump",
1249            OpGetPerfDomainsDump::lookup,
1250        );
1251        res
1252    }
1253    #[doc = "Get the list of information for all performance domains.\n\nRequest attributes:\n- [.push_perf_domain_id()](PushPerfDomain::push_perf_domain_id)\n\nReply attributes:\n- [.get_perf_domain_id()](IterablePerfDomain::get_perf_domain_id)\n- [.get_flags()](IterablePerfDomain::get_flags)\n- [.get_cpus()](IterablePerfDomain::get_cpus)\n\n"]
1254    pub fn op_get_perf_domains_do(self) -> OpGetPerfDomainsDo<'buf> {
1255        let mut res = OpGetPerfDomainsDo::new(self);
1256        res.request.do_writeback(
1257            res.protocol(),
1258            "op-get-perf-domains-do",
1259            OpGetPerfDomainsDo::lookup,
1260        );
1261        res
1262    }
1263    #[doc = "Get the energy model table of a performance domain.\n\nRequest attributes:\n- [.push_perf_domain_id()](PushPerfTable::push_perf_domain_id)\n\nReply attributes:\n- [.get_perf_domain_id()](IterablePerfTable::get_perf_domain_id)\n- [.get_perf_state()](IterablePerfTable::get_perf_state)\n\n"]
1264    pub fn op_get_perf_table_do(self) -> OpGetPerfTableDo<'buf> {
1265        let mut res = OpGetPerfTableDo::new(self);
1266        res.request.do_writeback(
1267            res.protocol(),
1268            "op-get-perf-table-do",
1269            OpGetPerfTableDo::lookup,
1270        );
1271        res
1272    }
1273}
1274#[cfg(test)]
1275mod generated_tests {
1276    use super::*;
1277    #[test]
1278    fn tests() {
1279        let _ = IterablePerfDomain::get_cpus;
1280        let _ = IterablePerfDomain::get_flags;
1281        let _ = IterablePerfDomain::get_perf_domain_id;
1282        let _ = IterablePerfTable::get_perf_domain_id;
1283        let _ = IterablePerfTable::get_perf_state;
1284        let _ = OpPerfDomainCreatedNotif;
1285        let _ = OpPerfDomainDeletedNotif;
1286        let _ = OpPerfDomainUpdatedNotif;
1287        let _ = PushPerfDomain::<&mut Vec<u8>>::push_perf_domain_id;
1288        let _ = PushPerfTable::<&mut Vec<u8>>::push_perf_domain_id;
1289    }
1290}