#[cfg(not(target_family = "wasm"))]
use burn_remote::server::Transport;
use burn_remote::{
Endpoint,
server::{BackendServer, RemoteProtocol, ServeError, ServerSettings},
};
use crate::DispatchDevice;
use crate::backends::*;
macro_rules! with_backend {
($devices:expr, |$b:ident, $hosted:ident| $body:expr) => {{
let devices: Vec<DispatchDevice> =
$devices.into_iter().map(DispatchDevice::inner).collect();
match devices.first() {
None => Err(ServeError::NoDevices),
#[cfg(cube_backend)]
Some(DispatchDevice::Cube(_)) => {
type $b = Cube;
let $hosted = hosted!(devices, Cube)?;
$body
}
#[cfg(feature = "flex")]
Some(DispatchDevice::Flex(_)) => {
type $b = Flex;
let $hosted = hosted!(devices, Flex)?;
$body
}
#[cfg(feature = "remote")]
Some(DispatchDevice::Remote(_)) => Err(ServeError::UnsupportedDevice {
reason: "a remote device cannot host a remote server".into(),
}),
#[cfg(feature = "capture")]
Some(DispatchDevice::Capture(_)) => Err(ServeError::UnsupportedDevice {
reason: "a capture device cannot host a remote server".into(),
}),
#[cfg(feature = "group")]
Some(DispatchDevice::Group(_)) => Err(ServeError::UnsupportedDevice {
reason: "a device group cannot host a remote server".into(),
}),
#[cfg(feature = "autodiff")]
Some(DispatchDevice::Autodiff(_)) => {
unreachable!("Autodiff stripped by DispatchDevice::inner")
}
}
}};
}
macro_rules! hosted {
($devices:expr, $variant:ident) => {
$devices
.into_iter()
.map(|device| match device {
DispatchDevice::$variant(device) => Ok(device),
#[allow(unreachable_patterns)]
_ => Err(ServeError::MixedBackends),
})
.collect::<Result<Vec<_>, ServeError>>()
};
}
#[cfg(not(target_family = "wasm"))]
pub fn serve(
devices: Vec<DispatchDevice>,
settings: ServerSettings,
transport: Transport,
) -> Result<(), ServeError> {
with_backend!(devices, |B, hosted| BackendServer::<B>::new(hosted)
.with_settings(settings)
.serve(transport))
}
#[cfg(not(target_family = "wasm"))]
pub async fn serve_async(
devices: Vec<DispatchDevice>,
settings: ServerSettings,
transport: Transport,
) -> Result<(), ServeError> {
with_backend!(devices, |B, hosted| BackendServer::<B>::new(hosted)
.with_settings(settings)
.serve_async(transport)
.await)
}
pub fn into_protocol(
devices: Vec<DispatchDevice>,
settings: ServerSettings,
endpoint: &Endpoint,
) -> Result<RemoteProtocol, ServeError> {
with_backend!(devices, |B, hosted| BackendServer::<B>::new(hosted)
.with_settings(settings)
.into_protocol(endpoint))
}