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::err_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
50 .get_metadata(&self.name)
51 .await
52 .map_err(|_| zx::Status::INTERNAL)?
53 .map_err(|e| e.err().unwrap_or(zx::Status::INTERNAL))?
54 .metadata;
55 Ok(Self { data: Some(Arc::new(data)), name: self.name })
56 }
57
58 pub fn create_handler(&self, scope: fasync::ScopeHandle) -> Option<MetadataHandler> {
59 let data = self.data.clone()?;
60 Some(MetadataHandler { data, scope })
61 }
62
63 pub fn create_service_offer(&self) -> Option<ServiceOffer<fmetadata::Service>> {
64 Some(ServiceOffer::<fmetadata::Service>::new_next())
65 }
66
67 pub fn serve<O>(
68 &self,
69 fs: &mut ServiceFs<O>,
70 scope: fasync::ScopeHandle,
71 instance_name: impl Into<String>,
72 ) -> Option<fdf::Offer>
73 where
74 O: ServiceObjTrait,
75 {
76 let data = self.data.clone()?;
77 let handler = MetadataHandler { data, scope };
78
79 let offer = ServiceOffer::<fmetadata::Service>::new_with_name(self.name.clone())
80 .add_default_named_next(fs, instance_name, handler)
81 .build_zircon_offer_next();
82
83 Some(offer)
84 }
85}
86
87pub struct MetadataHandler {
88 data: Arc<Vec<u8>>,
89 scope: fasync::ScopeHandle,
90}
91
92impl fmetadata::ServiceHandler for MetadataHandler {
93 fn metadata(&self, server_end: ServerEnd<fmetadata::Metadata>) {
94 let data = self.data.clone();
95 self.scope.spawn_local(async move {
96 let dispatcher = fidl_next::ServerDispatcher::new(server_end);
97 let _ = dispatcher.run_local(MetadataServerImpl { data }).await;
98 });
99 }
100}
101
102struct MetadataServerImpl {
103 data: Arc<Vec<u8>>,
104}
105
106impl fmetadata::MetadataLocalServerHandler for MetadataServerImpl {
107 async fn get_persisted_metadata(
108 &mut self,
109 responder: Responder<fmetadata::metadata::GetPersistedMetadata>,
110 ) {
111 let _ = responder.respond(self.data.as_slice()).await;
112 }
113}