blob: 76031ff9df8e03a07a2e437b65bc2595fc8e226c [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use crate::normalize_field_key;
use cm_rust::{ConfigDecl, ConfigField, ConfigNestedValueType, ConfigValueType};
use handlebars::Handlebars;
use serde::Serialize;
/// Create a custom FIDL library source file containing all the fields of a config declaration
pub fn create_fidl_source(config_decl: &ConfigDecl, library_name: String) -> String {
let fidl_library = FidlLibrary::new(config_decl, library_name);
let mut hbars = Handlebars::new();
hbars.set_strict_mode(true);
hbars.register_escape_fn(handlebars::no_escape);
hbars
.register_template_string("fidl_library", FIDL_CLIENT_TEMPLATE)
.expect("known good template should parse");
hbars.render("fidl_library", &fidl_library).unwrap()
}
// TODO(http://fxbug.dev/90690): The type identifier for the configuration fields struct
// should be user-definable
static FIDL_CLIENT_TEMPLATE: &str = "
library {{library_name}};
type Config = struct {
{{#each struct_fields}}
{{key}} {{type_}};
{{/each}}
};
";
#[derive(Debug, Serialize)]
struct FidlLibrary {
library_name: String,
struct_fields: Vec<FidlStructField>,
}
impl FidlLibrary {
fn new(config_decl: &ConfigDecl, library_name: String) -> Self {
FidlLibrary {
library_name,
struct_fields: config_decl.fields.iter().map(FidlStructField::from_decl).collect(),
}
}
}
#[derive(Debug, Serialize)]
struct FidlStructField {
key: String,
type_: String,
}
impl FidlStructField {
fn from_decl(field: &ConfigField) -> Self {
FidlStructField {
key: normalize_field_key(&field.key),
type_: config_value_type_to_fidl_type(&field.type_),
}
}
}
fn config_value_type_to_fidl_type(value_type: &ConfigValueType) -> String {
match value_type {
ConfigValueType::Bool => "bool".to_string(),
ConfigValueType::Uint8 => "uint8".to_string(),
ConfigValueType::Uint16 => "uint16".to_string(),
ConfigValueType::Uint32 => "uint32".to_string(),
ConfigValueType::Uint64 => "uint64".to_string(),
ConfigValueType::Int8 => "int8".to_string(),
ConfigValueType::Int16 => "int16".to_string(),
ConfigValueType::Int32 => "int32".to_string(),
ConfigValueType::Int64 => "int64".to_string(),
ConfigValueType::String { max_size } => format!("string:{}", max_size),
ConfigValueType::Vector { max_count, nested_type } => {
format!("vector<{}>:{}", config_nested_value_type_to_fidl_type(nested_type), max_count)
}
}
}
fn config_nested_value_type_to_fidl_type(nested_type: &ConfigNestedValueType) -> String {
match nested_type {
ConfigNestedValueType::Bool => "bool".to_string(),
ConfigNestedValueType::Uint8 => "uint8".to_string(),
ConfigNestedValueType::Uint16 => "uint16".to_string(),
ConfigNestedValueType::Uint32 => "uint32".to_string(),
ConfigNestedValueType::Uint64 => "uint64".to_string(),
ConfigNestedValueType::Int8 => "int8".to_string(),
ConfigNestedValueType::Int16 => "int16".to_string(),
ConfigNestedValueType::Int32 => "int32".to_string(),
ConfigNestedValueType::Int64 => "int64".to_string(),
ConfigNestedValueType::String { max_size } => {
format!("string:{}", max_size)
}
}
}