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