use std::time::{Duration, SystemTime, UNIX_EPOCH};
use crate::generated::google::rpc::Status;
use crate::rpc_support::RpcStatus;
pub(crate) fn from_wire_status(value: Status) -> RpcStatus {
RpcStatus {
code: value.code,
message: value.message,
}
}
pub(crate) fn to_wire_timestamp(value: SystemTime) -> prost_types::Timestamp {
match value.duration_since(UNIX_EPOCH) {
Ok(elapsed) => prost_types::Timestamp {
seconds: elapsed.as_secs() as i64,
nanos: elapsed.subsec_nanos() as i32,
},
Err(err) => {
let before = err.duration();
let mut seconds = -(before.as_secs() as i64);
let mut nanos = before.subsec_nanos() as i32;
if nanos > 0 {
seconds -= 1;
nanos = 1_000_000_000 - nanos;
}
prost_types::Timestamp { seconds, nanos }
}
}
}
pub(crate) fn from_wire_timestamp(value: prost_types::Timestamp) -> SystemTime {
let nanos = value.nanos.clamp(0, 999_999_999) as u32;
if value.seconds >= 0 {
UNIX_EPOCH
.checked_add(Duration::new(value.seconds as u64, nanos))
.unwrap_or(UNIX_EPOCH)
} else {
UNIX_EPOCH
.checked_sub(Duration::new(value.seconds.unsigned_abs(), 0))
.and_then(|time| time.checked_add(Duration::new(0, nanos)))
.unwrap_or(UNIX_EPOCH)
}
}
pub(crate) fn to_wire_duration(value: Duration) -> prost_types::Duration {
prost_types::Duration {
seconds: i64::try_from(value.as_secs()).unwrap_or(i64::MAX),
nanos: value.subsec_nanos() as i32,
}
}
pub(crate) fn to_wire_struct(
value: serde_json::Map<String, serde_json::Value>,
) -> prost_types::Struct {
prost_types::Struct {
fields: value
.into_iter()
.map(|(key, item)| (key, to_wire_value(item)))
.collect(),
}
}
pub(crate) fn from_wire_struct(
value: prost_types::Struct,
) -> serde_json::Map<String, serde_json::Value> {
value
.fields
.into_iter()
.map(|(key, item)| (key, from_wire_value(item)))
.collect()
}
pub(crate) fn to_wire_value(value: serde_json::Value) -> prost_types::Value {
use prost_types::value::Kind;
let kind = match value {
serde_json::Value::Null => Kind::NullValue(prost_types::NullValue::NullValue as i32),
serde_json::Value::Bool(item) => Kind::BoolValue(item),
serde_json::Value::Number(item) => Kind::NumberValue(item.as_f64().unwrap_or(0.0)),
serde_json::Value::String(item) => Kind::StringValue(item),
serde_json::Value::Array(items) => Kind::ListValue(prost_types::ListValue {
values: items.into_iter().map(to_wire_value).collect(),
}),
serde_json::Value::Object(items) => Kind::StructValue(to_wire_struct(items)),
};
prost_types::Value { kind: Some(kind) }
}
pub(crate) fn from_wire_value(value: prost_types::Value) -> serde_json::Value {
use prost_types::value::Kind;
match value.kind {
None | Some(Kind::NullValue(_)) => serde_json::Value::Null,
Some(Kind::BoolValue(item)) => serde_json::Value::Bool(item),
Some(Kind::NumberValue(item)) => serde_json::Number::from_f64(item)
.map_or(serde_json::Value::Null, serde_json::Value::Number),
Some(Kind::StringValue(item)) => serde_json::Value::String(item),
Some(Kind::ListValue(items)) => {
serde_json::Value::Array(items.values.into_iter().map(from_wire_value).collect())
}
Some(Kind::StructValue(items)) => serde_json::Value::Object(from_wire_struct(items)),
}
}