#![feature(try_trait)]
extern crate serde;
use serde::{Serialize, de::DeserializeOwned};
use std::fmt::Display;
use std::option::NoneError;
pub enum Error {
Fetch(String),
SerDe(String),
NotFound(String),
Authorization(String),
}
impl From<NoneError> for Error {
fn from(_: NoneError) -> Error {
Error::NotFound(String::from("Expected a value, found None"))
}
}
pub trait Provider<P> {
type Data: Endpoint;
fn get(provider: &P, id: <Self::Data as Endpoint>::Id) -> Result<Self::Data, Error>;
fn list(provider: &P, query: Self::Data) -> Vec<Self::Data>;
fn create(provider: &P, query: Self::Data) -> Result<Self::Data, Error>;
fn update(provider: &P, id: <Self::Data as Endpoint>::Id, new_data: Self::Data) -> Result<Self::Data, Error>;
fn delete(provider: &P, id: <Self::Data as Endpoint>::Id);
}
pub trait Endpoint: Default + Serialize + DeserializeOwned {
type Id: Display;
fn endpoint() -> &'static str;
fn get<F: Fetch>(&self, id: Self::Id) -> Result<Self, Error> {
F::fetch("GET", format!("{}/{}", Self::endpoint(), id), None)
}
fn list<F: Fetch>(&self) -> Result<Self, Error> {
F::fetch("GET", format!("{}", Self::endpoint()), None)
}
fn find<F: Fetch>(&self, query: Self) -> Result<Self, Error> {
F::fetch("GET", format!("{}", Self::endpoint()), Some(query))
}
fn create<F: Fetch>(&self, new: Self) -> Result<Self, Error> {
F::fetch("POST", format!("{}", Self::endpoint()), Some(new))
}
fn update<F: Fetch>(&self, id: Self::Id, data: Self) -> Result<Self, Error> {
F::fetch("PUT", format!("{}/{}", Self::endpoint(), id), Some(data))
}
fn delete<F: Fetch>(&self, id: Self::Id) -> Result<Self, Error> {
F::fetch("DELETE", format!("{}/{}", Self::endpoint(), id), None)
}
}
pub trait Fetch {
fn fetch<T: Endpoint>(method: &'static str, url: String, query: Option<T>) -> Result<T, Error>;
}