Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

messages: Parse enum types #40

Open
wants to merge 1 commit into
base: feature/13-add-data-types-for-messages
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 48 additions & 45 deletions fitparser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,11 @@ impl FitDataField {
pub fn into_value(self) -> Value {
self.value
}

/// Consume the field and return the value with associated units
pub fn into_value_with_units(self) -> ValueWithUnits {
ValueWithUnits::new(self.value, self.units)
}
}

impl fmt::Display for FitDataField {
Expand Down Expand Up @@ -326,7 +331,7 @@ impl convert::TryInto<i64> for &Value {
/// Describes a field value along with its defined units (if any), this struct is useful for
/// serializing data in a key-value store where the key is either the name or definition number
/// since it can be created from a `FitDataField` with minimal data cloning.
#[derive(Clone, Debug, Serialize)]
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize)]
pub struct ValueWithUnits {
value: Value,
units: String,
Expand All @@ -337,6 +342,16 @@ impl ValueWithUnits {
pub fn new(value: Value, units: String) -> Self {
ValueWithUnits { value, units }
}

/// Return a reference to the stored value
pub fn value(&self) -> &Value {
&self.value
}

/// Return units associated with the value
pub fn units(&self) -> &str {
&self.units
}
}

impl convert::From<FitDataField> for ValueWithUnits {
Expand All @@ -361,104 +376,104 @@ mod tests {
use super::*;
use std::collections::HashSet;

fn validate_records(records: Vec<FitDataRecord>, ignore_unexpected_fields: bool) {
let mut options = MessageParseOptions::default();
options.ignore_unexpected_fields = ignore_unexpected_fields;
for record in records {
validate_record(record, options);
}
}

fn validate_record(record: FitDataRecord, options: MessageParseOptions) {
if !MesgNum::is_named_variant(record.kind().as_i64()) {
return;
}
let message = Message::parse_with_options(record, options).unwrap();
assert!(
message.invalid_fields().is_empty(),
"{:?}",
message.invalid_fields()
);
}

#[test]
fn parse_activity() {
let data = include_bytes!("../tests/fixtures/Activity.fit").to_vec();
let fit_data = from_bytes(&data).unwrap();
assert_eq!(fit_data.len(), 22);
for record in fit_data {
assert!(Message::parse(record).is_ok());
}
validate_records(fit_data, false);
}

#[test]
fn parse_developer_data() {
let data = include_bytes!("../tests/fixtures/DeveloperData.fit").to_vec();
let fit_data = from_bytes(&data).unwrap();
assert_eq!(fit_data.len(), 6);
for record in fit_data {
assert!(Message::parse(record).is_ok());
}
validate_records(fit_data, false);
}

#[test]
fn parse_monitoring_file() {
let data = include_bytes!("../tests/fixtures/MonitoringFile.fit").to_vec();
let fit_data = from_bytes(&data).unwrap();
assert_eq!(fit_data.len(), 355);
for record in fit_data {
assert!(Message::parse(record).is_ok());
}
validate_records(fit_data, false);
}

#[test]
fn parse_settings() {
let data = include_bytes!("../tests/fixtures/Settings.fit").to_vec();
let fit_data = from_bytes(&data).unwrap();
assert_eq!(fit_data.len(), 3);
for record in fit_data {
assert!(Message::parse(record).is_ok());
}
validate_records(fit_data, false);
}

#[test]
fn parse_weight_scale_multi_user() {
let data = include_bytes!("../tests/fixtures/WeightScaleMultiUser.fit").to_vec();
let fit_data = from_bytes(&data).unwrap();
assert_eq!(fit_data.len(), 7);
for record in fit_data {
assert!(Message::parse(record).is_ok());
}
validate_records(fit_data, false);
}

#[test]
fn parse_weight_scale_single_user() {
let data = include_bytes!("../tests/fixtures/WeightScaleSingleUser.fit").to_vec();
let fit_data = from_bytes(&data).unwrap();
assert_eq!(fit_data.len(), 6);
for record in fit_data {
assert!(Message::parse(record).is_ok());
}
validate_records(fit_data, false);
}

#[test]
fn parse_workout_custom_target_values() {
let data = include_bytes!("../tests/fixtures/WorkoutCustomTargetValues.fit").to_vec();
let fit_data = from_bytes(&data).unwrap();
assert_eq!(fit_data.len(), 6);
for record in fit_data {
assert!(Message::parse(record).is_ok());
}
validate_records(fit_data, false);
}

#[test]
fn parse_workout_individual_steps() {
let data = include_bytes!("../tests/fixtures/WorkoutIndividualSteps.fit").to_vec();
let fit_data = from_bytes(&data).unwrap();
assert_eq!(fit_data.len(), 6);
for record in fit_data {
assert!(Message::parse(record).is_ok());
}
validate_records(fit_data, false);
}

#[test]
fn parse_workout_repeat_greater_than_step() {
let data = include_bytes!("../tests/fixtures/WorkoutRepeatGreaterThanStep.fit").to_vec();
let fit_data = from_bytes(&data).unwrap();
assert_eq!(fit_data.len(), 7);
for record in fit_data {
assert!(Message::parse(record).is_ok());
}
validate_records(fit_data, false);
}

#[test]
fn parse_workout_repeat_steps() {
let data = include_bytes!("../tests/fixtures/WorkoutRepeatSteps.fit").to_vec();
let fit_data = from_bytes(&data).unwrap();
assert_eq!(fit_data.len(), 7);
for record in fit_data {
assert!(Message::parse(record).is_ok());
}
validate_records(fit_data, false);
}

#[test]
Expand All @@ -468,13 +483,7 @@ mod tests {
let data = include_bytes!("../tests/fixtures/garmin-fenix-5-bike.fit").to_vec();
let fit_data = from_bytes(&data).unwrap();
assert_eq!(fit_data.len(), 143);
let mut options = MessageParseOptions::default();
options.ignore_unexpected_fields = true;
for record in fit_data {
if MesgNum::is_named_variant(record.kind().as_i64()) {
assert!(Message::parse_with_options(record, options).is_ok());
}
}
validate_records(fit_data, true);
}

#[test]
Expand All @@ -483,13 +492,7 @@ mod tests {
let data = include_bytes!("../tests/fixtures/sample_mulitple_header.fit").to_vec();
let fit_data = from_bytes(&data).unwrap();
assert_eq!(fit_data.len(), 3023);
let mut options = MessageParseOptions::default();
options.ignore_unexpected_fields = true;
for record in fit_data {
if MesgNum::is_named_variant(record.kind().as_i64()) {
assert!(Message::parse_with_options(record, options).is_ok());
}
}
validate_records(fit_data, true);
}

#[test]
Expand Down
Loading
Loading