use core::f32;
use std::time::{SystemTime, UNIX_EPOCH};
use ygw::{ArrayValue, PreparedCommand};
use crate::YgwError;
use self::ygw::{value, ParameterValue, Timestamp, Value};
pub mod ygw {
use std::fmt;
include!(concat!(env!("OUT_DIR"), "/yamcs.protobuf.ygw.rs"));
impl fmt::Display for PreparedCommand {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self)
}
}
}
impl From<f32> for Value {
fn from(item: f32) -> Self {
Value {
v: Some(value::V::FloatValue(item)),
}
}
}
impl From<f64> for Value {
fn from(item: f64) -> Self {
Value {
v: Some(value::V::DoubleValue(item)),
}
}
}
impl From<u32> for Value {
fn from(item: u32) -> Self {
Value {
v: Some(value::V::Uint32Value(item)),
}
}
}
impl From<i32> for Value {
fn from(item: i32) -> Self {
Value {
v: Some(value::V::Sint32Value(item)),
}
}
}
impl From<u64> for Value {
fn from(item: u64) -> Self {
Value {
v: Some(value::V::Uint64Value(item)),
}
}
}
impl From<i64> for Value {
fn from(item: i64) -> Self {
Value {
v: Some(value::V::Sint64Value(item)),
}
}
}
impl From<bool> for Value {
fn from(item: bool) -> Self {
Value {
v: Some(value::V::BooleanValue(item)),
}
}
}
impl From<String> for Value {
fn from(item: String) -> Self {
Value {
v: Some(value::V::StringValue(item)),
}
}
}
impl<T> From<&[T]> for Value
where
T: Into<Value> + Copy,
{
fn from(xarray: &[T]) -> Self {
let mut v: Vec<Value> = Vec::with_capacity(xarray.len());
for x in xarray {
v.push((*x).into());
}
Value {
v: Some(value::V::ArrayValue(ArrayValue { value: v })),
}
}
}
impl<T> From<Vec<T>> for Value
where
T: Into<Value>,
{
fn from(xarray: Vec<T>) -> Self {
let mut v: Vec<Value> = Vec::with_capacity(xarray.len());
for x in xarray {
v.push(x.into());
}
Value {
v: Some(value::V::ArrayValue(ArrayValue { value: v })),
}
}
}
impl TryFrom<Value> for f32 {
type Error = YgwError;
fn try_from(value: Value) -> Result<Self, Self::Error> {
match value.v {
Some(value::V::FloatValue(v)) => Ok(v),
_ => Err(YgwError::ConversionError(
format!("{:?}", value),
"f32".into(),
)),
}
}
}
impl TryFrom<Value> for f64 {
type Error = YgwError;
fn try_from(value: Value) -> Result<Self, Self::Error> {
match value.v {
Some(value::V::DoubleValue(v)) => Ok(v),
_ => Err(YgwError::ConversionError(
format!("{:?}", value),
"f64".into(),
)),
}
}
}
impl TryFrom<Value> for u32 {
type Error = YgwError;
fn try_from(value: Value) -> Result<Self, Self::Error> {
match value.v {
Some(value::V::Uint32Value(v)) => Ok(v),
_ => Err(YgwError::ConversionError(
format!("{:?}", value),
"u32".into(),
)),
}
}
}
impl TryFrom<Value> for Vec<u8> {
type Error = YgwError;
fn try_from(value: Value) -> Result<Self, Self::Error> {
match value.v {
Some(value::V::BinaryValue(v)) => Ok(v),
_ => Err(YgwError::ConversionError(
format!("{:?}", value),
"u32".into(),
)),
}
}
}
impl TryFrom<Value> for i32 {
type Error = YgwError;
fn try_from(value: Value) -> Result<Self, Self::Error> {
match value.v {
Some(value::V::Sint32Value(v)) => Ok(v),
_ => Err(YgwError::ConversionError(
format!("{:?}", value),
"i32".into(),
)),
}
}
}
impl TryFrom<Value> for u64 {
type Error = YgwError;
fn try_from(value: Value) -> Result<Self, Self::Error> {
match value.v {
Some(value::V::Uint64Value(v)) => Ok(v),
_ => Err(YgwError::ConversionError(
format!("{:?}", value),
"u64".into(),
)),
}
}
}
impl TryFrom<Value> for i64 {
type Error = YgwError;
fn try_from(value: Value) -> Result<Self, Self::Error> {
match value.v {
Some(value::V::Sint64Value(v)) => Ok(v),
_ => Err(YgwError::ConversionError(
format!("{:?}", value),
"i64".into(),
)),
}
}
}
impl TryFrom<Value> for bool {
type Error = YgwError;
fn try_from(value: Value) -> Result<Self, Self::Error> {
match value.v {
Some(value::V::BooleanValue(v)) => Ok(v),
_ => Err(YgwError::ConversionError(
format!("{:?}", value),
"bool".into(),
)),
}
}
}
impl TryFrom<Value> for String {
type Error = YgwError;
fn try_from(value: Value) -> Result<Self, Self::Error> {
match value.v {
Some(value::V::StringValue(v)) => Ok(v),
_ => Err(YgwError::ConversionError(
format!("{:?}", value),
"String".into(),
)),
}
}
}
impl<T> TryFrom<Value> for Vec<T>
where
T: TryFrom<Value, Error = YgwError>,
{
type Error = YgwError;
fn try_from(value: Value) -> Result<Self, Self::Error> {
match value.v {
Some(value::V::ArrayValue(array)) => {
let mut result = Vec::with_capacity(array.value.len());
for val in array.value {
result.push(T::try_from(val)?);
}
Ok(result)
}
_ => Err(YgwError::ConversionError(
format!("{:?}", value),
format!("Vec<{}>", std::any::type_name::<T>()),
)),
}
}
}
pub fn get_pv_eng<T>(id: u32, gentime: Option<Timestamp>, eng_value: T) -> ParameterValue
where
T: Into<Value>,
{
ParameterValue {
id,
raw_value: None,
eng_value: Some(get_value(eng_value)),
acquisition_time: None,
generation_time: gentime,
expire_millis: None,
}
}
pub fn get_value<T>(v: T) -> Value
where
T: Into<Value>,
{
v.into()
}
pub fn get_raw_arg<T: TryFrom<Value>>(pc: &PreparedCommand, arg_name: &str) -> Result<T, YgwError> {
for assignment in &pc.assignments {
if assignment.name == arg_name {
if let Some(ref value) = assignment.raw_value {
return T::try_from(value.clone()).map_err(|_| {
YgwError::CommandError(format!(
"Argument '{}' found but has incorrect type",
arg_name
))
});
}
return Err(YgwError::CommandError(format!(
"Argument '{}' found but has no raw value",
arg_name
)));
}
}
Err(YgwError::CommandError(format!(
"Argument '{}' not found",
arg_name
)))
}
pub fn get_eng_arg<T: TryFrom<Value>>(pc: &PreparedCommand, arg_name: &str) -> Result<T, YgwError> {
for assignment in &pc.assignments {
if assignment.name == arg_name {
if let Some(ref value) = assignment.eng_value {
return T::try_from(value.clone()).map_err(|_| {
YgwError::CommandError(format!(
"Argument '{}' found but has incorrect type",
arg_name
))
});
}
return Err(YgwError::CommandError(format!(
"Argument '{}' found but has no engineering value",
arg_name
)));
}
}
Err(YgwError::CommandError(format!(
"Argument '{}' not found",
arg_name
)))
}
pub fn now() -> Timestamp {
let start = SystemTime::now();
let since_the_epoch = start
.duration_since(UNIX_EPOCH)
.expect("Cannot use times before the unix epoch");
let millis =
since_the_epoch.as_secs() as i64 * 1000 + since_the_epoch.subsec_nanos() as i64 / 1_000_000;
let millis = millis + 37_000; let picos = (since_the_epoch.subsec_nanos() % 1_000_000) * 1000;
Timestamp { millis, picos }
}