#![feature(try_trait)]
#![forbid(unsafe_code, missing_docs)]
mod error;
mod resources;
mod token;
pub use crate::error::*;
use crate::resources::service_account::ServiceAccount;
pub use crate::resources::{
bucket::{Bucket, NewBucket},
object::Object,
*,
};
use crate::token::Token;
use std::sync::Mutex;
lazy_static::lazy_static! {
static ref TOKEN_CACHE: Mutex<Token> = Mutex::new(Token::new(
"https://www.googleapis.com/auth/devstorage.full_control",
));
static ref IAM_TOKEN_CACHE: Mutex<Token> = Mutex::new(Token::new(
"https://www.googleapis.com/auth/iam"
));
pub static ref SERVICE_ACCOUNT: ServiceAccount = ServiceAccount::get();
}
const BASE_URL: &'static str = "https://www.googleapis.com/storage/v1";
fn get_headers() -> Result<reqwest::header::HeaderMap, Error> {
let mut result = reqwest::header::HeaderMap::new();
let mut guard = TOKEN_CACHE.lock().unwrap();
let token = guard.get()?;
result.insert(
reqwest::header::AUTHORIZATION,
format!("Bearer {}", token).parse().unwrap(),
);
Ok(result)
}
fn from_str<'de, T, D>(deserializer: D) -> Result<T, D::Error>
where
T: std::str::FromStr,
T::Err: std::fmt::Display,
D: serde::Deserializer<'de>,
{
use serde::de::Deserialize;
let s = String::deserialize(deserializer)?;
T::from_str(&s).map_err(serde::de::Error::custom)
}
fn from_str_opt<'de, T, D>(deserializer: D) -> Result<Option<T>, D::Error>
where
T: std::str::FromStr,
T::Err: std::fmt::Display,
D: serde::Deserializer<'de>,
{
let s: Result<serde_json::Value, _> = serde::Deserialize::deserialize(deserializer);
println!("{:?}", s);
match s {
Ok(serde_json::Value::String(s)) => T::from_str(&s)
.map_err(serde::de::Error::custom)
.map(Option::from),
Ok(serde_json::Value::Number(num)) => T::from_str(&num.to_string())
.map_err(serde::de::Error::custom)
.map(Option::from),
Ok(_value) => Err(serde::de::Error::custom("Incorrect type")),
Err(_) => Ok(None),
}
}
#[cfg(test)]
fn read_test_bucket() -> Bucket {
dotenv::dotenv().ok();
let name = std::env::var("TEST_BUCKET").unwrap();
match Bucket::read(&name) {
Ok(bucket) => bucket,
Err(_not_found) => Bucket::create(&NewBucket {
name,
..Default::default()
})
.unwrap(),
}
}
#[cfg(test)]
fn create_test_bucket(name: &str) -> Bucket {
dotenv::dotenv().ok();
let base_name = std::env::var("TEST_BUCKET").unwrap();
let name = format!("{}-{}", base_name, name);
let new_bucket = NewBucket {
name,
..Default::default()
};
match dbg!(Bucket::create(&new_bucket)) {
Ok(bucket) => bucket,
Err(_alread_exists) => dbg!(Bucket::read(&new_bucket.name)).unwrap(),
}
}