const VERSION: Option<&'static str> = option_env!("CARGO_PKG_VERSION");
use crate::plugins::gstorage::serde_json::from_str;
use tdb_core::storage::file_metadata::FileMetadata;
use std::fmt;
use std::error;
use std::borrow::Cow;
#[derive(Serialize)]
enum GStorageOp {
AddDtf,
}
impl fmt::Display for GStorageOp {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
GStorageOp::AddDtf => write!(f, "add.dtf"),
}
}
}
#[derive(Serialize)]
pub struct GStorageOpMetadata<'a> {
id: Cow<'a, str>,
#[serde(rename = "selfLink")]
self_link: Cow<'a, str>,
name: Cow<'a, str>,
bucket: Cow<'a, str>,
metageneration: Cow<'a, str>,
#[serde(rename = "timeCreated")]
time_created: Cow<'a, str>,
#[serde(rename = "timeStorageClassUpdated")]
time_storage_class_updated: Cow<'a, str>,
size: Cow<'a, str>,
#[serde(rename = "md5Hash")]
md5_hash: Cow<'a, str>,
#[serde(rename = "mediaLink")]
media_link: Cow<'a, str>,
op_type: GStorageOp,
pub start_ts: u32,
pub finish_ts: u32,
pub response_time: u32,
chunked: bool,
n_batch_parts: u8,
x_of_n: u8,
batch_hash: Cow<'a, str>,
status: Cow<'a, str>,
dtf_spec: Cow<'a, str>,
priority: u16,
client_version: Cow<'a, str>,
server_version: Cow<'a, str>,
_prefix: Cow<'a, str>,
}
impl<'a> Default for GStorageOpMetadata<'a> {
fn default() -> Self {
GStorageOpMetadata {
op_type: GStorageOp::AddDtf,
chunked: false,
n_batch_parts: 1,
x_of_n: 1,
status: "ok".into(),
dtf_spec: "v1".into(),
priority: 0,
client_version: VERSION.unwrap_or("unknown").into(),
server_version: "?".into(),
_prefix: "".into(),
batch_hash: "".into(),
response_time: 0,
time_storage_class_updated: "".into(),
size: "".into(),
time_created: "".into(),
start_ts: 0,
finish_ts: 0,
bucket: "".into(),
id: "".into(),
self_link: "".into(),
name: "".into(),
metageneration: "".into(),
md5_hash: "".into(),
media_link: "".into(),
}
}
}
impl<'a> GStorageOpMetadata<'a> {
pub fn new(
resp: String,
start_ts: u32,
finish_ts: u32,
) -> Result<GStorageOpMetadata<'a>, Box<dyn error::Error>> {
let mut meta = GStorageOpMetadata::default();
let resp = from_str::<GStorageResp>(&resp)?;
meta.start_ts = start_ts;
meta.finish_ts = finish_ts;
meta.response_time = finish_ts - start_ts;
meta.id = resp.id;
meta.self_link = resp.self_link;
meta.name = resp.name;
meta.bucket = resp.bucket;
meta.metageneration = resp.metageneration;
meta.time_created = resp.time_created;
meta.time_storage_class_updated = resp.time_storage_class_updated;
meta.size = resp.size;
meta.md5_hash = resp.md5_hash.clone();
meta.media_link = resp.media_link;
meta.batch_hash = resp.md5_hash;
Ok(meta)
}
}
#[derive(Deserialize)]
struct GStorageResp<'a> {
id: Cow<'a, str>,
#[serde(rename = "selfLink")]
self_link: Cow<'a, str>,
name: Cow<'a, str>,
bucket: Cow<'a, str>,
metageneration: Cow<'a, str>,
#[serde(rename = "timeCreated")]
time_created: Cow<'a, str>,
#[serde(rename = "timeStorageClassUpdated")]
time_storage_class_updated: Cow<'a, str>,
size: Cow<'a, str>,
#[serde(rename = "md5Hash")]
md5_hash: Cow<'a, str>,
#[serde(rename = "mediaLink")]
media_link: Cow<'a, str>,
}
#[derive(Serialize)]
pub struct GStorageMetadata<'a, T: FileMetadata> {
meta: GStorageOpMetadata<'a>,
data: T,
}
impl<'a, T: FileMetadata> GStorageMetadata<'a, T> {
pub fn new(op_meta: GStorageOpMetadata<'a>, file_meta: T) -> GStorageMetadata<'a, T> {
GStorageMetadata {
meta: op_meta,
data: file_meta,
}
}
}
impl<'a, T: FileMetadata> Default for GStorageMetadata<'a, T> {
fn default() -> Self {
GStorageMetadata {
meta: Default::default(),
data: Default::default(),
}
}
}