Skip to main content

cm_rust/
config.rs

1// Copyright 2026 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use cm_rust_derive::FidlDecl;
6use fidl_fuchsia_component_decl as fdecl;
7use from_enum::FromEnum;
8use std::fmt;
9use std::hash::Hash;
10
11use crate::{FidlIntoNative, NativeIntoFidl};
12
13#[cfg(feature = "serde")]
14use serde::{Deserialize, Serialize};
15
16#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
17#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
18#[fidl_decl(fidl_table = "fdecl::ConfigValuesData")]
19pub struct ConfigValuesData {
20    pub values: Box<[ConfigValueSpec]>,
21    pub checksum: ConfigChecksum,
22}
23
24#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
25#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
26#[fidl_decl(fidl_table = "fdecl::ConfigValueSpec")]
27pub struct ConfigValueSpec {
28    pub value: ConfigValue,
29}
30
31#[derive(FromEnum, FidlDecl, Debug, Clone, PartialEq, Eq)]
32#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
33#[fidl_decl(fidl_union = "fdecl::ConfigValue")]
34pub enum ConfigValue {
35    Single(ConfigSingleValue),
36    Vector(ConfigVectorValue),
37}
38
39impl ConfigValue {
40    /// Return the type of this value.
41    pub fn ty(&self) -> ConfigValueType {
42        match self {
43            Self::Single(sv) => sv.ty(),
44            Self::Vector(vv) => vv.ty(),
45        }
46    }
47
48    /// Check if this value matches the type of another value.
49    pub fn matches_type(&self, other: &ConfigValue) -> bool {
50        match (self, other) {
51            (ConfigValue::Single(a), ConfigValue::Single(b)) => {
52                std::mem::discriminant(a) == std::mem::discriminant(b)
53            }
54            (ConfigValue::Vector(a), ConfigValue::Vector(b)) => {
55                std::mem::discriminant(a) == std::mem::discriminant(b)
56            }
57            _ => false,
58        }
59    }
60}
61
62impl From<&str> for ConfigValue {
63    fn from(value: &str) -> Self {
64        ConfigValue::Single(value.to_string().into())
65    }
66}
67
68impl From<Vec<&str>> for ConfigValue {
69    fn from(value: Vec<&str>) -> Self {
70        let value: Box<[_]> = value.into_iter().map(|s| s.to_string()).collect();
71        ConfigValue::Vector(value.into())
72    }
73}
74
75#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
76#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
77#[fidl_decl(fidl_table = "fdecl::ConfigOverride")]
78pub struct ConfigOverride {
79    pub key: String,
80    pub value: ConfigValue,
81}
82
83#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
84#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
85#[fidl_decl(fidl_table = "fdecl::ConfigSchema")]
86pub struct ConfigDecl {
87    pub fields: Box<[ConfigField]>,
88    pub checksum: ConfigChecksum,
89    pub value_source: ConfigValueSource,
90}
91
92#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
93#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
94#[fidl_decl(fidl_union = "fdecl::ConfigChecksum")]
95pub enum ConfigChecksum {
96    Sha256([u8; 32]),
97}
98
99#[cfg(fuchsia_api_level_at_least = "HEAD")]
100#[derive(FidlDecl, Debug, Default, Clone, PartialEq, Eq)]
101#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
102#[fidl_decl(fidl_table = "fdecl::ConfigSourceCapabilities")]
103pub struct ConfigSourceCapabilities {}
104
105#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
106#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
107#[fidl_decl(fidl_union = "fdecl::ConfigValueSource")]
108pub enum ConfigValueSource {
109    PackagePath(String),
110    #[cfg(fuchsia_api_level_at_least = "HEAD")]
111    Capabilities(ConfigSourceCapabilities),
112}
113
114#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
115#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
116#[fidl_decl(fidl_table = "fdecl::ConfigField")]
117pub struct ConfigField {
118    pub key: String,
119    pub type_: ConfigValueType,
120
121    // This field will not be present in compiled manifests which predate F12.
122    #[fidl_decl(default)]
123    pub mutability: ConfigMutability,
124}
125
126#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
127#[derive(Debug, Clone, PartialEq, Eq)]
128pub enum ConfigNestedValueType {
129    Bool,
130    Uint8,
131    Int8,
132    Uint16,
133    Int16,
134    Uint32,
135    Int32,
136    Uint64,
137    Int64,
138    String { max_size: u32 },
139}
140
141#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
142#[derive(Debug, Clone, PartialEq, Eq)]
143pub enum ConfigValueType {
144    Bool,
145    Uint8,
146    Int8,
147    Uint16,
148    Int16,
149    Uint32,
150    Int32,
151    Uint64,
152    Int64,
153    String { max_size: u32 },
154    Vector { nested_type: ConfigNestedValueType, max_count: u32 },
155}
156
157impl ConfigValueType {
158    pub fn get_max_size(&self) -> Option<u32> {
159        match self {
160            ConfigValueType::String { max_size } => Some(*max_size),
161            ConfigValueType::Bool
162            | ConfigValueType::Uint8
163            | ConfigValueType::Int8
164            | ConfigValueType::Uint16
165            | ConfigValueType::Int16
166            | ConfigValueType::Uint32
167            | ConfigValueType::Int32
168            | ConfigValueType::Uint64
169            | ConfigValueType::Int64
170            | ConfigValueType::Vector { .. } => None,
171        }
172    }
173
174    pub fn get_nested_type(&self) -> Option<ConfigNestedValueType> {
175        match self {
176            ConfigValueType::Vector { nested_type, .. } => Some(nested_type.clone()),
177            ConfigValueType::Bool
178            | ConfigValueType::Uint8
179            | ConfigValueType::Int8
180            | ConfigValueType::Uint16
181            | ConfigValueType::Int16
182            | ConfigValueType::Uint32
183            | ConfigValueType::Int32
184            | ConfigValueType::Uint64
185            | ConfigValueType::Int64
186            | ConfigValueType::String { .. } => None,
187        }
188    }
189
190    pub fn get_max_count(&self) -> Option<u32> {
191        match self {
192            ConfigValueType::Vector { max_count, .. } => Some(*max_count),
193            ConfigValueType::Bool
194            | ConfigValueType::Uint8
195            | ConfigValueType::Int8
196            | ConfigValueType::Uint16
197            | ConfigValueType::Int16
198            | ConfigValueType::Uint32
199            | ConfigValueType::Int32
200            | ConfigValueType::Uint64
201            | ConfigValueType::Int64
202            | ConfigValueType::String { .. } => None,
203        }
204    }
205}
206
207macro_rules! generate_configvalue_from {
208    ($name:expr, $type:ty) => {
209        impl From<$type> for ConfigValue {
210            fn from(value: $type) -> Self {
211                $name(value.into())
212            }
213        }
214    };
215}
216
217generate_configvalue_from!(ConfigValue::Single, bool);
218generate_configvalue_from!(ConfigValue::Single, u8);
219generate_configvalue_from!(ConfigValue::Single, u16);
220generate_configvalue_from!(ConfigValue::Single, u32);
221generate_configvalue_from!(ConfigValue::Single, u64);
222generate_configvalue_from!(ConfigValue::Single, i8);
223generate_configvalue_from!(ConfigValue::Single, i16);
224generate_configvalue_from!(ConfigValue::Single, i32);
225generate_configvalue_from!(ConfigValue::Single, i64);
226generate_configvalue_from!(ConfigValue::Single, String);
227generate_configvalue_from!(ConfigValue::Vector, Box<[bool]>);
228generate_configvalue_from!(ConfigValue::Vector, Box<[u8]>);
229generate_configvalue_from!(ConfigValue::Vector, Box<[u16]>);
230generate_configvalue_from!(ConfigValue::Vector, Box<[u32]>);
231generate_configvalue_from!(ConfigValue::Vector, Box<[u64]>);
232generate_configvalue_from!(ConfigValue::Vector, Box<[i8]>);
233generate_configvalue_from!(ConfigValue::Vector, Box<[i16]>);
234generate_configvalue_from!(ConfigValue::Vector, Box<[i32]>);
235generate_configvalue_from!(ConfigValue::Vector, Box<[i64]>);
236generate_configvalue_from!(ConfigValue::Vector, Box<[String]>);
237generate_configvalue_from!(ConfigValue::Vector, Vec<bool>);
238generate_configvalue_from!(ConfigValue::Vector, Vec<u8>);
239generate_configvalue_from!(ConfigValue::Vector, Vec<u16>);
240generate_configvalue_from!(ConfigValue::Vector, Vec<u32>);
241generate_configvalue_from!(ConfigValue::Vector, Vec<u64>);
242generate_configvalue_from!(ConfigValue::Vector, Vec<i8>);
243generate_configvalue_from!(ConfigValue::Vector, Vec<i16>);
244generate_configvalue_from!(ConfigValue::Vector, Vec<i32>);
245generate_configvalue_from!(ConfigValue::Vector, Vec<i64>);
246generate_configvalue_from!(ConfigValue::Vector, Vec<String>);
247
248impl fmt::Display for ConfigValue {
249    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
250        match self {
251            ConfigValue::Single(sv) => sv.fmt(f),
252            ConfigValue::Vector(lv) => lv.fmt(f),
253        }
254    }
255}
256
257#[derive(FromEnum, FidlDecl, Debug, Clone, PartialEq, Eq)]
258#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
259#[fidl_decl(fidl_union = "fdecl::ConfigSingleValue")]
260pub enum ConfigSingleValue {
261    Bool(bool),
262    Uint8(u8),
263    Uint16(u16),
264    Uint32(u32),
265    Uint64(u64),
266    Int8(i8),
267    Int16(i16),
268    Int32(i32),
269    Int64(i64),
270    String(String),
271}
272
273impl ConfigSingleValue {
274    fn ty(&self) -> ConfigValueType {
275        match self {
276            ConfigSingleValue::Bool(_) => ConfigValueType::Bool,
277            ConfigSingleValue::Uint8(_) => ConfigValueType::Uint8,
278            ConfigSingleValue::Uint16(_) => ConfigValueType::Uint16,
279            ConfigSingleValue::Uint32(_) => ConfigValueType::Uint32,
280            ConfigSingleValue::Uint64(_) => ConfigValueType::Uint64,
281            ConfigSingleValue::Int8(_) => ConfigValueType::Int8,
282            ConfigSingleValue::Int16(_) => ConfigValueType::Int16,
283            ConfigSingleValue::Int32(_) => ConfigValueType::Int32,
284            ConfigSingleValue::Int64(_) => ConfigValueType::Int64,
285            // We substitute the max size limit because the value itself doesn't carry the info.
286            ConfigSingleValue::String(_) => ConfigValueType::String { max_size: std::u32::MAX },
287        }
288    }
289}
290
291impl fmt::Display for ConfigSingleValue {
292    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
293        use ConfigSingleValue::*;
294        match self {
295            Bool(v) => write!(f, "{}", v),
296            Uint8(v) => write!(f, "{}", v),
297            Uint16(v) => write!(f, "{}", v),
298            Uint32(v) => write!(f, "{}", v),
299            Uint64(v) => write!(f, "{}", v),
300            Int8(v) => write!(f, "{}", v),
301            Int16(v) => write!(f, "{}", v),
302            Int32(v) => write!(f, "{}", v),
303            Int64(v) => write!(f, "{}", v),
304            String(v) => write!(f, "\"{}\"", v),
305        }
306    }
307}
308
309#[derive(FromEnum, FidlDecl, Debug, Clone, PartialEq, Eq)]
310#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
311#[fidl_decl(fidl_union = "fdecl::ConfigVectorValue")]
312pub enum ConfigVectorValue {
313    BoolVector(Box<[bool]>),
314    Uint8Vector(Box<[u8]>),
315    Uint16Vector(Box<[u16]>),
316    Uint32Vector(Box<[u32]>),
317    Uint64Vector(Box<[u64]>),
318    Int8Vector(Box<[i8]>),
319    Int16Vector(Box<[i16]>),
320    Int32Vector(Box<[i32]>),
321    Int64Vector(Box<[i64]>),
322    StringVector(Box<[String]>),
323}
324
325impl From<Vec<bool>> for ConfigVectorValue {
326    fn from(v: Vec<bool>) -> Self {
327        Self::BoolVector(v.into())
328    }
329}
330
331impl From<Vec<u8>> for ConfigVectorValue {
332    fn from(v: Vec<u8>) -> Self {
333        Self::Uint8Vector(v.into())
334    }
335}
336
337impl From<Vec<u16>> for ConfigVectorValue {
338    fn from(v: Vec<u16>) -> Self {
339        Self::Uint16Vector(v.into())
340    }
341}
342
343impl From<Vec<u32>> for ConfigVectorValue {
344    fn from(v: Vec<u32>) -> Self {
345        Self::Uint32Vector(v.into())
346    }
347}
348
349impl From<Vec<u64>> for ConfigVectorValue {
350    fn from(v: Vec<u64>) -> Self {
351        Self::Uint64Vector(v.into())
352    }
353}
354
355impl From<Vec<i8>> for ConfigVectorValue {
356    fn from(v: Vec<i8>) -> Self {
357        Self::Int8Vector(v.into())
358    }
359}
360
361impl From<Vec<i16>> for ConfigVectorValue {
362    fn from(v: Vec<i16>) -> Self {
363        Self::Int16Vector(v.into())
364    }
365}
366
367impl From<Vec<i32>> for ConfigVectorValue {
368    fn from(v: Vec<i32>) -> Self {
369        Self::Int32Vector(v.into())
370    }
371}
372
373impl From<Vec<i64>> for ConfigVectorValue {
374    fn from(v: Vec<i64>) -> Self {
375        Self::Int64Vector(v.into())
376    }
377}
378
379impl From<Vec<String>> for ConfigVectorValue {
380    fn from(v: Vec<String>) -> Self {
381        Self::StringVector(v.into())
382    }
383}
384
385impl ConfigVectorValue {
386    fn ty(&self) -> ConfigValueType {
387        // We substitute the max size limit because the value itself doesn't carry the info.
388        match self {
389            ConfigVectorValue::BoolVector(_) => ConfigValueType::Vector {
390                nested_type: ConfigNestedValueType::Bool,
391                max_count: std::u32::MAX,
392            },
393            ConfigVectorValue::Uint8Vector(_) => ConfigValueType::Vector {
394                nested_type: ConfigNestedValueType::Uint8,
395                max_count: std::u32::MAX,
396            },
397            ConfigVectorValue::Uint16Vector(_) => ConfigValueType::Vector {
398                nested_type: ConfigNestedValueType::Uint16,
399                max_count: std::u32::MAX,
400            },
401            ConfigVectorValue::Uint32Vector(_) => ConfigValueType::Vector {
402                nested_type: ConfigNestedValueType::Uint32,
403                max_count: std::u32::MAX,
404            },
405            ConfigVectorValue::Uint64Vector(_) => ConfigValueType::Vector {
406                nested_type: ConfigNestedValueType::Uint64,
407                max_count: std::u32::MAX,
408            },
409            ConfigVectorValue::Int8Vector(_) => ConfigValueType::Vector {
410                nested_type: ConfigNestedValueType::Int8,
411                max_count: std::u32::MAX,
412            },
413            ConfigVectorValue::Int16Vector(_) => ConfigValueType::Vector {
414                nested_type: ConfigNestedValueType::Int16,
415                max_count: std::u32::MAX,
416            },
417            ConfigVectorValue::Int32Vector(_) => ConfigValueType::Vector {
418                nested_type: ConfigNestedValueType::Int32,
419                max_count: std::u32::MAX,
420            },
421            ConfigVectorValue::Int64Vector(_) => ConfigValueType::Vector {
422                nested_type: ConfigNestedValueType::Int64,
423                max_count: std::u32::MAX,
424            },
425            ConfigVectorValue::StringVector(_) => ConfigValueType::Vector {
426                nested_type: ConfigNestedValueType::String { max_size: std::u32::MAX },
427                max_count: std::u32::MAX,
428            },
429        }
430    }
431}
432
433bitflags::bitflags! {
434    #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
435    // TODO(https://fxbug.dev/42075220) uncomment once bitflags is updated
436    // pub struct ConfigMutability: <fdecl::ConfigMutability as bitflags::BitFlags>::Bits {
437    pub struct ConfigMutability: u32 {
438        const PARENT = fdecl::ConfigMutability::PARENT.bits();
439    }
440}
441
442#[cfg(feature = "serde")]
443bitflags_serde_legacy::impl_traits!(ConfigMutability);
444
445impl NativeIntoFidl<fdecl::ConfigMutability> for ConfigMutability {
446    fn native_into_fidl(self) -> fdecl::ConfigMutability {
447        fdecl::ConfigMutability::from_bits_allow_unknown(self.bits())
448    }
449}
450
451impl FidlIntoNative<ConfigMutability> for fdecl::ConfigMutability {
452    fn fidl_into_native(self) -> ConfigMutability {
453        ConfigMutability::from_bits_retain(self.bits())
454    }
455}
456
457impl fmt::Display for ConfigVectorValue {
458    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
459        use ConfigVectorValue::*;
460        macro_rules! print_list {
461            ($f:ident, $list:ident) => {{
462                $f.write_str("[")?;
463
464                for (i, item) in $list.iter().enumerate() {
465                    if i > 0 {
466                        $f.write_str(", ")?;
467                    }
468                    write!($f, "{}", item)?;
469                }
470
471                $f.write_str("]")
472            }};
473        }
474        match self {
475            BoolVector(l) => print_list!(f, l),
476            Uint8Vector(l) => print_list!(f, l),
477            Uint16Vector(l) => print_list!(f, l),
478            Uint32Vector(l) => print_list!(f, l),
479            Uint64Vector(l) => print_list!(f, l),
480            Int8Vector(l) => print_list!(f, l),
481            Int16Vector(l) => print_list!(f, l),
482            Int32Vector(l) => print_list!(f, l),
483            Int64Vector(l) => print_list!(f, l),
484            StringVector(l) => {
485                f.write_str("[")?;
486                for (i, item) in l.iter().enumerate() {
487                    if i > 0 {
488                        f.write_str(", ")?;
489                    }
490                    write!(f, "\"{}\"", item)?;
491                }
492                f.write_str("]")
493            }
494        }
495    }
496}
497
498impl FidlIntoNative<ConfigNestedValueType> for fdecl::ConfigType {
499    fn fidl_into_native(mut self) -> ConfigNestedValueType {
500        match self.layout {
501            fdecl::ConfigTypeLayout::Bool => ConfigNestedValueType::Bool,
502            fdecl::ConfigTypeLayout::Uint8 => ConfigNestedValueType::Uint8,
503            fdecl::ConfigTypeLayout::Uint16 => ConfigNestedValueType::Uint16,
504            fdecl::ConfigTypeLayout::Uint32 => ConfigNestedValueType::Uint32,
505            fdecl::ConfigTypeLayout::Uint64 => ConfigNestedValueType::Uint64,
506            fdecl::ConfigTypeLayout::Int8 => ConfigNestedValueType::Int8,
507            fdecl::ConfigTypeLayout::Int16 => ConfigNestedValueType::Int16,
508            fdecl::ConfigTypeLayout::Int32 => ConfigNestedValueType::Int32,
509            fdecl::ConfigTypeLayout::Int64 => ConfigNestedValueType::Int64,
510            fdecl::ConfigTypeLayout::String => {
511                let max_size =
512                    if let fdecl::LayoutConstraint::MaxSize(s) = self.constraints.remove(0) {
513                        s
514                    } else {
515                        panic!("Unexpected constraint on String layout type for config field");
516                    };
517                ConfigNestedValueType::String { max_size }
518            }
519            fdecl::ConfigTypeLayout::Vector => {
520                panic!("Nested vectors are not supported in structured config")
521            }
522            fdecl::ConfigTypeLayoutUnknown!() => panic!("Unknown layout type for config field"),
523        }
524    }
525}
526
527impl NativeIntoFidl<fdecl::ConfigType> for ConfigNestedValueType {
528    fn native_into_fidl(self) -> fdecl::ConfigType {
529        let layout = match self {
530            ConfigNestedValueType::Bool => fdecl::ConfigTypeLayout::Bool,
531            ConfigNestedValueType::Uint8 => fdecl::ConfigTypeLayout::Uint8,
532            ConfigNestedValueType::Uint16 => fdecl::ConfigTypeLayout::Uint16,
533            ConfigNestedValueType::Uint32 => fdecl::ConfigTypeLayout::Uint32,
534            ConfigNestedValueType::Uint64 => fdecl::ConfigTypeLayout::Uint64,
535            ConfigNestedValueType::Int8 => fdecl::ConfigTypeLayout::Int8,
536            ConfigNestedValueType::Int16 => fdecl::ConfigTypeLayout::Int16,
537            ConfigNestedValueType::Int32 => fdecl::ConfigTypeLayout::Int32,
538            ConfigNestedValueType::Int64 => fdecl::ConfigTypeLayout::Int64,
539            ConfigNestedValueType::String { .. } => fdecl::ConfigTypeLayout::String,
540        };
541        let constraints = match self {
542            ConfigNestedValueType::String { max_size } => {
543                vec![fdecl::LayoutConstraint::MaxSize(max_size)]
544            }
545            _ => vec![],
546        };
547        fdecl::ConfigType { layout, constraints, parameters: Some(vec![]) }
548    }
549}
550
551impl FidlIntoNative<ConfigValueType> for fdecl::ConfigType {
552    fn fidl_into_native(mut self) -> ConfigValueType {
553        match self.layout {
554            fdecl::ConfigTypeLayout::Bool => ConfigValueType::Bool,
555            fdecl::ConfigTypeLayout::Uint8 => ConfigValueType::Uint8,
556            fdecl::ConfigTypeLayout::Uint16 => ConfigValueType::Uint16,
557            fdecl::ConfigTypeLayout::Uint32 => ConfigValueType::Uint32,
558            fdecl::ConfigTypeLayout::Uint64 => ConfigValueType::Uint64,
559            fdecl::ConfigTypeLayout::Int8 => ConfigValueType::Int8,
560            fdecl::ConfigTypeLayout::Int16 => ConfigValueType::Int16,
561            fdecl::ConfigTypeLayout::Int32 => ConfigValueType::Int32,
562            fdecl::ConfigTypeLayout::Int64 => ConfigValueType::Int64,
563            fdecl::ConfigTypeLayout::String => {
564                let max_size = if let fdecl::LayoutConstraint::MaxSize(s) =
565                    self.constraints.remove(0)
566                {
567                    s
568                } else {
569                    panic!(
570                        "Unexpected constraint on String layout type for config field. Expected MaxSize."
571                    );
572                };
573                ConfigValueType::String { max_size }
574            }
575            fdecl::ConfigTypeLayout::Vector => {
576                let max_count = if let fdecl::LayoutConstraint::MaxSize(c) =
577                    self.constraints.remove(0)
578                {
579                    c
580                } else {
581                    panic!(
582                        "Unexpected constraint on Vector layout type for config field. Expected MaxSize."
583                    );
584                };
585                let mut parameters =
586                    self.parameters.expect("Config field must have parameters set");
587                let nested_type = if let fdecl::LayoutParameter::NestedType(nested_type) =
588                    parameters.remove(0)
589                {
590                    nested_type.fidl_into_native()
591                } else {
592                    panic!(
593                        "Unexpected parameter on Vector layout type for config field. Expected NestedType."
594                    );
595                };
596                ConfigValueType::Vector { max_count, nested_type }
597            }
598            fdecl::ConfigTypeLayoutUnknown!() => panic!("Unknown layout type for config field"),
599        }
600    }
601}
602
603impl NativeIntoFidl<fdecl::ConfigType> for ConfigValueType {
604    fn native_into_fidl(self) -> fdecl::ConfigType {
605        let layout = match self {
606            ConfigValueType::Bool => fdecl::ConfigTypeLayout::Bool,
607            ConfigValueType::Uint8 => fdecl::ConfigTypeLayout::Uint8,
608            ConfigValueType::Uint16 => fdecl::ConfigTypeLayout::Uint16,
609            ConfigValueType::Uint32 => fdecl::ConfigTypeLayout::Uint32,
610            ConfigValueType::Uint64 => fdecl::ConfigTypeLayout::Uint64,
611            ConfigValueType::Int8 => fdecl::ConfigTypeLayout::Int8,
612            ConfigValueType::Int16 => fdecl::ConfigTypeLayout::Int16,
613            ConfigValueType::Int32 => fdecl::ConfigTypeLayout::Int32,
614            ConfigValueType::Int64 => fdecl::ConfigTypeLayout::Int64,
615            ConfigValueType::String { .. } => fdecl::ConfigTypeLayout::String,
616            ConfigValueType::Vector { .. } => fdecl::ConfigTypeLayout::Vector,
617        };
618        let (constraints, parameters) = match self {
619            ConfigValueType::String { max_size } => {
620                (vec![fdecl::LayoutConstraint::MaxSize(max_size)], vec![])
621            }
622            ConfigValueType::Vector { max_count, nested_type } => {
623                let nested_type = nested_type.native_into_fidl();
624                (
625                    vec![fdecl::LayoutConstraint::MaxSize(max_count)],
626                    vec![fdecl::LayoutParameter::NestedType(nested_type)],
627                )
628            }
629            _ => (vec![], vec![]),
630        };
631        fdecl::ConfigType { layout, constraints, parameters: Some(parameters) }
632    }
633}