use crate::{
prelude::{Error, Message},
utils::Utils,
};
use std::str::from_utf8;
#[derive(Debug, Clone, PartialEq)]
pub struct PositionEcef3d {
pub x_ecef_m: f64,
pub y_ecef_m: f64,
pub z_ecef_m: f64,
pub ellipsoid: String,
}
impl PositionEcef3d {
pub(crate) fn encoding_size(&self) -> usize {
let mut size = 24;
if !self.ellipsoid.eq("WGS84") {
let str_len = self.ellipsoid.len();
size += Message::bnxi_encoding_size(str_len as u32);
size += str_len;
} else {
size += 1;
}
size
}
pub(crate) fn encode(&self, big_endian: bool, buf: &mut [u8]) -> Result<usize, Error> {
let mut ptr = 0;
let size = self.encoding_size();
if buf.len() < size {
return Err(Error::NotEnoughBytes);
}
if self.ellipsoid.eq("WGS84") {
buf[ptr] = 0;
ptr += 1;
} else {
let str_len = self.ellipsoid.len();
let size = Message::encode_bnxi(str_len as u32, big_endian, &mut buf[ptr..])?;
ptr += size;
buf[ptr..ptr + str_len].copy_from_slice(self.ellipsoid.as_bytes());
ptr += str_len;
}
let bytes = if big_endian {
self.x_ecef_m.to_be_bytes()
} else {
self.x_ecef_m.to_le_bytes()
};
buf[ptr..ptr + 8].copy_from_slice(&bytes);
let bytes = if big_endian {
self.y_ecef_m.to_be_bytes()
} else {
self.y_ecef_m.to_le_bytes()
};
buf[ptr + 8..ptr + 16].copy_from_slice(&bytes);
let bytes = if big_endian {
self.z_ecef_m.to_be_bytes()
} else {
self.z_ecef_m.to_le_bytes()
};
buf[ptr + 16..ptr + 24].copy_from_slice(&bytes);
Ok(size)
}
pub(crate) fn decode(big_endian: bool, buf: &[u8]) -> Result<Self, Error> {
let buf_len = buf.len();
if buf_len < 2 {
return Err(Error::NotEnoughBytes);
}
let (str_len, mut ptr) = Message::decode_bnxi(buf, big_endian);
let str_len = str_len as usize;
let ellipsoid = if str_len == 0 {
"WGS84".to_string()
} else {
let ellipsoid_str =
from_utf8(&buf[ptr..ptr + str_len]).map_err(|_| Error::Utf8Error)?;
ellipsoid_str.to_string()
};
ptr += str_len;
if buf_len - str_len < 24 {
return Err(Error::NotEnoughBytes);
}
let x_ecef_m = Utils::decode_f64(big_endian, &buf[ptr..ptr + 8])?;
let y_ecef_m = Utils::decode_f64(big_endian, &buf[ptr + 8..ptr + 16])?;
let z_ecef_m = Utils::decode_f64(big_endian, &buf[ptr + 16..ptr + 24])?;
Ok(Self {
x_ecef_m,
y_ecef_m,
z_ecef_m,
ellipsoid,
})
}
pub fn new_wgs84(x_ecef_m: f64, y_ecef_m: f64, z_ecef_m: f64) -> Self {
Self {
x_ecef_m,
y_ecef_m,
z_ecef_m,
ellipsoid: "WGS84".to_string(),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Velocity3d {
pub x_m_s: f64,
pub y_m_s: f64,
pub z_m_s: f64,
}