blob: 57d45a70f0e0c125de369e9920017ac86bb9bb9c [file] [log] [blame]
// Copyright 2021 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 {
protocols::FidlProtocol,
fidl::endpoints::DiscoverableProtocolMarker,
proc_macro::TokenStream,
quote::quote,
std::collections::hash_map::Entry,
protocols_dependencies::{DependencyGraph, Node, VerifyError},
};
#[proc_macro]
pub fn generate_protocol_map(_item: TokenStream) -> TokenStream {
let mut graph = DependencyGraph::default();
{% for dep in deps %}
let {{ dep.lib }}_node = Node::new(
// Protocol name.
<<{{ dep.lib }}::ProtocolType as FidlProtocol>::Protocol as DiscoverableProtocolMarker>::PROTOCOL_NAME,
// Build target.
"{{ dep.target }}".to_owned(),
// Deps.
{{ dep.lib }}::PROTOCOL_DEPS,
);
match graph.nodes.entry({{ dep.lib }}_node.protocol) {
Entry::Occupied(e) => {
panic!("Protocol endpoint for {} already registered with library at {}", {{ dep.lib }}_node.protocol, e.get().build_target);
}
Entry::Vacant(i) => {
i.insert({{ dep.lib }}_node)
}
};
{% endfor %}
if let Err(e) = graph.verify() {
match e {
VerifyError::CycleFound(path) => {
let errors_string = path
.into_iter()
.map(|n| format!("\n\t{}, implemented in {}", n.protocol, n.build_target))
.collect::<Vec<_>>()
.join("");
panic!("Dependency cycle detected between the following protocols: {}", errors_string);
}
VerifyError::InvalidDependencyError(m) => panic!("{}", m),
}
}
let res = quote! {
{
use fidl::endpoints::DiscoverableProtocolMarker;
use protocols::{FidlStreamHandler, FidlProtocol};
use protocols::NameToStreamHandlerMap;
let mut map = NameToStreamHandlerMap::new();
{% for dep in deps %}
map.insert(
<<{{ dep.lib }}::ProtocolType as FidlProtocol>::Protocol as DiscoverableProtocolMarker>::PROTOCOL_NAME.to_owned(),
Box::new(<{{dep.lib }}::ProtocolType as FidlProtocol>::StreamHandler::default()),
);
{% endfor %}
map
}
};
TokenStream::from(res)
}