use std::{
net::Ipv4Addr,
time::{Duration, SystemTime},
};
use bytes::Bytes;
use kynos::{
Router,
extract::media::MediaType,
http::etag::ETag,
response::range::{
served::{Conditions, Delivery, Served},
source::ByteSource,
},
server::Server,
};
struct Mpeg;
impl MediaType for Mpeg {
const MEDIA_TYPE: &'static str = "audio/mpeg";
}
struct Synthetic {
length: u64,
}
impl ByteSource for Synthetic {
type Error = std::convert::Infallible;
async fn complete_length(&self) -> Result<u64, Self::Error> {
Ok(self.length)
}
async fn read_span(&self, first: u64, last: u64) -> Result<Bytes, Self::Error> {
let span = usize::try_from(last - first + 1).unwrap_or(0);
let mut octets = Vec::with_capacity(span);
for offset in first..=last {
octets.push(b'a' + u8::try_from(offset % 26).unwrap_or(0));
}
Ok(Bytes::from(octets))
}
}
fn recording() -> Served<Synthetic, Mpeg> {
Served::new(Synthetic {
length: 512 * 1024 * 1024,
})
.etag(ETag::strong("synthetic-v1"))
.last_modified(SystemTime::UNIX_EPOCH + Duration::from_secs(1_700_000_000))
.cache_control("public, max-age=86400")
.attachment("recording.mp3")
}
#[kynos::get("/recordings/current")]
async fn get_recording(conditions: Conditions) -> Delivery<Mpeg> {
recording()
.deliver(&conditions)
.await
.expect("a generator cannot fail")
}
#[kynos::head("/recordings/current")]
async fn head_recording(conditions: Conditions) -> Delivery<Mpeg> {
recording()
.deliver(&conditions)
.await
.expect("a generator cannot fail")
}
#[tokio::main]
async fn main() -> kynos::Result<()> {
let router = Router::<()>::new().mount(kynos::routes![get_recording, head_recording]);
println!("{}", router.openapi()?.to_json()?);
Server::new(router.build(())?)
.bind((Ipv4Addr::UNSPECIFIED, 3000))
.serve()
.await
}