use clap::Parser;
use futures_util::future;
use hyper::server::Server;
use hyper::service::{make_service_fn, service_fn};
use hyper::{Body, Request, Response};
use hyper_staticfile::Static;
use std::path::PathBuf;
pub fn find_rustdoc() -> Option<PathBuf> {
let output = std::process::Command::new("rustup")
.arg("which")
.arg("rustdoc")
.output()
.unwrap();
if output.status.success() {
Some(PathBuf::from(String::from_utf8(output.stdout).unwrap()))
} else {
None
}
.and_then(|rustdoc| {
Some(
rustdoc
.parent()?
.parent()?
.join("share")
.join("doc")
.join("rust")
.join("html"),
)
})
}
async fn handle_request<B>(
req: Request<B>,
static_: Static,
) -> Result<Response<Body>, std::io::Error> {
static_.clone().serve(req).await
}
pub async fn serve_rustbook(addr: &std::net::SocketAddr) -> Result<(), anyhow::Error> {
let rustdoc_dir = find_rustdoc().unwrap();
Ok(serve_dir(addr, &rustdoc_dir).await?)
}
pub async fn serve_dir(addr: &std::net::SocketAddr, dir: &PathBuf) -> Result<(), anyhow::Error> {
let handler = make_service_fn(|_| {
let dir = Static::new(dir.clone());
future::ok::<_, hyper::Error>(service_fn(move |req| handle_request(req, dir.clone())))
});
Ok(Server::bind(addr).serve(handler).await?)
}