use crate::api::{HasPagination, HasResponse};
use crate::method::{Create, Delete, Get, List, Method, Update};
use crate::DigitalOcean;
use crate::error::Error;
use getset::{Getters, MutGetters, Setters};
use serde_json::Value;
use std::marker::PhantomData;
use url::Url;
use url_serde;
pub type AccountRequest<M, V> = Request<M, V>;
pub type ActionRequest<M, V> = Request<M, V>;
pub type CertificateRequest<M, V> = Request<M, V>;
pub type DomainRecordRequest<M, V> = Request<M, V>;
pub type DomainRequest<M, V> = Request<M, V>;
pub type DropletActionRequest<M, V> = Request<M, V>;
pub type DropletRequest<M, V> = Request<M, V>;
pub type FloatingIpActionRequest<M, V> = Request<M, V>;
pub type FloatingIpRequest<M, V> = Request<M, V>;
pub type ImageActionRequest<M, V> = Request<M, V>;
pub type ImageRequest<M, V> = Request<M, V>;
pub type CustomImageRequest<M, V> = Request<M, V>;
pub type LoadBalancerRequest<M, V> = Request<M, V>;
pub type RegionRequest<M, V> = Request<M, V>;
pub type SizeRequest<M, V> = Request<M, V>;
pub type SnapshotRequest<M, V> = Request<M, V>;
pub type SshKeyRequest<M, V> = Request<M, V>;
pub type TagRequest<M, V> = Request<M, V>;
pub type VolumeActionRequest<M, V> = Request<M, V>;
pub type VolumeRequest<M, V> = Request<M, V>;
#[derive(Debug, Clone, Serialize, Deserialize, MutGetters, Getters, Setters)]
pub struct Request<A: Method, R> {
#[get_mut = "pub"]
#[set = "pub"]
#[get = "pub"]
#[serde(with = "url_serde")]
url: Url,
#[get_mut = "pub"]
#[set = "pub"]
#[get = "pub"]
body: Value,
#[get = "pub"]
method: A,
value: PhantomData<R>
}
impl<A: Method, V> Request<A, V> {
pub fn new(url: Url) -> Self {
Request {
url,
body: Value::Null,
method: A::default(),
value: PhantomData,
}
}
pub(crate) fn transmute<C: Method, D>(self) -> Request<C, D> {
let mut req = Request::new(self.url);
req.set_body(self.body);
req
}
}
impl<V> Request<List, V> {
pub fn limit(mut self, limit: Option<usize>) -> Self {
self.method.0 = limit;
self
}
}
pub trait Executable<T: HasResponse>: Sized {
fn execute(self, instance: &DigitalOcean) -> Result<T, Error>;
}
impl<V> Executable<Vec<V>> for Request<List, Vec<V>>
where
Vec<V>: HasResponse,
<Vec<V> as HasResponse>::Response: HasPagination {
fn execute(self, instance: &DigitalOcean) -> Result<Vec<V>, Error> {
let response: Vec<V> = instance.list(self)?;
Ok(response)
}
}
impl<V: HasResponse> Executable<V> for Request<Create, V> {
fn execute(self, instance: &DigitalOcean) -> Result<V, Error> {
let response = instance.post(self)?;
Ok(response)
}
}
impl<V: HasResponse> Executable<V> for Request<Update, V> {
fn execute(self, instance: &DigitalOcean) -> Result<V, Error> {
let response = instance.put(self)?;
Ok(response)
}
}
impl<V: HasResponse> Executable<V> for Request<Get, V> {
fn execute(self, instance: &DigitalOcean) -> Result<V, Error> {
let response = instance.get(self)?;
Ok(response)
}
}
impl Executable<()> for Request<Delete, ()> {
fn execute(self, instance: &DigitalOcean) -> Result<(), Error> {
instance.delete(self)
}
}