implement From<String>

This commit is contained in:
Max Bradbury 2020-04-12 11:51:30 +01:00
parent b09b9dbece
commit cd82c075be
1 changed files with 274 additions and 257 deletions

View File

@ -624,8 +624,9 @@ fn test_colour_to_string() {
); );
} }
fn palette_from_string(palette: String) -> Palette { impl From<String> for Palette {
let lines: Vec<&str> = palette.split('\n').collect(); fn from(string: String) -> Palette {
let lines: Vec<&str> = string.lines().collect();
let id = lines[0].replace("PAL ", ""); let id = lines[0].replace("PAL ", "");
@ -642,10 +643,11 @@ fn palette_from_string(palette: String) -> Palette {
Palette { id, name, colours } Palette { id, name, colours }
} }
}
#[test] #[test]
fn test_palette_from_string() { fn test_palette_from_string() {
let output = palette_from_string( let output = Palette::from(
"PAL 1\nNAME lamplight\n45,45,59\n66,60,39\n140,94,1".to_string() "PAL 1\nNAME lamplight\n45,45,59\n66,60,39\n140,94,1".to_string()
); );
@ -664,7 +666,7 @@ fn test_palette_from_string() {
#[test] #[test]
fn test_palette_from_string_no_name() { fn test_palette_from_string_no_name() {
let output = palette_from_string( let output = Palette::from(
"PAL 9\n45,45,59\n66,60,39\n140,94,1".to_string() "PAL 9\n45,45,59\n66,60,39\n140,94,1".to_string()
); );
@ -715,7 +717,8 @@ fn test_palette_to_string() {
assert_eq!(output, expected); assert_eq!(output, expected);
} }
fn position_from_string(string: String) -> Position { impl From<String> for Position {
fn from(string: String) -> Position {
// e.g. "2,5" // e.g. "2,5"
let xy: Vec<&str> = string.split(',').collect(); let xy: Vec<&str> = string.split(',').collect();
let x = xy[0].parse().unwrap(); let x = xy[0].parse().unwrap();
@ -723,13 +726,11 @@ fn position_from_string(string: String) -> Position {
Position { x, y } Position { x, y }
} }
}
#[test] #[test]
fn test_position_from_string() { fn test_position_from_string() {
assert_eq!( assert_eq!(Position::from("4,12".to_string()), Position { x: 4, y: 12 });
position_from_string("4,12".to_string()),
Position { x: 4, y: 12 }
)
} }
impl ToString for Position { impl ToString for Position {
@ -744,13 +745,14 @@ fn test_position_to_string() {
assert_eq!(Position { x: 4, y: 12 }.to_string(), "4,12".to_string()) assert_eq!(Position { x: 4, y: 12 }.to_string(), "4,12".to_string())
} }
fn avatar_from_string(string: String) -> Avatar { impl From<String> for Avatar {
fn from(string: String) -> Avatar {
let string = string.replace("SPR A\n", ""); let string = string.replace("SPR A\n", "");
let mut lines: Vec<&str> = string.lines().collect(); let mut lines: Vec<&str> = string.lines().collect();
let room_pos = lines.pop().unwrap().replace("POS ", ""); let room_pos = lines.pop().unwrap().replace("POS ", "");
let room_pos: Vec<&str> = room_pos.split_whitespace().collect(); let room_pos: Vec<&str> = room_pos.split_whitespace().collect();
let room = room_pos[0].to_string(); let room = room_pos[0].to_string();
let position = position_from_string(room_pos[1].to_string()); let position = Position::from(room_pos[1].to_string());
let animation_frames: String = lines.join("\n"); let animation_frames: String = lines.join("\n");
let animation_frames: Vec<&str> = animation_frames.split("\n>\n").collect(); let animation_frames: Vec<&str> = animation_frames.split("\n>\n").collect();
let animation_frames: Vec<Image> = animation_frames.iter().map(|&frame| { let animation_frames: Vec<Image> = animation_frames.iter().map(|&frame| {
@ -759,12 +761,14 @@ fn avatar_from_string(string: String) -> Avatar {
Avatar { animation_frames, room, position } Avatar { animation_frames, room, position }
} }
}
#[test] #[test]
fn test_avatar_from_string() { fn test_avatar_from_string() {
let output = avatar_from_string( let output = Avatar::from(
include_str!("../test/resources/avatar").to_string() include_str!("../test/resources/avatar").to_string()
); );
let expected = example_avatar(); let expected = example_avatar();
assert_eq!(output, expected); assert_eq!(output, expected);
} }
@ -786,7 +790,8 @@ fn test_avatar_to_string() {
assert_eq!(example_avatar().to_string(), include_str!("../test/resources/avatar")); assert_eq!(example_avatar().to_string(), include_str!("../test/resources/avatar"));
} }
fn sprite_from_string(string: String) -> Sprite { impl From<String> for Sprite {
fn from(string: String) -> Sprite {
let mut lines: Vec<&str> = string.lines().collect(); let mut lines: Vec<&str> = string.lines().collect();
let id = lines[0].replace("SPR ", ""); let id = lines[0].replace("SPR ", "");
@ -806,9 +811,10 @@ fn sprite_from_string(string: String) -> Sprite {
let last_line = last_line.replace("POS ", ""); let last_line = last_line.replace("POS ", "");
let room_position: Vec<&str> = last_line.split(' ').collect(); let room_position: Vec<&str> = last_line.split(' ').collect();
room = Some(room_position[0].to_string()); room = Some(room_position[0].to_string());
position = Some(position_from_string(room_position[1].to_string())); position = Some(Position::from(room_position[1].to_string()));
} else { } else {
lines.push(last_line); break; lines.push(last_line);
break;
} }
} }
@ -824,10 +830,11 @@ fn sprite_from_string(string: String) -> Sprite {
Sprite { id, name, animation_frames, dialogue, room, position } Sprite { id, name, animation_frames, dialogue, room, position }
} }
}
#[test] #[test]
fn test_sprite_from_string() { fn test_sprite_from_string() {
let output = sprite_from_string( let output = Sprite::from(
include_str!("../test/resources/sprite").to_string() include_str!("../test/resources/sprite").to_string()
); );
@ -856,7 +863,8 @@ fn test_sprite_to_string() {
assert_eq!(example_sprite().to_string(), include_str!("../test/resources/sprite").to_string()); assert_eq!(example_sprite().to_string(), include_str!("../test/resources/sprite").to_string());
} }
fn item_from_string(string: String) -> Item { impl From<String> for Item {
fn from(string: String) -> Item {
let mut lines: Vec<&str> = string.lines().collect(); let mut lines: Vec<&str> = string.lines().collect();
let id = lines[0].replace("ITM ", ""); let id = lines[0].replace("ITM ", "");
@ -871,7 +879,8 @@ fn item_from_string(string: String) -> Item {
} else if last_line.starts_with("DLG") { } else if last_line.starts_with("DLG") {
dialogue = Some(last_line.replace("DLG ", "").to_string()); dialogue = Some(last_line.replace("DLG ", "").to_string());
} else { } else {
lines.push(last_line); break; lines.push(last_line);
break;
} }
} }
@ -884,15 +893,12 @@ fn item_from_string(string: String) -> Item {
Item { id, name, animation_frames, dialogue } Item { id, name, animation_frames, dialogue }
} }
}
#[test] #[test]
fn test_item_from_string() { fn test_item_from_string() {
let output = item_from_string( let output = Item::from(include_str!("../test/resources/item").to_string());
include_str!("../test/resources/item").to_string()
);
let expected = example_item(); let expected = example_item();
assert_eq!(output, expected); assert_eq!(output, expected);
} }
@ -916,19 +922,21 @@ fn test_item_to_string() {
assert_eq!(output, expected); assert_eq!(output, expected);
} }
fn exit_from_string(string: String) -> Exit { impl From<String> for Exit {
fn from(string: String) -> Exit {
// e.g. "4 3,3" // e.g. "4 3,3"
let room_position: Vec<&str> = string.split(' ').collect(); let room_position: Vec<&str> = string.split(' ').collect();
let room = room_position[0].to_string(); let room = room_position[0].to_string();
let position = position_from_string(room_position[1].to_string()); let position = Position::from(room_position[1].to_string());
Exit { room, position } Exit { room, position }
} }
}
#[test] #[test]
fn test_exit_from_string() { fn test_exit_from_string() {
assert_eq!( assert_eq!(
exit_from_string("a 12,13".to_string()), Exit::from("a 12,13".to_string()),
Exit { room: "a".to_string(), position: Position { x: 12, y: 13 } } Exit { room: "a".to_string(), position: Position { x: 12, y: 13 } }
); );
} }
@ -947,19 +955,21 @@ fn test_exit_to_string() {
); );
} }
fn ending_from_string(string: String) -> Ending { impl From<String> for Ending {
fn from(string: String) -> Ending {
let string = string.replace("END ", ""); let string = string.replace("END ", "");
let id_dialogue: Vec<&str> = string.split('\n').collect(); let id_dialogue: Vec<&str> = string.lines().collect();
let id = id_dialogue[0].to_string(); let id = id_dialogue[0].to_string();
let dialogue = id_dialogue[1].to_string(); let dialogue = id_dialogue[1].to_string();
Ending { id, dialogue } Ending { id, dialogue }
} }
}
#[test] #[test]
fn test_ending_from_string() { fn test_ending_from_string() {
assert_eq!( assert_eq!(
ending_from_string(include_str!("../test/resources/ending").to_string()), Ending::from(include_str!("../test/resources/ending").to_string()),
Ending { Ending {
id: "a".to_string(), id: "a".to_string(),
dialogue: "This is a long line of dialogue. Blah blah blah".to_string() dialogue: "This is a long line of dialogue. Blah blah blah".to_string()
@ -985,18 +995,20 @@ fn test_ending_to_string() {
); );
} }
fn dialogue_from_string(string: String) -> Dialogue { impl From<String> for Dialogue {
fn from(string: String) -> Dialogue {
let lines: Vec<&str> = string.lines().collect(); let lines: Vec<&str> = string.lines().collect();
let id = lines[0].replace("DLG ", "").to_string(); let id = lines[0].replace("DLG ", "").to_string();
let contents = lines[1..].join("\n"); let contents = lines[1..].join("\n");
Dialogue { id, contents } Dialogue { id, contents }
} }
}
#[test] #[test]
fn test_dialogue_from_string() { fn test_dialogue_from_string() {
assert_eq!( assert_eq!(
dialogue_from_string("DLG h\nhello\ngoodbye".to_string()), Dialogue::from("DLG h\nhello\ngoodbye".to_string()),
Dialogue { id: "h".to_string(), contents: "hello\ngoodbye".to_string()} Dialogue { id: "h".to_string(), contents: "hello\ngoodbye".to_string()}
) )
} }
@ -1019,18 +1031,20 @@ fn test_dialogue_to_string() {
); );
} }
fn variable_from_string(string: String) -> Variable { impl From<String> for Variable {
fn from(string: String) -> Variable {
let id_value: Vec<&str> = string.split('\n').collect(); let id_value: Vec<&str> = string.split('\n').collect();
let id = id_value[0].replace("VAR ", "").to_string(); let id = id_value[0].replace("VAR ", "").to_string();
let initial_value = id_value[1].to_string(); let initial_value = id_value[1].to_string();
Variable { id, initial_value } Variable { id, initial_value }
} }
}
#[test] #[test]
fn test_variable_from_string() { fn test_variable_from_string() {
assert_eq!( assert_eq!(
variable_from_string("VAR a\n42".to_string()), Variable::from("VAR a\n42".to_string()),
Variable { id: "a".to_string(), initial_value: "42".to_string()} Variable { id: "a".to_string(), initial_value: "42".to_string()}
); );
} }
@ -1049,7 +1063,8 @@ fn test_variable_to_string() {
assert_eq!(output, expected); assert_eq!(output, expected);
} }
fn room_from_string(string: String) -> Room { impl From<String> for Room {
fn from(string: String) -> Room {
// todo handle room_format? // todo handle room_format?
let mut lines: Vec<&str> = string.lines().collect(); let mut lines: Vec<&str> = string.lines().collect();
let id = lines[0].replace("ROOM ", ""); let id = lines[0].replace("ROOM ", "");
@ -1071,14 +1086,14 @@ fn room_from_string(string: String) -> Room {
let item_position: Vec<&str> = last_line.split(' ').collect(); let item_position: Vec<&str> = last_line.split(' ').collect();
let item_id = item_position[0]; let item_id = item_position[0];
let position = item_position[1]; let position = item_position[1];
let position = position_from_string(position.to_string()); let position = Position::from(position.to_string());
items.push(Instance { position, id: item_id.to_string() }); items.push(Instance { position, id: item_id.to_string() });
} else if last_line.starts_with("EXT") { } else if last_line.starts_with("EXT") {
let last_line = last_line.replace("EXT ", ""); let last_line = last_line.replace("EXT ", "");
let parts: Vec<&str> = last_line.split(' ').collect(); let parts: Vec<&str> = last_line.split(' ').collect();
let position = position_from_string(parts[0].to_string()); let position = Position::from(parts[0].to_string());
let exit = exit_from_string(format!("{} {}", parts[1], parts[2])); let exit = Exit::from(format!("{} {}", parts[1], parts[2]));
exits.push(ExitInstance { position, exit }); exits.push(ExitInstance { position, exit });
} else if last_line.starts_with("END") { } else if last_line.starts_with("END") {
@ -1086,11 +1101,12 @@ fn room_from_string(string: String) -> Room {
let ending_position: Vec<&str> = last_line.split(' ').collect(); let ending_position: Vec<&str> = last_line.split(' ').collect();
let ending = ending_position[0].to_string(); let ending = ending_position[0].to_string();
let position = ending_position[1].to_string(); let position = ending_position[1].to_string();
let position = position_from_string(position); let position = Position::from(position);
endings.push(Instance { position, id: ending }); endings.push(Instance { position, id: ending });
} else { } else {
lines.push(last_line); break; lines.push(last_line);
break;
} }
} }
@ -1108,13 +1124,11 @@ fn room_from_string(string: String) -> Room {
Room { id, palette, name, tiles, items, exits, endings } Room { id, palette, name, tiles, items, exits, endings }
} }
}
#[test] #[test]
fn test_room_from_string() { fn test_room_from_string() {
let output = room_from_string(example_room_string()); assert_eq!(Room::from(example_room_string()), example_room());
let expected = example_room();
assert_eq!(output, expected);
} }
impl ToString for Room { impl ToString for Room {
@ -1174,7 +1188,8 @@ fn test_room_to_string() {
assert_eq!(example_room().to_string(), example_room_string()); assert_eq!(example_room().to_string(), example_room_string());
} }
fn game_from_string(string: String ) -> Game { impl From<String> for Game {
fn from(string: String) -> Game {
// dialogues and endings can have 2+ line breaks inside, so deal with these separately // dialogues and endings can have 2+ line breaks inside, so deal with these separately
// otherwise, everything can be split on a double line break (\n\n) // otherwise, everything can be split on a double line break (\n\n)
let mut dialogues: Vec<Dialogue> = Vec::new(); let mut dialogues: Vec<Dialogue> = Vec::new();
@ -1192,7 +1207,7 @@ fn game_from_string(string: String ) -> Game {
for segment in variable_segments { for segment in variable_segments {
let segment = format!("VAR{}", segment); let segment = format!("VAR{}", segment);
variables.push(variable_from_string(segment)); variables.push(Variable::from(segment));
} }
} }
@ -1204,7 +1219,7 @@ fn game_from_string(string: String ) -> Game {
for segment in ending_segments { for segment in ending_segments {
let segment = format!("END{}", segment); let segment = format!("END{}", segment);
endings.push(ending_from_string(segment)); endings.push(Ending::from(segment));
} }
} }
@ -1212,7 +1227,7 @@ fn game_from_string(string: String ) -> Game {
let dialogue_segments: Vec<&str> = dialogue_segments.split("\n\nDLG").collect(); let dialogue_segments: Vec<&str> = dialogue_segments.split("\n\nDLG").collect();
for segment in dialogue_segments[1..].to_owned() { for segment in dialogue_segments[1..].to_owned() {
let segment = format!("DLG{}", segment); let segment = format!("DLG{}", segment);
dialogues.push(dialogue_from_string(segment)); dialogues.push(Dialogue::from(segment));
} }
let segments: Vec<&str> = main.split("\n\n").collect(); let segments: Vec<&str> = main.split("\n\n").collect();
@ -1235,17 +1250,17 @@ fn game_from_string(string: String ) -> Game {
} else if segment.starts_with("! ROOM_FORMAT") { } else if segment.starts_with("! ROOM_FORMAT") {
room_format = segment.replace("! ROOM_FORMAT ", "").parse().unwrap(); room_format = segment.replace("! ROOM_FORMAT ", "").parse().unwrap();
} else if segment.starts_with("PAL") { } else if segment.starts_with("PAL") {
palettes.push(palette_from_string(segment)); palettes.push(Palette::from(segment));
} else if segment.starts_with("ROOM") { } else if segment.starts_with("ROOM") {
rooms.push(room_from_string(segment)); rooms.push(Room::from(segment));
} else if segment.starts_with("TIL") { } else if segment.starts_with("TIL") {
tiles.push(Tile::from(segment)); tiles.push(Tile::from(segment));
} else if segment.starts_with("SPR A") { } else if segment.starts_with("SPR A") {
avatar = Some(avatar_from_string(segment)); avatar = Some(Avatar::from(segment));
} else if segment.starts_with("SPR") { } else if segment.starts_with("SPR") {
sprites.push(sprite_from_string(segment)); sprites.push(Sprite::from(segment));
} else if segment.starts_with("ITM") { } else if segment.starts_with("ITM") {
items.push(item_from_string(segment)); items.push(Item::from(segment));
} }
} }
@ -1267,12 +1282,14 @@ fn game_from_string(string: String ) -> Game {
variables, variables,
} }
} }
}
#[test] #[test]
fn test_game_from_string() { fn test_game_from_string() {
let output = game_from_string( let output = Game::from(
include_str!["../test/resources/default.bitsy"].to_string() include_str!["../test/resources/default.bitsy"].to_string()
); );
let expected = example_game_default(); let expected = example_game_default();
assert_eq!(output, expected); assert_eq!(output, expected);