use runestick::Bytes;
use std::fmt;
use std::fmt::Write as _;
pub fn module() -> Result<runestick::Module, runestick::ContextError> {
let mut module = runestick::Module::new(&["http"]);
module.ty(&["Client"]).build::<Client>()?;
module.ty(&["Response"]).build::<Response>()?;
module.ty(&["RequestBuilder"]).build::<RequestBuilder>()?;
module.ty(&["StatusCode"]).build::<StatusCode>()?;
module.ty(&["Error"]).build::<Error>()?;
module.function(&["Client", "new"], Client::new)?;
module.async_function(&["get"], get)?;
module.async_inst_fn("get", Client::get)?;
module.async_inst_fn("post", Client::post)?;
module.async_inst_fn("text", Response::text)?;
module.inst_fn("status", Response::status)?;
module.async_inst_fn("send", RequestBuilder::send)?;
module.inst_fn("header", RequestBuilder::header)?;
module.async_inst_fn("body_bytes", RequestBuilder::body_bytes)?;
module.inst_fn(runestick::STRING_DISPLAY, StatusCode::display)?;
Ok(module)
}
#[derive(Debug)]
pub struct Error {
inner: reqwest::Error,
}
impl From<reqwest::Error> for Error {
fn from(inner: reqwest::Error) -> Self {
Self { inner }
}
}
#[derive(Debug)]
struct Client {
client: reqwest::Client,
}
#[derive(Debug)]
pub struct Response {
response: reqwest::Response,
}
#[derive(Debug)]
pub struct StatusCode {
inner: reqwest::StatusCode,
}
impl StatusCode {
fn display(&self, buf: &mut String) -> fmt::Result {
write!(buf, "{}", self.inner)
}
}
impl Response {
async fn text(self) -> Result<String, Error> {
let text = self.response.text().await?;
Ok(text)
}
fn status(&self) -> StatusCode {
let inner = self.response.status();
StatusCode { inner }
}
}
#[derive(Debug)]
pub struct RequestBuilder {
request: reqwest::RequestBuilder,
}
impl RequestBuilder {
async fn send(self) -> Result<Response, Error> {
let response = self.request.send().await?;
Ok(Response { response })
}
fn header(self, key: &str, value: &str) -> Self {
Self {
request: self.request.header(key, value),
}
}
async fn body_bytes(self, bytes: Bytes) -> Result<Self, Error> {
let bytes = bytes.into_vec();
Ok(Self {
request: self.request.body(bytes),
})
}
}
impl Client {
fn new() -> Self {
Self {
client: reqwest::Client::new(),
}
}
async fn get(&self, url: &str) -> Result<RequestBuilder, Error> {
let request = self.client.get(url);
Ok(RequestBuilder { request })
}
async fn post(&self, url: &str) -> Result<RequestBuilder, Error> {
let request = self.client.post(url);
Ok(RequestBuilder { request })
}
}
async fn get(url: &str) -> Result<Response, Error> {
Ok(Response {
response: reqwest::get(url).await?,
})
}
runestick::decl_external!(Error);
runestick::decl_external!(Client);
runestick::decl_external!(Response);
runestick::decl_external!(RequestBuilder);
runestick::decl_external!(StatusCode);