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