use super::SERVERS;
use crate::{RuntimelessRuntime, TestTransport};
use async_channel::Receiver;
use std::io::{Error, Result};
use trillium::Info;
use trillium_server_common::Server;
use url::Url;
#[derive(Debug)]
pub struct RuntimelessServer {
host: String,
port: u16,
channel: Receiver<TestTransport>,
}
impl RuntimelessServer {
pub fn is_empty() -> bool {
SERVERS.is_empty()
}
pub fn len() -> usize {
SERVERS.len()
}
}
impl Server for RuntimelessServer {
type Runtime = RuntimelessRuntime;
type Transport = TestTransport;
type UdpTransport = ();
fn runtime() -> Self::Runtime {
RuntimelessRuntime::default()
}
async fn accept(&mut self) -> Result<Self::Transport> {
self.channel.recv().await.map_err(Error::other)
}
fn from_host_and_port(host: &str, mut port: u16) -> Self {
if port == 0 {
loop {
port = fastrand::u16(..);
if !SERVERS.contains_key(&(host.to_string(), port)) {
break;
}
}
}
let entry = SERVERS
.entry((host.to_string(), port))
.or_insert_with(async_channel::unbounded);
let (_, channel) = entry.value();
Self {
host: host.to_string(),
channel: channel.clone(),
port,
}
}
async fn clean_up(self) {
SERVERS.remove(&(self.host, self.port));
}
fn init(&self, info: &mut Info) {
info.insert_shared_state(
Url::parse(&format!("http://{}:{}", self.host, self.port)).unwrap(),
);
}
}