|
1 | 1 | //! Strongly typed property hints. |
2 | 2 |
|
3 | | -use std::fmt::{self, Write}; |
| 3 | +use std::fmt::{self, Display, Write}; |
4 | 4 | use std::ops::RangeInclusive; |
5 | 5 |
|
6 | 6 | use crate::core_types::GodotString; |
@@ -116,52 +116,72 @@ where |
116 | 116 | /// ``` |
117 | 117 | #[derive(Clone, Eq, PartialEq, Debug, Default)] |
118 | 118 | pub struct EnumHint { |
119 | | - values: Vec<(String, Option<i64>)>, |
| 119 | + entries: Vec<EnumHintEntry>, |
120 | 120 | } |
121 | 121 |
|
122 | 122 | impl EnumHint { |
123 | 123 | #[inline] |
124 | | - pub fn new(values: Vec<String>) -> Self { |
125 | | - let values = values.into_iter().map(|v| (v, None)).collect(); |
126 | | - EnumHint { values } |
| 124 | + pub fn new(keys: Vec<String>) -> Self { |
| 125 | + let entries = keys.into_iter().map(EnumHintEntry::new).collect(); |
| 126 | + EnumHint { entries } |
127 | 127 | } |
128 | 128 |
|
129 | 129 | #[inline] |
130 | | - pub fn with_numbers(values: Vec<(String, i64)>) -> Self { |
131 | | - let values = values |
132 | | - .into_iter() |
133 | | - .map(|(key, val)| (key, Some(val))) |
134 | | - .collect(); |
135 | | - EnumHint { values } |
| 130 | + pub fn with_entries(entries: Vec<EnumHintEntry>) -> Self { |
| 131 | + EnumHint { entries } |
136 | 132 | } |
137 | 133 |
|
138 | 134 | /// Formats the hint as a Godot hint string. |
139 | 135 | fn to_godot_hint_string(&self) -> GodotString { |
140 | 136 | let mut s = String::new(); |
141 | 137 |
|
142 | | - let mut iter = self.values.iter(); |
143 | | - let write_item = |s: &mut String, item: &(String, Option<i64>)| match item { |
144 | | - (key, Some(val)) => { |
145 | | - write!(s, "{key}:{val}") |
146 | | - } |
147 | | - (key, None) => { |
148 | | - write!(s, "{key}") |
149 | | - } |
150 | | - }; |
| 138 | + let mut iter = self.entries.iter(); |
151 | 139 |
|
152 | 140 | if let Some(first) = iter.next() { |
153 | | - write_item(&mut s, first).unwrap(); |
| 141 | + write!(s, "{first}").unwrap(); |
154 | 142 | } |
155 | 143 |
|
156 | 144 | for rest in iter { |
157 | 145 | write!(s, ",").unwrap(); |
158 | | - write_item(&mut s, rest).unwrap(); |
| 146 | + write!(s, "{rest}").unwrap(); |
159 | 147 | } |
160 | 148 |
|
161 | 149 | s.into() |
162 | 150 | } |
163 | 151 | } |
164 | 152 |
|
| 153 | +#[derive(Clone, PartialEq, Eq, Debug)] |
| 154 | +pub struct EnumHintEntry { |
| 155 | + key: String, |
| 156 | + value: Option<i64>, |
| 157 | +} |
| 158 | + |
| 159 | +impl EnumHintEntry { |
| 160 | + #[inline] |
| 161 | + pub fn new(key: String) -> Self { |
| 162 | + Self { key, value: None } |
| 163 | + } |
| 164 | + |
| 165 | + #[inline] |
| 166 | + pub fn with_value(key: String, value: i64) -> Self { |
| 167 | + Self { |
| 168 | + key, |
| 169 | + value: Some(value), |
| 170 | + } |
| 171 | + } |
| 172 | +} |
| 173 | + |
| 174 | +impl Display for EnumHintEntry { |
| 175 | + #[inline] |
| 176 | + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 177 | + write!(f, "{}", self.key)?; |
| 178 | + if let Some(value) = self.value { |
| 179 | + write!(f, ":{}", value)?; |
| 180 | + } |
| 181 | + Ok(()) |
| 182 | + } |
| 183 | +} |
| 184 | + |
165 | 185 | /// Possible hints for integers. |
166 | 186 | #[derive(Clone, Debug)] |
167 | 187 | #[non_exhaustive] |
@@ -495,6 +515,9 @@ godot_test!(test_enum_hint_without_mapping { |
495 | 515 | }); |
496 | 516 |
|
497 | 517 | godot_test!(test_enum_hint_with_mapping { |
498 | | - let hint = EnumHint::with_numbers(vec![("Foo".into(), 42), ("Bar".into(), 67)]); |
| 518 | + let hint = EnumHint::with_entries(vec![ |
| 519 | + EnumHintEntry::with_value("Foo".to_string(), 42), |
| 520 | + EnumHintEntry::with_value("Bar".to_string(), 67), |
| 521 | + ]); |
499 | 522 | assert_eq!(hint.to_godot_hint_string().to_string(), "Foo:42,Bar:67".to_string(),); |
500 | 523 | }); |
0 commit comments