nhl_api/types/
common.rs

1use serde::{Deserialize, Serialize};
2use std::fmt;
3
4/// Localized string (NHL API returns {default: "value"})
5#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
6pub struct LocalizedString {
7    pub default: String,
8}
9
10/// Conference information for a team
11#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
12pub struct Conference {
13    pub abbr: String,
14    pub name: String,
15}
16
17/// Division information for a team
18#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
19pub struct Division {
20    pub abbr: String,
21    pub name: String,
22}
23
24/// NHL Team information
25#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
26pub struct Team {
27    pub name: String,
28    pub common_name: String,
29    pub abbr: String,
30    pub logo: String,
31    pub conference: Conference,
32    pub division: Division,
33    #[serde(skip_serializing_if = "Option::is_none")]
34    pub franchise_id: Option<i64>,
35}
36
37impl fmt::Display for Team {
38    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39        write!(f, "{} ({})", self.name, self.abbr)
40    }
41}
42
43/// Franchise information
44#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
45pub struct Franchise {
46    pub id: i64,
47    #[serde(rename = "fullName")]
48    pub full_name: String,
49    #[serde(rename = "teamCommonName")]
50    pub team_common_name: Option<String>,
51}
52
53/// Response from the franchises endpoint
54#[derive(Debug, Clone, Serialize, Deserialize)]
55pub struct FranchisesResponse {
56    pub data: Vec<Franchise>,
57}
58
59/// Team roster information
60/// Team roster with players by position
61#[derive(Debug, Clone, Serialize, Deserialize)]
62pub struct Roster {
63    #[serde(default)]
64    pub forwards: Vec<RosterPlayer>,
65    #[serde(default)]
66    pub defensemen: Vec<RosterPlayer>,
67    #[serde(default)]
68    pub goalies: Vec<RosterPlayer>,
69}
70
71/// Individual player in a team roster
72#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
73pub struct RosterPlayer {
74    pub id: i64,
75    pub headshot: String,
76    #[serde(rename = "firstName")]
77    pub first_name: LocalizedString,
78    #[serde(rename = "lastName")]
79    pub last_name: LocalizedString,
80    #[serde(rename = "sweaterNumber")]
81    pub sweater_number: i32,
82    #[serde(rename = "positionCode")]
83    pub position_code: String,
84    #[serde(rename = "shootsCatches")]
85    pub shoots_catches: String,
86    #[serde(rename = "heightInInches")]
87    pub height_in_inches: i32,
88    #[serde(rename = "weightInPounds")]
89    pub weight_in_pounds: i32,
90    #[serde(rename = "heightInCentimeters")]
91    pub height_in_centimeters: i32,
92    #[serde(rename = "weightInKilograms")]
93    pub weight_in_kilograms: i32,
94    #[serde(rename = "birthDate")]
95    pub birth_date: String,
96    #[serde(rename = "birthCity")]
97    pub birth_city: LocalizedString,
98    #[serde(rename = "birthCountry")]
99    pub birth_country: String,
100    #[serde(skip_serializing_if = "Option::is_none")]
101    #[serde(rename = "birthStateProvince")]
102    pub birth_state_province: Option<LocalizedString>,
103}
104
105#[cfg(test)]
106mod tests {
107    use super::*;
108
109    #[test]
110    fn test_team_serialization() {
111        let team = Team {
112            name: "Buffalo Sabres".to_string(),
113            common_name: "Sabres".to_string(),
114            abbr: "BUF".to_string(),
115            logo: "https://assets.nhle.com/logos/nhl/svg/BUF_light.svg".to_string(),
116            conference: Conference {
117                abbr: "E".to_string(),
118                name: "Eastern".to_string(),
119            },
120            division: Division {
121                abbr: "ATL".to_string(),
122                name: "Atlantic".to_string(),
123            },
124            franchise_id: Some(19),
125        };
126
127        let json = serde_json::to_string(&team).unwrap();
128        let deserialized: Team = serde_json::from_str(&json).unwrap();
129
130        assert_eq!(deserialized.name, "Buffalo Sabres");
131        assert_eq!(deserialized.abbr, "BUF");
132        assert_eq!(deserialized.franchise_id, Some(19));
133    }
134
135    #[test]
136    fn test_franchise_response_deserialization() {
137        let json = r#"{
138            "data": [
139                {
140                    "id": 19,
141                    "fullName": "Buffalo Sabres",
142                    "teamCommonName": "Sabres"
143                }
144            ]
145        }"#;
146
147        let response: FranchisesResponse = serde_json::from_str(json).unwrap();
148        assert_eq!(response.data.len(), 1);
149        assert_eq!(response.data[0].id, 19);
150        assert_eq!(response.data[0].full_name, "Buffalo Sabres");
151    }
152
153    #[test]
154    fn test_team_display() {
155        let team = Team {
156            name: "Buffalo Sabres".to_string(),
157            common_name: "Sabres".to_string(),
158            abbr: "BUF".to_string(),
159            logo: "https://assets.nhle.com/logos/nhl/svg/BUF_light.svg".to_string(),
160            conference: Conference {
161                abbr: "E".to_string(),
162                name: "Eastern".to_string(),
163            },
164            division: Division {
165                abbr: "ATL".to_string(),
166                name: "Atlantic".to_string(),
167            },
168            franchise_id: Some(19),
169        };
170
171        assert_eq!(team.to_string(), "Buffalo Sabres (BUF)");
172    }
173}