Skip to main content

settings_test_common/fakes/
service.rs

1// Copyright 2024 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 anyhow::{format_err, Error};
6
7use futures::future::LocalBoxFuture;
8use futures::lock::Mutex;
9use settings_common::service_context::GenerateService;
10use std::rc::Rc;
11
12/// Trait for providing a service.
13pub trait Service {
14    /// Returns true if this service can process the given service name, false
15    /// otherwise.
16    fn can_handle_service(&self, service_name: &str) -> bool;
17
18    /// Processes the request stream within the specified channel. Ok is returned
19    /// on success, an error otherwise.
20    fn process_stream(&mut self, service_name: &str, channel: zx::Channel) -> Result<(), Error>;
21}
22
23pub type ServiceRegistryHandle = Rc<Mutex<ServiceRegistry>>;
24
25/// A helper class that gathers services through registration and directs
26/// the appropriate channels to them.
27pub struct ServiceRegistry {
28    services: Vec<Rc<Mutex<dyn Service>>>,
29}
30
31impl ServiceRegistry {
32    pub fn create() -> ServiceRegistryHandle {
33        Rc::new(Mutex::new(ServiceRegistry { services: Vec::new() }))
34    }
35
36    pub fn register_service(&mut self, service: Rc<Mutex<dyn Service>>) {
37        self.services.push(service);
38    }
39
40    async fn service_channel(&self, service_name: &str, channel: zx::Channel) -> Result<(), Error> {
41        for service_handle in self.services.iter() {
42            let mut service = service_handle.lock().await;
43            if service.can_handle_service(service_name) {
44                return service.process_stream(service_name, channel);
45            }
46        }
47
48        Err(format_err!("channel not handled for service: {}", service_name))
49    }
50
51    pub fn serve(registry_handle: ServiceRegistryHandle) -> GenerateService {
52        Box::new(
53            move |service_name: &str,
54                  channel: zx::Channel|
55                  -> LocalBoxFuture<'_, Result<(), Error>> {
56                let registry_handle_clone = registry_handle.clone();
57                let service_name_clone = String::from(service_name);
58
59                Box::pin(async move {
60                    registry_handle_clone
61                        .lock()
62                        .await
63                        .service_channel(service_name_clone.as_str(), channel)
64                        .await
65                })
66            },
67        )
68    }
69}