use crate::error::{ErrorKind, Result};
use crate::FitDataRecord;
use nom::number::complete::le_u16;
use std::collections::HashMap;
use std::io::Read;
use std::rc::Rc;
mod crc;
use crc::{caculate_crc, update_crc};
mod decode;
use decode::Decoder;
mod parser;
pub use parser::{FitDataMessage, FitDefinitionMessage, FitFileHeader};
#[derive(Clone, Debug)]
pub enum FitObject {
Crc(u16),
Header(FitFileHeader),
DataMessage(FitDataMessage),
DefinitionMessage(Rc<FitDefinitionMessage>),
}
struct Deserializer {
definitions: HashMap<u8, Rc<parser::FitDefinitionMessage>>,
position: usize,
end_of_messages: usize,
crc: u16,
}
impl Deserializer {
fn new() -> Self {
Deserializer {
definitions: HashMap::new(),
position: 0,
end_of_messages: 0,
crc: 0,
}
}
fn reset(&mut self) {
self.crc = 0;
self.definitions = HashMap::new();
}
fn deserialize_next<'de>(&mut self, input: &'de [u8]) -> Result<(&'de [u8], FitObject)> {
if self.position > 0 && self.position == self.end_of_messages {
return self.deserialize_crc(input);
}
if self.position == 0 || (self.position > self.end_of_messages && !input.is_empty()) {
return self.deserialize_header(input);
}
self.deserialize_message(input)
}
fn deserialize_header<'de>(&mut self, input: &'de [u8]) -> Result<(&'de [u8], FitObject)> {
let (remaining, header) =
parser::fit_file_header(input).map_err(|e| self.to_parse_err(e))?;
self.end_of_messages =
self.position + header.header_size() as usize + header.data_size() as usize;
self.position += header.header_size() as usize;
self.crc = 0;
if let Some(value) = header.crc() {
let checksum = caculate_crc(&input[0..(header.header_size() - 2) as usize]);
if checksum != value {
return Err(Box::new(ErrorKind::InvalidCrc((
Vec::from(remaining),
FitObject::Header(header),
value,
checksum,
))));
}
} else {
self.crc = update_crc(0, &input[0..(header.header_size() as usize)]);
}
Ok((remaining, FitObject::Header(header)))
}
fn deserialize_crc<'de>(&mut self, input: &'de [u8]) -> Result<(&'de [u8], FitObject)> {
let (input, crc) = le_u16(input).map_err(|e| self.to_parse_err(e))?;
self.position += 2;
if crc != self.crc {
return Err(Box::new(ErrorKind::InvalidCrc((
Vec::from(input),
FitObject::Crc(crc),
crc,
self.crc,
))));
}
Ok((input, FitObject::Crc(crc)))
}
fn deserialize_message<'de>(&mut self, input: &'de [u8]) -> Result<(&'de [u8], FitObject)> {
let init_len = input.len();
let (remaining, message) =
parser::fit_message(input, &self.definitions).map_err(|e| self.to_parse_err(e))?;
self.crc = update_crc(self.crc, &input[0..(input.len() - remaining.len())]);
match message {
parser::FitMessage::Data(message) => {
self.position += init_len - remaining.len();
Ok((remaining, FitObject::DataMessage(message)))
}
parser::FitMessage::Definition(message) => {
let msg_rc = Rc::new(message);
self.definitions
.insert(msg_rc.local_message_number(), Rc::clone(&msg_rc));
self.position += init_len - remaining.len();
Ok((remaining, FitObject::DefinitionMessage(msg_rc)))
}
parser::FitMessage::MissingDefinitionMessage(n) => {
Err(ErrorKind::MissingDefinitionMessage(n, self.position).into())
}
}
}
fn to_parse_err(&self, err: nom::Err<(&[u8], nom::error::ErrorKind)>) -> crate::Error {
match err {
nom::Err::Error((_, kind)) => ErrorKind::ParseError(self.position, kind).into(),
nom::Err::Failure((_, kind)) => ErrorKind::ParseError(self.position, kind).into(),
nom::Err::Incomplete(needed) => ErrorKind::UnexpectedEof(needed).into(),
}
}
}
pub struct FitStreamProcessor {
decoder: Decoder,
deserializer: Deserializer,
}
impl Default for FitStreamProcessor {
fn default() -> Self {
FitStreamProcessor {
decoder: Decoder::new(),
deserializer: Deserializer::new(),
}
}
}
impl FitStreamProcessor {
pub fn new() -> Self {
Self::default()
}
pub fn reset(&mut self) {
self.decoder.reset();
self.deserializer.reset();
}
pub fn deserialize_next<'de>(&mut self, input: &'de [u8]) -> Result<(&'de [u8], FitObject)> {
self.deserializer.deserialize_next(input)
}
pub fn decode_message(&mut self, msg: FitDataMessage) -> Result<FitDataRecord> {
self.decoder.decode_message(msg)
}
}
pub fn from_bytes(mut buffer: &[u8]) -> Result<Vec<FitDataRecord>> {
let mut processor = FitStreamProcessor::new();
let mut records = Vec::new();
while !buffer.is_empty() {
let (buf, obj) = processor.deserialize_next(buffer)?;
match obj {
FitObject::Crc(..) => processor.reset(),
FitObject::Header(..) => {}
FitObject::DataMessage(msg) => records.push(processor.decode_message(msg)?),
FitObject::DefinitionMessage(..) => {}
}
buffer = buf;
}
Ok(records)
}
pub fn from_reader<T: Read>(source: &mut T) -> Result<Vec<FitDataRecord>> {
let mut buffer = Vec::new();
source.read_to_end(&mut buffer)?;
from_bytes(&buffer)
}