1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
use crate::types::Result;
use async_trait::async_trait;
use http::{Method, Response};
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::fmt::Debug;
/// An async trait for making HTTP requests and deserializing responses.
#[async_trait]
pub trait Requestable {
/// Sends an HTTP request with a given HTTP method and data and returns a deserialized response.
///
/// # Arguments
///
/// * `method` - An HTTP method (`http::Method`) for the request.
/// * `data` - An optional JSON value (`serde_json::Value`) to include in the request body.
///
/// # Generic type parameters
///
/// * `Resp` - A type that implements the `Deserialize` trait and represents the response body.
///
/// # Returns
///
/// A `Result` containing a deserialized `http::Response` on success or an error on failure.
async fn request<Resp>(&self, method: Method, data: Option<Value>) -> Result<Response<Resp>>
where
Resp: for<'a> Deserialize<'a>;
/// Sends an HTTP request with a given HTTP method and returns a generic deserialized response.
///
/// This method is a convenience wrapper around `request()` that doesn't require a request body
/// and returns a generic deserialized response.
///
/// # Generic type parameters
///
/// * `T` - A type that implements both the `Serialize` and `DeserializeOwned` traits and represents the response body.
///
/// # Arguments
///
/// * `method` - An HTTP method (`http::Method`) for the request.
///
/// # Returns
///
/// A `Result` containing a generic deserialized response on success or an error on failure.
async fn request_generic<T>(&self, method: Method) -> Result<T>
where
T: Serialize + DeserializeOwned + Debug,
{
let request = self.request::<T>(method, None).await;
match request {
Ok(response) => Ok(response.into_body()),
Err(err) => Err(err),
}
}
/// ```
/// use firebase_rs::{Firebase, Response, Requestable};
/// use serde::{Serialize, Deserialize};
///
/// #[derive(Serialize, Deserialize, Debug)]
/// struct User {
/// name: String
/// }
///
/// # async fn run() {
/// let user = User { name: String::default() };
/// let mut firebase = Firebase::new("https://myfirebase.firebaseio.com").unwrap();
/// let endpoint = firebase.at("users");
/// let users = endpoint.set::<_, String>(&user).await;
/// # }
/// ```
async fn set<T, Resp>(&self, data: &T) -> Result<Response<Resp>>
where
T: Serialize + DeserializeOwned + Debug + Send + Sync,
Resp: for<'a> Deserialize<'a>,
{
let data = serde_json::to_value(data).unwrap();
self.request(Method::POST, Some(data)).await
}
/// ```
/// use firebase_rs::{Firebase, Requestable};
///
/// # async fn run() {
/// let mut firebase = Firebase::new("https://myfirebase.firebaseio.com").unwrap();
/// let endpoint = firebase.at("users");
/// let users = endpoint.get_as_string().await;
/// # }
/// ```
async fn get_as_string(&self) -> Result<Response<String>> {
self.request(Method::GET, None).await
}
/// ```
/// use std::collections::HashMap;
/// use firebase_rs::{Firebase, Requestable};
/// use serde::{Serialize, Deserialize};
///
/// #[derive(Serialize, Deserialize, Debug)]
/// struct User {
/// name: String
/// }
///
/// # async fn run() {
/// let mut firebase = Firebase::new("https://myfirebase.firebaseio.com").unwrap();
/// let endpoint = firebase.at("users").at("USER_ID");
/// let user = endpoint.get::<User>().await;
///
/// // OR
///
/// let mut firebase = Firebase::new("https://myfirebase.firebaseio.com").unwrap();
/// let endpoint = firebase.at("users");
/// let user = endpoint.get::<HashMap<String, User>>().await;
/// # }
/// ```
async fn get<T>(&self) -> Result<T>
where
T: Serialize + DeserializeOwned + Debug,
{
self.request_generic::<T>(Method::GET).await
}
/// ```
/// use firebase_rs::{Firebase, Response, Result, Requestable};
///
/// # async fn run() {
/// let mut firebase = Firebase::new("https://myfirebase.firebaseio.com").unwrap();
/// let endpoint = firebase.at("users").at("USER_ID");
/// endpoint.delete::<serde_json::Value>().await;
/// # }
/// ```
async fn delete<Resp>(&self) -> Result<Response<Resp>>
where
Resp: for<'a> Deserialize<'a>,
{
self.request(Method::DELETE, None).await
}
/// ```
/// use firebase_rs::{Firebase, Response, Requestable};
/// use serde::{Serialize, Deserialize};
///
/// #[derive(Serialize, Deserialize, Debug)]
/// struct User {
/// name: String
/// }
///
/// # async fn run() {
/// let user = User { name: String::default() };
/// let mut firebase = Firebase::new("https://myfirebase.firebaseio.com").unwrap();
/// let endpoint = firebase.at("users").at("USER_ID");
/// let users: Response<serde_json::Value> = endpoint.update(&user).await.unwrap();
/// # }
/// ```
async fn update<T, Resp>(&self, data: &T) -> Result<Response<Resp>>
where
T: DeserializeOwned + Serialize + Debug + Send + Sync,
Resp: for<'a> Deserialize<'a>,
{
let value = serde_json::to_value(data).unwrap();
self.request(Method::PATCH, Some(value)).await
}
}