|
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