doris-rs 0.1.0

DORIS RINEX file parsing and production
Documentation
use crate::{error::ParsingError, fmt_doris, prelude::FormattingError};

use std::{
    io::{BufWriter, Write},
    str::FromStr,
};

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

/// GNSS receiver description
#[derive(Default, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Receiver {
    /// Receiver (hardware) model
    pub model: String,

    /// Receiver (hardware) identification info
    pub serial_number: String,

    /// Receiver embedded software info
    pub firmware: String,
}

impl Receiver {
    /// Formats [Receiver] into [BufWriter]
    pub(crate) fn format<W: Write>(&self, w: &mut BufWriter<W>) -> Result<(), FormattingError> {
        writeln!(
            w,
            "{}",
            fmt_doris(
                &format!(
                    "{:<20}{:<20}{}",
                    self.serial_number, self.model, self.firmware
                ),
                "REC # / TYPE / VERS"
            )
        )?;

        Ok(())
    }

    pub fn with_model(&self, model: &str) -> Self {
        let mut s = self.clone();
        s.model = model.to_string();
        s
    }

    pub fn with_serial_number(&self, serial_number: &str) -> Self {
        let mut s = self.clone();
        s.serial_number = serial_number.to_string();
        s
    }

    pub fn with_firmware(&self, firmware: &str) -> Self {
        let mut s = self.clone();
        s.firmware = firmware.to_string();
        s
    }
}

impl FromStr for Receiver {
    type Err = ParsingError;

    fn from_str(line: &str) -> Result<Self, Self::Err> {
        if line.len() < 60 {
            return Err(ParsingError::Receiver);
        }

        let (sn, rem) = line.split_at(20);
        let (model, rem) = rem.split_at(20);
        let (version, _) = rem.split_at(20);

        Ok(Receiver {
            serial_number: sn.trim().to_string(),
            model: model.trim().to_string(),
            firmware: version.trim().to_string(),
        })
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::str::FromStr;

    #[test]
    fn receiver_parsing() {
        let content = "2090088             LEICA GR50          4.51                ";

        let rcvr = Receiver::from_str(content).unwrap();
        assert_eq!(rcvr.model, "LEICA GR50");
        assert_eq!(rcvr.firmware, "4.51");
        assert_eq!(rcvr.serial_number, "2090088");
    }
}