use crate::{
message::{record::monument::FieldID, Message},
Error,
};
<<<<<<< HEAD
#[derive(Debug, Clone, PartialEq)]
pub enum MonumentGeoFrame {
Comment(String),
SoftwareName(String),
AgencyName(String),
OperatorName(String),
SiteLocation(String),
SiteNumber(String),
SiteName(String),
SiteOperator(String),
SiteOperatorContact(String),
SiteOperatorAgency(String),
ObserverName(String),
ObserverContact(String),
MarkerName(String),
MonumentName(String),
MonumentNumber(String),
MarkerNumber(String),
ProjectName(String),
ReferenceName(String),
ReferenceDate(String),
ReferenceNumber(String),
Climatic(String),
Geophysical(String),
AntennaType(String),
AntennaRadomeType(String),
AntennaMount(String),
AntennaNumber(String),
AntennaRadomeNumber(String),
ReceiverFirmwareVersion(String),
ReceiverType(String),
ReceiverNumber(String),
UserID(String),
Extra(String),
}
impl MonumentGeoFrame {
pub(crate) fn encoding_size(&self) -> usize {
match self {
Self::Comment(s)
| Self::ReferenceDate(s)
| Self::ReferenceName(s)
| Self::ReferenceNumber(s)
| Self::SiteNumber(s)
| Self::SiteOperator(s)
| Self::SiteOperatorAgency(s)
| Self::SiteOperatorContact(s)
| Self::Extra(s)
| Self::SiteLocation(s)
| Self::SiteName(s)
| Self::ReceiverFirmwareVersion(s)
| Self::ReceiverNumber(s)
| Self::ReceiverType(s)
| Self::ObserverContact(s)
| Self::ObserverName(s)
| Self::MonumentName(s)
| Self::MonumentNumber(s)
| Self::ProjectName(s)
| Self::MarkerName(s)
| Self::MarkerNumber(s)
| Self::SoftwareName(s)
| Self::Geophysical(s)
| Self::Climatic(s)
| Self::AntennaType(s)
| Self::AntennaMount(s)
| Self::AntennaRadomeType(s)
| Self::AntennaRadomeNumber(s)
| Self::AntennaNumber(s)
| Self::OperatorName(s)
| Self::UserID(s)
| Self::AgencyName(s) => {
let s_len = s.len();
s_len + 1 + Message::bnxi_encoding_size(s_len as u32) },
}
}
pub(crate) fn to_field_id(&self) -> FieldID {
match self {
Self::Comment(_) => FieldID::Comment,
Self::OperatorName(_) => FieldID::OperatorName,
Self::SiteLocation(_) => FieldID::SiteLocation,
Self::SiteOperator(_) => FieldID::SiteOperator,
Self::SiteOperatorAgency(_) => FieldID::SiteOperatorAgency,
Self::SiteOperatorContact(_) => FieldID::SiteOperatorContact,
Self::SiteName(_) => FieldID::SiteName,
Self::MonumentName(_) => FieldID::MonumentName,
Self::MonumentNumber(_) => FieldID::MonumentNumber,
Self::ProjectName(_) => FieldID::ProjectName,
Self::MarkerName(_) => FieldID::MarkerName,
Self::MarkerNumber(_) => FieldID::MarkerNumber,
Self::ObserverContact(_) => FieldID::ObserverContact,
Self::ObserverName(_) => FieldID::ObserverName,
Self::Extra(_) => FieldID::Extra,
Self::UserID(_) => FieldID::UserID,
Self::Climatic(_) => FieldID::Climatic,
Self::Geophysical(_) => FieldID::Geophysical,
Self::SoftwareName(_) => FieldID::SoftwareName,
Self::AgencyName(_) => FieldID::AgencyName,
Self::AntennaType(_) => FieldID::AntennaType,
Self::AntennaMount(_) => FieldID::AntennaMount,
Self::AntennaNumber(_) => FieldID::AntennaNumber,
Self::AntennaRadomeType(_) => FieldID::AntennaRadomeType,
Self::AntennaRadomeNumber(_) => FieldID::AntennaRadomeNumber,
Self::ReceiverFirmwareVersion(_) => FieldID::ReceiverFirmwareVersion,
Self::ReceiverNumber(_) => FieldID::ReceiverNumber,
Self::ReceiverType(_) => FieldID::ReceiverType,
Self::SiteNumber(_) => FieldID::SiteNumber,
Self::ReferenceDate(_) => FieldID::ReferenceDate,
Self::ReferenceName(_) => FieldID::ReferenceName,
Self::ReferenceNumber(_) => FieldID::ReferenceNumber,
}
}
pub(crate) fn decode(big_endian: bool, buf: &[u8]) -> Result<Self, Error> {
if buf.len() < 2 {
return Err(Error::NotEnoughBytes);
}
let (fid, mut ptr) = Message::decode_bnxi(&buf, big_endian);
let fid = FieldID::from(fid);
match fid {
FieldID::Comment
| FieldID::AntennaNumber
| FieldID::AntennaType
| FieldID::AntennaMount
| FieldID::AntennaRadomeNumber
| FieldID::AntennaRadomeType
| FieldID::AgencyName
| FieldID::Climatic
| FieldID::Geophysical
| FieldID::MonumentName
| FieldID::MonumentNumber
| FieldID::MarkerName
| FieldID::MarkerNumber
| FieldID::ObserverContact
| FieldID::ObserverName
| FieldID::ProjectName
| FieldID::SiteLocation
| FieldID::ReceiverFirmwareVersion
| FieldID::ReceiverType
| FieldID::ReceiverNumber
| FieldID::Extra => {
if buf.len() < 1 + ptr {
return Err(Error::NotEnoughBytes);
}
let (s_len, size) = Message::decode_bnxi(&buf[ptr..], big_endian);
let s_len = s_len as usize;
ptr += size;
if buf.len() - ptr < s_len {
return Err(Error::NotEnoughBytes); }
match std::str::from_utf8(&buf[ptr..ptr + s_len]) {
Ok(s) => match fid {
FieldID::Comment => Ok(Self::Comment(s.to_string())),
FieldID::MonumentName => Ok(Self::MonumentName(s.to_string())),
FieldID::MonumentNumber => Ok(Self::MonumentNumber(s.to_string())),
FieldID::ProjectName => Ok(Self::ProjectName(s.to_string())),
FieldID::ObserverName => Ok(Self::ObserverName(s.to_string())),
FieldID::ObserverContact => Ok(Self::ObserverContact(s.to_string())),
FieldID::SoftwareName => Ok(Self::SoftwareName(s.to_string())),
FieldID::MarkerName => Ok(Self::MarkerName(s.to_string())),
FieldID::MarkerNumber => Ok(Self::MarkerNumber(s.to_string())),
FieldID::Extra => Ok(Self::Extra(s.to_string())),
FieldID::Climatic => Ok(Self::Climatic(s.to_string())),
FieldID::Geophysical => Ok(Self::Geophysical(s.to_string())),
FieldID::AgencyName => Ok(Self::AgencyName(s.to_string())),
FieldID::AntennaType => Ok(Self::AntennaType(s.to_string())),
FieldID::AntennaMount => Ok(Self::AntennaMount(s.to_string())),
FieldID::AntennaNumber => Ok(Self::AntennaNumber(s.to_string())),
FieldID::AntennaRadomeType => Ok(Self::AntennaRadomeType(s.to_string())),
FieldID::AntennaRadomeNumber => {
Ok(Self::AntennaRadomeNumber(s.to_string()))
},
FieldID::ReceiverFirmwareVersion => {
Ok(Self::ReceiverFirmwareVersion(s.to_string()))
},
FieldID::ReceiverNumber => Ok(Self::ReceiverNumber(s.to_string())),
FieldID::ReceiverType => Ok(Self::ReceiverType(s.to_string())),
FieldID::OperatorName => Ok(Self::OperatorName(s.to_string())),
FieldID::SiteLocation => Ok(Self::SiteLocation(s.to_string())),
FieldID::SiteName => Ok(Self::SiteName(s.to_string())),
FieldID::SiteNumber => Ok(Self::SiteNumber(s.to_string())),
FieldID::ReferenceDate => Ok(Self::ReferenceDate(s.to_string())),
FieldID::ReferenceName => Ok(Self::ReferenceName(s.to_string())),
FieldID::ReferenceNumber => Ok(Self::ReferenceNumber(s.to_string())),
FieldID::UserID => Ok(Self::UserID(s.to_string())),
FieldID::SiteOperator => Ok(Self::SiteOperator(s.to_string())),
FieldID::SiteOperatorAgency => Ok(Self::SiteOperatorAgency(s.to_string())),
FieldID::SiteOperatorContact => {
Ok(Self::SiteOperatorContact(s.to_string()))
},
FieldID::AntennaEcef3D
| FieldID::Geocode
| FieldID::AntennaOffset3D
| FieldID::AntennaGeo3D
| FieldID::Unknown => Err(Error::UnknownMessage),
},
Err(e) => Err(Error::Utf8Error),
}
},
_ => Err(Error::UnknownRecordFieldId),
}
}
pub fn encode(&self, big_endian: bool, buf: &mut [u8]) -> Result<usize, Error> {
let size = self.encoding_size();
if buf.len() < size {
return Err(Error::NotEnoughBytes);
}
let fid = self.to_field_id() as u32;
let mut ptr = Message::encode_bnxi(fid, big_endian, buf)?;
match self {
Self::Comment(s)
| Self::UserID(s)
| Self::SiteOperator(s)
| Self::SiteOperatorAgency(s)
| Self::OperatorName(s)
| Self::SiteLocation(s)
| Self::SiteOperatorContact(s)
| Self::SiteNumber(s)
| Self::ObserverName(s)
| Self::ProjectName(s)
| Self::ReferenceName(s)
| Self::MonumentNumber(s)
| Self::ReferenceDate(s)
| Self::ReferenceNumber(s)
| Self::ObserverContact(s)
| Self::MonumentName(s)
| Self::SiteName(s)
| Self::Extra(s)
| Self::SoftwareName(s)
| Self::Climatic(s)
| Self::Geophysical(s)
| Self::AgencyName(s)
| Self::MarkerName(s)
| Self::MarkerNumber(s)
| Self::ReceiverFirmwareVersion(s)
| Self::ReceiverNumber(s)
| Self::ReceiverType(s)
| Self::AntennaType(s)
| Self::AntennaNumber(s)
| Self::AntennaMount(s)
| Self::AntennaRadomeType(s)
| Self::AntennaRadomeNumber(s) => {
let s_len = s.len();
let size = Message::encode_bnxi(s_len as u32, big_endian, &mut buf[ptr..])?;
ptr += size;
buf[ptr..ptr + s_len].clone_from_slice(s.as_bytes()); },
}
Ok(size)
}
}
=======
>>>>>>> binex
#[cfg(test)]
mod test {
use super::*;
#[test]
fn geo_comments() {
let frame = MonumentGeoFrame::Comment("Hello".to_string());
assert_eq!(frame.encoding_size(), 5 + 2);
let big_endian = true;
let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
let size = frame.encode(big_endian, &mut buf).unwrap();
assert_eq!(size, frame.encoding_size());
assert_eq!(
buf,
[0, 5, 'H' as u8, 'e' as u8, 'l' as u8, 'l' as u8, 'o' as u8, 0, 0, 0, 0, 0, 0]
);
let decoded = MonumentGeoFrame::decode(big_endian, &buf).unwrap();
assert_eq!(decoded, frame);
}
#[test]
fn geo_climatic() {
let frame = MonumentGeoFrame::Climatic("ABC".to_string());
assert_eq!(frame.encoding_size(), 3 + 2);
let big_endian = true;
let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
let size = frame.encode(big_endian, &mut buf).unwrap();
assert_eq!(size, frame.encoding_size());
assert_eq!(
buf,
[14, 3, 'A' as u8, 'B' as u8, 'C' as u8, 0, 0, 0, 0, 0, 0]
);
let decoded = MonumentGeoFrame::decode(big_endian, &buf).unwrap();
assert_eq!(decoded, frame);
}
}