• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Xevion / Pac-Man / 16896410642

12 Aug 2025 01:23AM UTC coverage: 43.298% (-2.1%) from 45.41%
16896410642

push

github

Xevion
feat!: implement proper error handling, drop most expect() & unwrap() usages

126 of 337 new or added lines in 10 files covered. (37.39%)

8 existing lines in 5 files now uncovered.

743 of 1716 relevant lines covered (43.3%)

280.21 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

81.54
/src/map/parser.rs
1
//! Map parsing functionality for converting raw board layouts into structured data.
2

3
use crate::constants::{MapTile, BOARD_CELL_SIZE};
4
use glam::IVec2;
5
use thiserror::Error;
6

7
/// Error type for map parsing operations.
8
#[derive(Debug, Error)]
9
pub enum ParseError {
10
    #[error("Unknown character in board: {0}")]
11
    UnknownCharacter(char),
12
    #[error("House door must have exactly 2 positions, found {0}")]
13
    InvalidHouseDoorCount(usize),
14
    #[error("Map parsing failed: {0}")]
15
    ParseFailed(String),
16
}
17

18
/// Represents the parsed data from a raw board layout.
19
#[derive(Debug)]
20
pub struct ParsedMap {
21
    /// The parsed tile layout.
22
    pub tiles: [[MapTile; BOARD_CELL_SIZE.y as usize]; BOARD_CELL_SIZE.x as usize],
23
    /// The positions of the house door tiles.
24
    pub house_door: [Option<IVec2>; 2],
25
    /// The positions of the tunnel end tiles.
26
    pub tunnel_ends: [Option<IVec2>; 2],
27
    /// Pac-Man's starting position.
28
    pub pacman_start: Option<IVec2>,
29
}
30

31
/// Parser for converting raw board layouts into structured map data.
32
pub struct MapTileParser;
33

34
impl MapTileParser {
35
    /// Parses a single character into a map tile.
36
    ///
37
    /// # Arguments
38
    ///
39
    /// * `c` - The character to parse
40
    ///
41
    /// # Returns
42
    ///
43
    /// The parsed map tile, or an error if the character is unknown.
44
    pub fn parse_character(c: char) -> Result<MapTile, ParseError> {
5,244✔
45
        match c {
5,244✔
46
            '#' => Ok(MapTile::Wall),
3,076✔
47
            '.' => Ok(MapTile::Pellet),
1,441✔
48
            'o' => Ok(MapTile::PowerPellet),
25✔
49
            ' ' => Ok(MapTile::Empty),
667✔
50
            'T' => Ok(MapTile::Tunnel),
13✔
51
            'X' => Ok(MapTile::Empty), // Pac-Man's starting position, treated as empty
7✔
52
            '=' => Ok(MapTile::Wall),  // House door is represented as a wall tile
13✔
53
            _ => Err(ParseError::UnknownCharacter(c)),
2✔
54
        }
55
    }
5,244✔
56

57
    /// Parses a raw board layout into structured map data.
58
    ///
59
    /// # Arguments
60
    ///
61
    /// * `raw_board` - The raw board layout as an array of strings
62
    ///
63
    /// # Returns
64
    ///
65
    /// The parsed map data, or an error if parsing fails.
66
    ///
67
    /// # Errors
68
    ///
69
    /// Returns an error if the board contains unknown characters or if the house door
70
    /// is not properly defined by exactly two '=' characters.
71
    pub fn parse_board(raw_board: [&str; BOARD_CELL_SIZE.y as usize]) -> Result<ParsedMap, ParseError> {
7✔
72
        // Validate board dimensions
7✔
73
        if raw_board.len() != BOARD_CELL_SIZE.y as usize {
7✔
NEW
74
            return Err(ParseError::ParseFailed(format!(
×
NEW
75
                "Invalid board height: expected {}, got {}",
×
NEW
76
                BOARD_CELL_SIZE.y,
×
NEW
77
                raw_board.len()
×
NEW
78
            )));
×
79
        }
7✔
80

81
        for (i, line) in raw_board.iter().enumerate() {
217✔
82
            if line.len() != BOARD_CELL_SIZE.x as usize {
217✔
NEW
83
                return Err(ParseError::ParseFailed(format!(
×
NEW
84
                    "Invalid board width at line {}: expected {}, got {}",
×
NEW
85
                    i,
×
NEW
86
                    BOARD_CELL_SIZE.x,
×
NEW
87
                    line.len()
×
NEW
88
                )));
×
89
            }
217✔
90
        }
91
        let mut tiles = [[MapTile::Empty; BOARD_CELL_SIZE.y as usize]; BOARD_CELL_SIZE.x as usize];
7✔
92
        let mut house_door = [None; 2];
7✔
93
        let mut tunnel_ends = [None; 2];
7✔
94
        let mut pacman_start: Option<IVec2> = None;
7✔
95

96
        for (y, line) in raw_board.iter().enumerate().take(BOARD_CELL_SIZE.y as usize) {
187✔
97
            for (x, character) in line.chars().enumerate().take(BOARD_CELL_SIZE.x as usize) {
5,236✔
98
                let tile = Self::parse_character(character)?;
5,236✔
99

100
                // Track special positions
101
                match tile {
3,087✔
102
                    MapTile::Tunnel => {
103
                        if tunnel_ends[0].is_none() {
12✔
104
                            tunnel_ends[0] = Some(IVec2::new(x as i32, y as i32));
6✔
105
                        } else {
6✔
106
                            tunnel_ends[1] = Some(IVec2::new(x as i32, y as i32));
6✔
107
                        }
6✔
108
                    }
109
                    MapTile::Wall if character == '=' => {
3,087✔
110
                        if house_door[0].is_none() {
12✔
111
                            house_door[0] = Some(IVec2::new(x as i32, y as i32));
6✔
112
                        } else {
6✔
113
                            house_door[1] = Some(IVec2::new(x as i32, y as i32));
6✔
114
                        }
6✔
115
                    }
116
                    _ => {}
5,211✔
117
                }
118

119
                // Track Pac-Man's starting position
120
                if character == 'X' {
5,235✔
121
                    pacman_start = Some(IVec2::new(x as i32, y as i32));
6✔
122
                }
5,229✔
123

124
                tiles[x][y] = tile;
5,235✔
125
            }
126
        }
127

128
        // Validate house door configuration
129
        let house_door_count = house_door.iter().filter(|x| x.is_some()).count();
12✔
130
        if house_door_count != 2 {
6✔
131
            return Err(ParseError::InvalidHouseDoorCount(house_door_count));
×
132
        }
6✔
133

6✔
134
        Ok(ParsedMap {
6✔
135
            tiles,
6✔
136
            house_door,
6✔
137
            tunnel_ends,
6✔
138
            pacman_start,
6✔
139
        })
6✔
140
    }
7✔
141
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc