Skip to content

Commit 0368a54

Browse files
committed
refactor save to use BlueprintType
1 parent 2c71ce6 commit 0368a54

3 files changed

Lines changed: 148 additions & 93 deletions

File tree

src/blueprint.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,31 @@ pub(crate) enum BlueprintType<T: Borrow<serde_json::Value>> {
5252
DeconstructionPlanner(T),
5353
}
5454

55+
impl BlueprintType<&serde_json::Value> {
56+
#[allow(
57+
dead_code,
58+
reason = "used in tests but not logically a test-only function"
59+
)]
60+
pub fn new(json: &serde_json::Value) -> BlueprintType<&serde_json::Value> {
61+
let json = match json {
62+
serde_json::Value::Object(json) => json,
63+
_ => panic!("blueprint entry should be an object, got {json:?}"),
64+
};
65+
66+
if json.contains_key("blueprint") {
67+
BlueprintType::Blueprint(&json["blueprint"])
68+
} else if json.contains_key("blueprint_book") {
69+
BlueprintType::BlueprintBook(&json["blueprint_book"])
70+
} else if json.contains_key("upgrade_planner") {
71+
BlueprintType::UpgradePlanner(&json["upgrade_planner"])
72+
} else if json.contains_key("deconstruction_planner") {
73+
BlueprintType::DeconstructionPlanner(&json["deconstruction_planner"])
74+
} else {
75+
panic!("blueprint has unknown type: {:?}", json.keys());
76+
}
77+
}
78+
}
79+
5580
impl BlueprintType<&mut serde_json::Value> {
5681
pub fn new(json: &mut serde_json::Value) -> BlueprintType<&mut serde_json::Value> {
5782
let json = match json {
@@ -72,6 +97,11 @@ impl BlueprintType<&mut serde_json::Value> {
7297
}
7398
}
7499

100+
#[inline]
101+
pub(crate) fn as_ref(&self) -> BlueprintType<&serde_json::Value> {
102+
self.as_ref_inner()
103+
}
104+
75105
fn any_mut(&mut self) -> &mut serde_json::Value {
76106
match self {
77107
BlueprintType::Blueprint(value) => value,
@@ -95,6 +125,33 @@ impl BlueprintType<&mut serde_json::Value> {
95125
}
96126
}
97127

128+
impl<T: Borrow<serde_json::Value>> BlueprintType<T> {
129+
pub(crate) fn any(&self) -> &serde_json::Value {
130+
match self {
131+
BlueprintType::Blueprint(value) => value,
132+
BlueprintType::BlueprintBook(value) => value,
133+
BlueprintType::UpgradePlanner(value) => value,
134+
BlueprintType::DeconstructionPlanner(value) => value,
135+
}
136+
.borrow()
137+
}
138+
139+
fn as_ref_inner(&self) -> BlueprintType<&serde_json::Value> {
140+
match self {
141+
BlueprintType::Blueprint(value) => BlueprintType::Blueprint(value.borrow()),
142+
BlueprintType::BlueprintBook(value) => BlueprintType::BlueprintBook(value.borrow()),
143+
BlueprintType::UpgradePlanner(value) => BlueprintType::UpgradePlanner(value.borrow()),
144+
BlueprintType::DeconstructionPlanner(value) => {
145+
BlueprintType::DeconstructionPlanner(value.borrow())
146+
}
147+
}
148+
}
149+
150+
pub(crate) fn label(&self) -> Option<&str> {
151+
self.any().get("label")?.as_str()
152+
}
153+
}
154+
98155
fn set_tag_in_string(description: String, tag: &str, value: &str) -> String {
99156
let start_offset = if description.starts_with(&format!("{tag}:")) {
100157
0

src/load.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ pub(crate) fn stamp(json: &mut serde_json::Value, path: &Path) {
107107
let id = repo
108108
.head_id()
109109
.unwrap_or_else(|e| panic!("error: couldn't get HEAD commit: {e}"));
110-
let mut bp = blueprint::BlueprintType::new(json);
110+
let mut bp = blueprint::BlueprintType::<&mut serde_json::Value>::new(json);
111111
bp.set_tag_in_description("last_commit", &format!("{id}"));
112112
}
113113

src/save.rs

Lines changed: 90 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ use std::{
55
path::{Path, PathBuf},
66
};
77

8+
use crate::blueprint::BlueprintType;
9+
810
fn format_tag(
911
typ: &str,
1012
name: Option<&serde_json::Value>,
@@ -46,100 +48,88 @@ fn unique_strings(iter: impl Iterator<Item = String>) -> impl Iterator<Item = St
4648
})
4749
}
4850

49-
fn compute_name(json: &serde_json::Value) -> String {
51+
fn compute_name(bp: BlueprintType<&serde_json::Value>) -> String {
5052
let mut name = String::new();
51-
if let Some(thing) = json
52-
.get("blueprint")
53-
.or(json.get("blueprint_book"))
54-
.or(json.get("upgrade_planner"))
55-
.or(json.get("deconstruction_planner"))
53+
if let Some(label) = bp.label() {
54+
name = label.to_owned();
55+
} else if let Some(icons) = bp.any().get("icons").or(bp
56+
.any()
57+
.get("settings")
58+
.and_then(|settings| settings.get("icons")))
59+
&& let Some(icons) = icons.as_array()
5660
{
57-
if let Some(label) = thing.get("label")
58-
&& let Some(label) = label.as_str()
59-
{
60-
name = label.to_owned();
61-
} else if let Some(icons) = thing.get("icons").or(thing
62-
.get("settings")
63-
.and_then(|settings| settings.get("icons")))
64-
&& let Some(icons) = icons.as_array()
65-
{
66-
for icon in icons {
67-
if let Some(signal) = icon.get("signal")
68-
&& let Some(signal_name) = format_icon_tag(signal)
69-
{
70-
if !name.is_empty() {
71-
name.push(' ');
72-
}
73-
name.push_str(&signal_name);
61+
for icon in icons {
62+
if let Some(signal) = icon.get("signal")
63+
&& let Some(signal_name) = format_icon_tag(signal)
64+
{
65+
if !name.is_empty() {
66+
name.push(' ');
7467
}
68+
name.push_str(&signal_name);
7569
}
76-
} else if let Some(blueprint) = json.get("deconstruction_planner")
77-
&& let Some(settings) = blueprint.get("settings")
78-
{
79-
let entities = settings.get("entity_filters");
80-
let entities = entities
81-
.iter()
82-
.flat_map(|e| e.as_array())
83-
.flatten()
84-
.flat_map(format_entity_tag);
70+
}
71+
} else if let BlueprintType::DeconstructionPlanner(blueprint) = bp
72+
&& let Some(settings) = blueprint.get("settings")
73+
{
74+
let entities = settings.get("entity_filters");
75+
let entities = entities
76+
.iter()
77+
.flat_map(|e| e.as_array())
78+
.flatten()
79+
.flat_map(format_entity_tag);
8580

86-
let tiles = settings.get("tile_filters");
87-
let tiles = tiles
88-
.iter()
89-
.flat_map(|e| e.as_array())
90-
.flatten()
91-
.flat_map(format_tile_tag);
81+
let tiles = settings.get("tile_filters");
82+
let tiles = tiles
83+
.iter()
84+
.flat_map(|e| e.as_array())
85+
.flatten()
86+
.flat_map(format_tile_tag);
9287

93-
let mut iter = entities.chain(tiles).fuse();
88+
let mut iter = entities.chain(tiles).fuse();
9489

95-
for name_part in (&mut iter).take(4) {
96-
if !name.is_empty() {
97-
name.push(' ');
98-
}
99-
name.push_str(&name_part);
100-
}
101-
if iter.next().is_some() {
102-
name.push('…');
90+
for name_part in (&mut iter).take(4) {
91+
if !name.is_empty() {
92+
name.push(' ');
10393
}
104-
} else if let Some(blueprint) = json.get("upgrade_planner")
105-
&& let Some(settings) = blueprint.get("settings")
106-
&& let Some(mappers) = settings.get("mappers")
107-
&& let Some(mappers) = mappers.as_array()
108-
{
109-
let mut iter = unique_strings(
110-
mappers
111-
.iter()
112-
.flat_map(|mapper| mapper.get("to"))
113-
.flat_map(|to| {
114-
let typ = to.get("type");
115-
if let Some(typ) = typ
116-
&& let Some(typ) = typ.as_str()
117-
&& let Some(name_part) =
118-
format_tag(typ, to.get("name"), to.get("quality"))
119-
{
120-
Some(name_part)
121-
} else if let Some(name_part) = to.get("name")
122-
&& let Some(name_part) = name_part.as_str()
123-
{
124-
Some(name_part.to_owned())
125-
} else {
126-
None
127-
}
128-
}),
129-
)
130-
.fuse();
131-
for name_part in (&mut iter).take(4) {
132-
if !name.is_empty() {
133-
name.push(' ');
94+
name.push_str(&name_part);
95+
}
96+
if iter.next().is_some() {
97+
name.push('…');
98+
}
99+
} else if let BlueprintType::UpgradePlanner(blueprint) = bp
100+
&& let Some(settings) = blueprint.get("settings")
101+
&& let Some(mappers) = settings.get("mappers")
102+
&& let Some(mappers) = mappers.as_array()
103+
{
104+
let mut iter = unique_strings(mappers.iter().flat_map(|mapper| mapper.get("to")).flat_map(
105+
|to| {
106+
let typ = to.get("type");
107+
if let Some(typ) = typ
108+
&& let Some(typ) = typ.as_str()
109+
&& let Some(name_part) = format_tag(typ, to.get("name"), to.get("quality"))
110+
{
111+
Some(name_part)
112+
} else if let Some(name_part) = to.get("name")
113+
&& let Some(name_part) = name_part.as_str()
114+
{
115+
Some(name_part.to_owned())
116+
} else {
117+
None
134118
}
135-
name.push_str(&name_part);
136-
}
137-
if iter.next().is_some() {
138-
name.push('…');
139-
}
119+
},
120+
))
121+
.fuse();
122+
for name_part in (&mut iter).take(4) {
140123
if !name.is_empty() {
141-
name = format!("Upgrade {name}");
124+
name.push(' ');
142125
}
126+
name.push_str(&name_part);
127+
}
128+
if iter.next().is_some() {
129+
name.push('…');
130+
}
131+
if !name.is_empty() {
132+
name = format!("Upgrade {name}");
143133
}
144134
}
145135

@@ -150,11 +140,13 @@ fn compute_name(json: &serde_json::Value) -> String {
150140
}
151141

152142
pub fn save(mut json: serde_json::Value, dir: Option<&Path>) {
153-
let mut name = compute_name(&json);
143+
let index = json
144+
.get("index")
145+
.and_then(|index| index.as_number().cloned());
146+
let mut bp = BlueprintType::<&mut serde_json::Value>::new(&mut json);
147+
let mut name = compute_name(bp.as_ref());
154148

155-
if let Some(index) = json.get_mut("index")
156-
&& let Some(index) = index.as_number()
157-
{
149+
if let Some(index) = index {
158150
name = format!("{index} {name}");
159151
}
160152

@@ -168,7 +160,7 @@ pub fn save(mut json: serde_json::Value, dir: Option<&Path>) {
168160
},
169161
);
170162

171-
let file_path: PathBuf = if let Some(blueprint_book) = json.get_mut("blueprint_book")
163+
let file_path: PathBuf = if let BlueprintType::BlueprintBook(blueprint_book) = &mut bp
172164
&& let Some(blueprints) = blueprint_book.get_mut("blueprints")
173165
&& let Some(blueprints) = blueprints.as_array_mut()
174166
{
@@ -189,7 +181,7 @@ pub fn save(mut json: serde_json::Value, dir: Option<&Path>) {
189181
if let Some(dir) = dir {
190182
dir.join(&file)
191183
} else {
192-
file.clone().into()
184+
file.into()
193185
}
194186
};
195187

@@ -284,15 +276,21 @@ mod tests {
284276
let bp = "0eNq1UMsKwjAQ/Jc9V5A+LA34JSIS2rUGmt2YbNVS8u8mYK968jaPZXaYFWY3ej3gxU2aCD2oFQKKGBpDxlY7hz7B0wpXzzZrsjgEBUhiZIECSNvMn8wD0q6/YZCk3mc9ZV8Bsbd6SlLP1mmvhdMbOEIsQPhLYBDE6ZOXbg0N+AK1j8XPKsbz/4vU8ZyJYGqyzbjbZizgkWYzTKCaQ9nVXde0VVPVbRnjGw8nfKM=";
285277
let json = crate::blueprint::blueprint_to_json(bp);
286278
let json = serde_json::Value::from_str(&json).expect("should contain valid json");
287-
assert_eq!(compute_name(&json), "Upgrade [entity=steel-chest]")
279+
assert_eq!(
280+
compute_name(BlueprintType::<&serde_json::Value>::new(&json)),
281+
"Upgrade [entity=steel-chest]"
282+
)
288283
}
289284

290285
#[test]
291286
fn test_upgrade_remove_module() {
292287
let bp = "0eNp1js0KwjAQhN9lzy1IfywN+CQiEsxaAtlkTbZiKXl3E7BHbzPfDrOzw8pL1Abv7LT3GEHtkFDE+iVVTZoZY5HXHZ4xUGWyMYICK0jQgNdUXWJE01Iwq8NCX6t2VrZy8CGSdgU9ArGOWkJ5AhfIDUj4W4fEsv3q2uSC1Lz1Bj+gTvlWTc2rY3977G/gXfba4EGN524e5nmc+rEfpi7nL1TiT8I=";
293288
let json = crate::blueprint::blueprint_to_json(bp);
294289
let json = serde_json::Value::from_str(&json).expect("should contain valid json");
295-
assert_eq!(compute_name(&json), "Upgrade [item=empty-module-slot]")
290+
assert_eq!(
291+
compute_name(BlueprintType::<&serde_json::Value>::new(&json)),
292+
"Upgrade [item=empty-module-slot]"
293+
)
296294
}
297295

298296
#[test]
@@ -301,7 +299,7 @@ mod tests {
301299
let json = crate::blueprint::blueprint_to_json(bp);
302300
let json = serde_json::Value::from_str(&json).expect("should contain valid json");
303301
assert_eq!(
304-
compute_name(&json),
302+
compute_name(BlueprintType::<&serde_json::Value>::new(&json)),
305303
"Upgrade [entity=biochamber,quality=uncommon]"
306304
)
307305
}

0 commit comments

Comments
 (0)