#[macro_export]
#[doc(hidden)]
macro_rules! define_handler {
(
$(#[$meta:meta])*
$vis:vis struct $handler:ident;
) => {
$(#[$meta])*
$vis struct $handler {
client: $crate::client::RestClient,
}
impl $handler {
pub fn new(client: $crate::client::RestClient) -> Self {
Self { client }
}
}
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! impl_crud {
($handler:ty { $($methods:tt)* }) => {
impl $handler {
$crate::impl_crud!(@methods $($methods)*);
}
};
(@methods list => $entity:ty, $path:literal; $($rest:tt)*) => {
pub async fn list(&self) -> $crate::error::Result<Vec<$entity>> {
self.client.get($path).await
}
$crate::impl_crud!(@methods $($rest)*);
};
(@methods get(u32) => $entity:ty, $path:literal; $($rest:tt)*) => {
pub async fn get(&self, uid: u32) -> $crate::error::Result<$entity> {
self.client.get(&format!($path, uid)).await
}
$crate::impl_crud!(@methods $($rest)*);
};
(@methods get(&str) => $entity:ty, $path:literal; $($rest:tt)*) => {
pub async fn get(&self, uid: &str) -> $crate::error::Result<$entity> {
self.client.get(&format!($path, uid)).await
}
$crate::impl_crud!(@methods $($rest)*);
};
(@methods delete(u32), $path:literal; $($rest:tt)*) => {
pub async fn delete(&self, uid: u32) -> $crate::error::Result<()> {
self.client.delete(&format!($path, uid)).await
}
$crate::impl_crud!(@methods $($rest)*);
};
(@methods delete(&str), $path:literal; $($rest:tt)*) => {
pub async fn delete(&self, uid: &str) -> $crate::error::Result<()> {
self.client.delete(&format!($path, uid)).await
}
$crate::impl_crud!(@methods $($rest)*);
};
(@methods create($req:ty) => $entity:ty, $path:literal; $($rest:tt)*) => {
pub async fn create(&self, request: $req) -> $crate::error::Result<$entity> {
self.client.post($path, &request).await
}
$crate::impl_crud!(@methods $($rest)*);
};
(@methods update(u32, $req:ty) => $entity:ty, $path:literal; $($rest:tt)*) => {
pub async fn update(&self, uid: u32, request: $req) -> $crate::error::Result<$entity> {
self.client.put(&format!($path, uid), &request).await
}
$crate::impl_crud!(@methods $($rest)*);
};
(@methods update(&str, $req:ty) => $entity:ty, $path:literal; $($rest:tt)*) => {
pub async fn update(&self, uid: &str, request: $req) -> $crate::error::Result<$entity> {
self.client.put(&format!($path, uid), &request).await
}
$crate::impl_crud!(@methods $($rest)*);
};
(@methods) => {};
}
#[cfg(test)]
mod tests {
#[allow(dead_code)]
mod test_handler {
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TestEntity {
pub uid: u32,
pub name: String,
}
#[derive(Debug, Serialize)]
pub struct CreateTestRequest {
pub name: String,
}
define_handler!(
pub struct TestHandler;
);
impl_crud!(TestHandler {
list => TestEntity, "/v1/test";
get(u32) => TestEntity, "/v1/test/{}";
delete(u32), "/v1/test/{}";
create(CreateTestRequest) => TestEntity, "/v1/test";
update(u32, CreateTestRequest) => TestEntity, "/v1/test/{}";
});
impl TestHandler {
pub async fn custom(&self) -> crate::error::Result<Vec<TestEntity>> {
self.client.get("/v1/test/custom").await
}
}
}
#[test]
fn test_macro_compiles() {
}
}