Skip to content

Instantly share code, notes, and snippets.

@KodrAus
Last active December 5, 2016 07:30
Show Gist options
  • Save KodrAus/a242e49cc7f69114017c9d65733cbe4b to your computer and use it in GitHub Desktop.
Save KodrAus/a242e49cc7f69114017c9d65733cbe4b to your computer and use it in GitHub Desktop.
elastic_requests codegen
use std::borrow::Cow;
use std::ops::Deref;
// - Codegen once -
#[derive(Debug)]
pub struct Body<'a>(Cow<'a, [u8]>);
impl <'a> From<Vec<u8>> for Body<'a> {
fn from(value: Vec<u8>) -> Body<'a> {
Body(value.into())
}
}
impl <'a> From<&'a [u8]> for Body<'a> {
fn from(value: &'a [u8]) -> Body<'a> {
Body(value.into())
}
}
impl <'a> From<&'a str> for Body<'a> {
fn from(value: &'a str) -> Body<'a> {
Body(value.as_bytes().into())
}
}
impl <'a> From<String> for Body<'a> {
fn from(value: String) -> Body<'a> {
Body(Cow::Owned(value.into()))
}
}
impl <'a> Deref for Body<'a> {
type Target = Cow<'a, [u8]>;
fn deref(&self) -> &Cow<'a, [u8]> {
&self.0
}
}
#[derive(Debug)]
pub enum HttpMethod {
Head,
Get,
Post,
Put,
Delete,
}
macro_rules! wrapper {
($name:ident) => {
#[derive(Debug)]
pub struct $name<'a>(pub Cow<'a, str>);
impl <'a> From<&'a str> for $name<'a> {
fn from(value: &'a str) -> $name<'a> {
$name(Cow::Borrowed(value))
}
}
impl <'a> From<String> for $name<'a> {
fn from(value: String) -> $name<'a> {
$name(Cow::Owned(value))
}
}
impl <'a> ::std::ops::Deref for $name<'a> {
type Target = str;
fn deref(&self) -> &str {
&self.0
}
}
}
}
wrapper!(Index);
wrapper!(Type);
#[derive(Debug)]
pub struct HttpRequest<'a> {
pub url: Cow<'a, str>,
pub method: HttpMethod,
pub body: Option<&'a Body<'a>>,
}
// - Codegen per endpoint -
pub enum ExistsAliasUrlParams<'a> {
None,
Index(Index<'a>),
IndexType(Index<'a>, Type<'a>),
}
pub struct ExistsAliasRequestParams<'a> {
pub url_params: ExistsAliasUrlParams<'a>,
pub body: Body<'a>,
}
impl<'a> ExistsAliasRequestParams<'a> {
pub fn new<IBody: Into<Body<'a>>>(body: IBody) -> ExistsAliasRequestParams<'a> {
ExistsAliasRequestParams {
url_params: ExistsAliasUrlParams::None,
body: body.into(),
}
}
pub fn index<IIndex: Into<Index<'a>>, IBody: Into<Body<'a>>>
(index: IIndex,
body: IBody)
-> ExistsAliasRequestParams<'a> {
ExistsAliasRequestParams {
url_params: ExistsAliasUrlParams::Index(index.into()),
body: body.into(),
}
}
pub fn index_ty<IIndex: Into<Index<'a>>, IType: Into<Type<'a>>, IBody: Into<Body<'a>>>
(index: IIndex,
ty: IType,
body: IBody)
-> ExistsAliasRequestParams<'a> {
ExistsAliasRequestParams {
url_params: ExistsAliasUrlParams::IndexType(index.into(), ty.into()),
body: body.into(),
}
}
}
impl<'a> ExistsAliasRequestParams<'a> {
pub fn url(&'a self) -> Cow<'a, str> {
match self.url_params {
ExistsAliasUrlParams::None => Cow::Borrowed("/_alias"),
ExistsAliasUrlParams::Index(ref index) => {
let mut url = String::with_capacity(8usize + index.len());
url.push_str("/");
url.push_str(index.as_ref());
url.push_str("/_alias");
Cow::Owned(url)
}
ExistsAliasUrlParams::IndexType(ref index, ref ty) => {
let mut url = String::with_capacity(9usize + index.len() + ty.len());
url.push_str("/");
url.push_str(index.as_ref());
url.push_str("/_alias/");
url.push_str(ty.as_ref());
Cow::Owned(url)
}
}
}
}
impl<'a, 'b: 'a> Into<HttpRequest<'a>> for &'a ExistsAliasRequestParams<'b> {
fn into(self) -> HttpRequest<'a> {
HttpRequest {
url: self.url(),
method: HttpMethod::Post,
body: Some(&self.body),
}
}
}
const BODY: &'static [u8] = b"{}";
fn main() {
// Request types are shells that borrow data:
// - The request body needs to outlive the endpoint request
// - The endpoint request needs to outlive the http request
// Below are examples showing a mix of owned and borrowed data
let req = ExistsAliasRequestParams::index_ty("index", String::from("ty"), BODY);
let req = ExistsAliasRequestParams::index_ty("index", "ty", Vec::new());
fn do_req<'a, I: Into<HttpRequest<'a>>>(req: I) {
let http = req.into();
println!("req: {:?}", http);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment