1use std::fmt;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum Mp3dCategoryMapping {
11 Default,
13 Raw,
15 MpCat40,
17 Category,
19}
20
21#[derive(Debug, Clone, PartialEq, Eq)]
26pub struct Mp3dObjectCategory {
27 source_index: i32,
28 raw_index: i32,
29 raw_name: String,
30 mpcat40_index: i32,
31 mpcat40_name: String,
32}
33
34impl Mp3dObjectCategory {
35 #[must_use]
36 pub(crate) const fn new(
37 source_index: i32,
38 raw_index: i32,
39 raw_name: String,
40 mpcat40_index: i32,
41 mpcat40_name: String,
42 ) -> Self {
43 Self {
44 source_index,
45 raw_index,
46 raw_name,
47 mpcat40_index,
48 mpcat40_name,
49 }
50 }
51
52 #[must_use]
54 pub const fn source_index(&self) -> i32 {
55 self.source_index
56 }
57
58 #[must_use]
60 pub const fn index(&self, mapping: Mp3dCategoryMapping) -> Option<i32> {
61 match mapping {
62 Mp3dCategoryMapping::Default | Mp3dCategoryMapping::MpCat40 => Some(self.mpcat40_index),
63 Mp3dCategoryMapping::Raw => Some(self.raw_index),
64 Mp3dCategoryMapping::Category => None,
65 }
66 }
67
68 #[must_use]
70 pub fn name(&self, mapping: Mp3dCategoryMapping) -> Option<&str> {
71 match mapping {
72 Mp3dCategoryMapping::Default | Mp3dCategoryMapping::MpCat40 => Some(&self.mpcat40_name),
73 Mp3dCategoryMapping::Raw => Some(&self.raw_name),
74 Mp3dCategoryMapping::Category => None,
75 }
76 }
77}
78
79impl fmt::Display for Mp3dObjectCategory {
80 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
81 write!(
82 formatter,
83 "mpcat40={}({}), raw={}({})",
84 self.mpcat40_name, self.mpcat40_index, self.raw_name, self.raw_index
85 )
86 }
87}
88
89#[derive(Debug, Clone, Copy, PartialEq, Eq)]
94pub struct Mp3dRegionCategory {
95 code: char,
96}
97
98impl Mp3dRegionCategory {
99 #[must_use]
100 pub(crate) const fn new(code: char) -> Self {
101 Self { code }
102 }
103
104 #[must_use]
106 pub const fn code(self) -> char {
107 self.code
108 }
109
110 #[must_use]
112 pub fn index(self) -> Option<i32> {
113 region_category_entries()
114 .iter()
115 .position(|(code, _)| *code == self.code)
116 .and_then(|index| i32::try_from(index).ok())
117 }
118
119 #[must_use]
121 pub fn name(self) -> Option<&'static str> {
122 region_category_entries()
123 .iter()
124 .find_map(|(code, name)| (*code == self.code).then_some(*name))
125 }
126}
127
128impl fmt::Display for Mp3dRegionCategory {
129 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
130 let name = self.name().unwrap_or("unknown");
131 write!(formatter, "{name}({})", self.code)
132 }
133}
134
135const fn region_category_entries() -> &'static [(char, &'static str)] {
136 &[
137 ('a', "bathroom"),
138 ('b', "bedroom"),
139 ('c', "closet"),
140 ('d', "dining room"),
141 ('e', "entryway/foyer/lobby"),
142 ('f', "familyroom/lounge"),
143 ('g', "garage"),
144 ('h', "hallway"),
145 ('i', "library"),
146 ('j', "laundryroom/mudroom"),
147 ('k', "kitchen"),
148 ('l', "living room"),
149 ('m', "meetingroom/conferenceroom"),
150 ('n', "lounge"),
151 ('o', "office"),
152 ('p', "porch/terrace/deck"),
153 ('r', "rec/game"),
154 ('s', "stairs"),
155 ('t', "toilet"),
156 ('u', "utilityroom/toolroom"),
157 ('v', "tv"),
158 ('w', "workout/gym/exercise"),
159 ('x', "outdoor"),
160 ('y', "balcony"),
161 ('z', "other room"),
162 ('B', "bar"),
163 ('C', "classroom"),
164 ('D', "dining booth"),
165 ('S', "spa/sauna"),
166 ('Z', "junk"),
167 ]
168}