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