rustyfit 0.10.0

The #![no_std] Rust implementation of The Flexible and Interoperable Data Transfer (FIT) Protocol for decoding and encoding Garmin FIT files, supporting FIT Protocol V2.
Documentation
// Code generated by fitgen/main.go. DO NOT EDIT.

// Copyright 2025 The RustyFIT Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

use core::fmt;
#[cfg(feature = "serde")]
use serde::{Deserialize, Deserializer, Serialize, Serializer, de, ser::SerializeStruct};

/// File type.
#[repr(transparent)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct File(pub u8);

impl File {
    /// Read only, single file. Must be in root directory.
    pub const DEVICE: File = File(1);
    /// Read/write, single file. Directory=Settings
    pub const SETTINGS: File = File(2);
    /// Read/write, multiple files, file number = sport type. Directory=Sports
    pub const SPORT: File = File(3);
    /// Read/erase, multiple files. Directory=Activities
    pub const ACTIVITY: File = File(4);
    /// Read/write/erase, multiple files. Directory=Workouts
    pub const WORKOUT: File = File(5);
    /// Read/write/erase, multiple files. Directory=Courses
    pub const COURSE: File = File(6);
    /// Read/write, single file. Directory=Schedules
    pub const SCHEDULES: File = File(7);
    /// Read only, single file. Circular buffer. All message definitions at start of file. Directory=Weight
    pub const WEIGHT: File = File(9);
    /// Read only, single file. Directory=Totals
    pub const TOTALS: File = File(10);
    /// Read/write, single file. Directory=Goals
    pub const GOALS: File = File(11);
    /// Read only. Directory=Blood Pressure
    pub const BLOOD_PRESSURE: File = File(14);
    /// Read only. Directory=Monitoring. File number=sub type.
    pub const MONITORING_A: File = File(15);
    /// Read/erase, multiple files. Directory=Activities
    pub const ACTIVITY_SUMMARY: File = File(20);
    pub const MONITORING_DAILY: File = File(28);
    /// Read only. Directory=Monitoring. File number=identifier
    pub const MONITORING_B: File = File(32);
    /// Read/write/erase. Multiple Files. Directory=Segments
    pub const SEGMENT: File = File(34);
    /// Read/write/erase. Single File. Directory=Segments
    pub const SEGMENT_LIST: File = File(35);
    /// Read/write/erase. Single File. Directory=Settings
    pub const EXD_CONFIGURATION: File = File(40);
    /// 0xF7 - 0xFE reserved for manufacturer specific file types
    pub const MFG_RANGE_MIN: File = File(0xF7);
    /// 0xF7 - 0xFE reserved for manufacturer specific file types
    pub const MFG_RANGE_MAX: File = File(0xFE);

    fn as_str(self) -> Option<&'static str> {
        match self.0 {
            1 => Some("device"),
            2 => Some("settings"),
            3 => Some("sport"),
            4 => Some("activity"),
            5 => Some("workout"),
            6 => Some("course"),
            7 => Some("schedules"),
            9 => Some("weight"),
            10 => Some("totals"),
            11 => Some("goals"),
            14 => Some("blood_pressure"),
            15 => Some("monitoring_a"),
            20 => Some("activity_summary"),
            28 => Some("monitoring_daily"),
            32 => Some("monitoring_b"),
            34 => Some("segment"),
            35 => Some("segment_list"),
            40 => Some("exd_configuration"),
            0xF7 => Some("mfg_range_min"),
            0xFE => Some("mfg_range_max"),
            _ => None,
        }
    }
}

impl Default for File {
    fn default() -> Self {
        Self(u8::MAX)
    }
}

impl fmt::Display for File {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self.as_str() {
            Some(s) => write!(f, "{}", s),
            None => write!(f, "File({})", self.0),
        }
    }
}

#[cfg(feature = "serde")]
impl Serialize for File {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut state = serializer.serialize_struct("File", 2)?;
        if let Some(s) = self.as_str() {
            state.serialize_field("t", s)?;
        }
        state.serialize_field("c", &self.0)?;
        state.end()
    }
}

#[cfg(feature = "serde")]
#[cfg_attr(feature = "serde", derive(Deserialize))]
struct De<'a> {
    #[serde(skip_serializing_if = "Option::is_none")]
    t: Option<&'a str>,
    c: u8,
}

#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for File {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let repr = De::deserialize(deserializer)?;
        let v = Self(repr.c);
        if let Some(t) = repr.t
            && let Some(s) = v.as_str()
            && t != s
        {
            return Err(de::Error::custom("tag and content mismatch"));
        }
        Ok(v)
    }
}