blob: 40c149e231e68115e3d33ec304fa82f396b209f3 [file]
// Copyright 2026 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
mod serde;
use fdf_component::ServiceOffer;
use fidl_fuchsia_driver_framework as fdf;
use fidl_next::{Responder, ServerEnd};
use fidl_next_fuchsia_driver_metadata as fmetadata;
use fidl_next_fuchsia_hardware_platform_device as fdevice_next;
use fuchsia_async as fasync;
use fuchsia_component::server::{ServiceFs, ServiceObjTrait};
use std::sync::Arc;
pub use serde::*;
pub struct MetadataServer {
data: Option<Arc<Vec<u8>>>,
name: String,
}
impl MetadataServer {
pub fn new(name: impl Into<String>) -> Self {
Self { data: None, name: name.into() }
}
pub fn with_metadata<T: fidl::Persistable>(self, metadata: &T) -> Result<Self, zx::Status> {
let data = fidl::persist(metadata).map_err(|_| zx::Status::INTERNAL)?;
Ok(Self { data: Some(Arc::new(data)), name: self.name })
}
pub async fn forward_from_pdev(
self,
pdev: &fidl_fuchsia_hardware_platform_device::DeviceProxy,
) -> Result<Self, zx::Status> {
let data = pdev
.get_metadata(&self.name)
.await
.map_err(|_| zx::Status::INTERNAL)?
.map_err(zx::Status::from_raw)?;
Ok(Self { data: Some(Arc::new(data)), name: self.name })
}
pub async fn forward_from_pdev_next(
self,
pdev: &fidl_next::Client<fdevice_next::Device>,
) -> Result<Self, zx::Status> {
let data = pdev.get_metadata(&self.name).await.map_err(|_| zx::Status::INTERNAL)??.metadata;
Ok(Self { data: Some(Arc::new(data)), name: self.name })
}
pub fn create_handler(&self, scope: fasync::ScopeHandle) -> Option<MetadataHandler> {
let data = self.data.clone()?;
Some(MetadataHandler { data, scope })
}
pub fn create_service_offer(&self) -> Option<ServiceOffer<fmetadata::Service>> {
Some(ServiceOffer::<fmetadata::Service>::new_next())
}
pub fn serve<O>(
&self,
fs: &mut ServiceFs<O>,
scope: fasync::ScopeHandle,
instance_name: impl Into<String>,
) -> Option<fdf::Offer>
where
O: ServiceObjTrait,
{
let data = self.data.clone()?;
let handler = MetadataHandler { data, scope };
let offer = ServiceOffer::<fmetadata::Service>::new_with_name(self.name.clone())
.add_default_named_next(fs, instance_name, handler)
.build_zircon_offer_next();
Some(offer)
}
}
pub struct MetadataHandler {
data: Arc<Vec<u8>>,
scope: fasync::ScopeHandle,
}
impl fmetadata::ServiceHandler for MetadataHandler {
fn metadata(&self, server_end: ServerEnd<fmetadata::Metadata>) {
let data = self.data.clone();
self.scope.spawn_local(async move {
let dispatcher = fidl_next::ServerDispatcher::new(server_end);
let _ = dispatcher.run_local(MetadataServerImpl { data }).await;
});
}
}
struct MetadataServerImpl {
data: Arc<Vec<u8>>,
}
impl fmetadata::MetadataLocalServerHandler for MetadataServerImpl {
async fn get_persisted_metadata(
&mut self,
responder: Responder<fmetadata::metadata::GetPersistedMetadata>,
) {
let _ = responder.respond(self.data.as_slice()).await;
}
}