Skip to main content

fdf_metadata/
lib.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 fdf_component::ServiceOffer;
6use fidl_fuchsia_driver_framework as fdf;
7use fidl_next::{Responder, ServerEnd};
8use fidl_next_fuchsia_driver_metadata as fmetadata;
9use fuchsia_async as fasync;
10use fuchsia_component::server::{ServiceFs, ServiceObjTrait};
11use std::sync::Arc;
12
13pub struct MetadataServer {
14    data: Option<Arc<Vec<u8>>>,
15    name: String,
16}
17
18impl MetadataServer {
19    pub fn new(name: impl Into<String>) -> Self {
20        Self { data: None, name: name.into() }
21    }
22
23    pub fn with_metadata<T: fidl::Persistable>(self, metadata: &T) -> Result<Self, zx::Status> {
24        let data = fidl::persist(metadata).map_err(|_| zx::Status::INTERNAL)?;
25        Ok(Self { data: Some(Arc::new(data)), name: self.name })
26    }
27
28    pub async fn forward_from_pdev(
29        self,
30        pdev: &fidl_fuchsia_hardware_platform_device::DeviceProxy,
31    ) -> Result<Self, zx::Status> {
32        let data = pdev
33            .get_metadata(&self.name)
34            .await
35            .map_err(|_| zx::Status::INTERNAL)?
36            .map_err(zx::Status::from_raw)?;
37        Ok(Self { data: Some(Arc::new(data)), name: self.name })
38    }
39
40    pub fn create_handler(&self, scope: fasync::ScopeHandle) -> Option<MetadataHandler> {
41        let data = self.data.clone()?;
42        Some(MetadataHandler { data, scope })
43    }
44
45    pub fn create_service_offer(&self) -> Option<ServiceOffer<fmetadata::Service>> {
46        Some(ServiceOffer::<fmetadata::Service>::new_next())
47    }
48
49    pub fn serve<O>(
50        &self,
51        fs: &mut ServiceFs<O>,
52        scope: fasync::ScopeHandle,
53        instance_name: impl Into<String>,
54    ) -> Option<fdf::Offer>
55    where
56        O: ServiceObjTrait,
57    {
58        let data = self.data.clone()?;
59        let handler = MetadataHandler { data, scope };
60
61        let offer = ServiceOffer::<fmetadata::Service>::new_with_name(self.name.clone())
62            .add_default_named_next(fs, instance_name, handler)
63            .build_zircon_offer_next();
64
65        Some(offer)
66    }
67}
68
69pub struct MetadataHandler {
70    data: Arc<Vec<u8>>,
71    scope: fasync::ScopeHandle,
72}
73
74impl fmetadata::ServiceHandler for MetadataHandler {
75    fn metadata(&self, server_end: ServerEnd<fmetadata::Metadata>) {
76        let data = self.data.clone();
77        self.scope.spawn_local(async move {
78            let dispatcher = fidl_next::ServerDispatcher::new(server_end);
79            let _ = dispatcher.run_local(MetadataServerImpl { data }).await;
80        });
81    }
82}
83
84struct MetadataServerImpl {
85    data: Arc<Vec<u8>>,
86}
87
88impl fmetadata::MetadataLocalServerHandler for MetadataServerImpl {
89    async fn get_persisted_metadata(
90        &mut self,
91        responder: Responder<fmetadata::metadata::GetPersistedMetadata>,
92    ) {
93        let _ = responder.respond(self.data.as_slice()).await;
94    }
95}