1mod 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}