blob: 4ec9ba6854d449ae4e9962af5f5fca47c444791e [file] [log] [blame]
// Copyright 2019 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 anyhow::{format_err, Error};
use fidl::endpoints::{DiscoverableService, Proxy, ServiceMarker};
use futures::future::BoxFuture;
use fuchsia_async as fasync;
use fuchsia_component::client::connect_to_service;
use fuchsia_zircon as zx;
use futures::lock::Mutex;
use std::sync::Arc;
pub type GenerateService =
Box<dyn Fn(&str, zx::Channel) -> BoxFuture<'static, Result<(), Error>> + Send + Sync>;
pub type ServiceContextHandle = Arc<Mutex<ServiceContext>>;
/// A wrapper around service operations, allowing redirection to a nested
/// environment.
pub struct ServiceContext {
generate_service: Option<GenerateService>,
}
impl ServiceContext {
pub fn create(generate_service: Option<GenerateService>) -> ServiceContextHandle {
return Arc::new(Mutex::new(ServiceContext::new(generate_service)));
}
pub fn new(generate_service: Option<GenerateService>) -> Self {
Self { generate_service: generate_service }
}
pub async fn connect<S: DiscoverableService>(&self) -> Result<S::Proxy, Error> {
if let Some(generate_service) = &self.generate_service {
let (client, server) = zx::Channel::create()?;
((generate_service)(S::SERVICE_NAME, server)).await?;
return Ok(S::Proxy::from_channel(fasync::Channel::from_channel(client)?));
} else {
return connect_to_service::<S>();
}
}
pub async fn connect_named<S: ServiceMarker>(
&self,
service_name: &str,
) -> Result<S::Proxy, Error> {
if let Some(generate_service) = &self.generate_service {
let (client, server) = zx::Channel::create()?;
if (generate_service)(service_name, server).await.is_err() {
return Err(format_err!("Could not handl service {:?}", service_name));
}
Ok(S::Proxy::from_channel(fasync::Channel::from_channel(client)?))
} else {
Err(format_err!("No service generator"))
}
}
}