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

TinTeam / SN-50 / 14149942514

29 Mar 2025 10:20PM UTC coverage: 91.618% (-1.7%) from 93.269%
14149942514

Pull #5

github

web-flow
Merge 11985a483 into d5615e274
Pull Request #5: refactor: improve tinlib code

36 of 62 new or added lines in 4 files covered. (58.06%)

6 existing lines in 2 files now uncovered.

1716 of 1873 relevant lines covered (91.62%)

36926.27 hits per line

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

96.65
/tinlib/src/graphic/glyph.rs
1
//! Glyph implementation and manipulation.
2
use std::fmt;
3
use std::slice;
4

5
use crate::common::{
6
    CommonError, Coord, CoordEnumerate, CoordEnumerateMut, CoordIter, Result, Size,
7
};
8

9
/// The default Glyph width.
10
pub const GLYPH_WIDTH: usize = 16;
11
/// The default Glyph height.
12
pub const GLYPH_HEIGHT: usize = 16;
13

14
/// A Glyph pixel representation.
15
#[derive(Debug, Clone, Copy, PartialEq)]
16
pub enum GlyphPixel {
17
    /// An empty or transparent pixel.
18
    Empty,
19
    /// An solid pixel.
20
    Solid,
21
}
22

23
/// A iterator over all glyph pìxels.
24
pub type GlyphPixelIter<'iter> = slice::Iter<'iter, GlyphPixel>;
25
/// A mutable iterator over all glyph pìxels.
26
pub type GlyphPixelIterMut<'iter> = slice::IterMut<'iter, GlyphPixel>;
27
/// A enumeration iterator over all glyph pixels and their coords.
28
pub type GlyphPixelEnumerate<'iter> = CoordEnumerate<'iter, GlyphPixel>;
29
/// A mutable enumeration iterator over all glyph pixels and their coords.
30
pub type GlyphPixelEnumerateMut<'iter> = CoordEnumerateMut<'iter, GlyphPixel>;
31

32
/// A Glyph representation with NxM Pixels.
33
#[derive(Clone)]
34
pub struct Glyph {
35
    size: Size,
36
    data: Vec<GlyphPixel>,
37
}
38

39
impl Glyph {
40
    /// Creates a new Glyph.
NEW
41
    pub fn new(size: Size) -> Self {
×
NEW
42
        Self {
×
NEW
43
            size,
×
NEW
44
            data: vec![GlyphPixel::Empty; size.width() * size.height()],
×
NEW
45
        }
×
UNCOV
46
    }
×
47

48
    /// Returns a Size.
49
    pub fn size(&self) -> Size {
264✔
50
        self.size
264✔
51
    }
264✔
52

53
    /// Returns a pixel.
54
    pub fn get_pixel(&self, coord: Coord) -> Result<GlyphPixel> {
3✔
55
        if !self.is_coord_valid(coord) {
3✔
56
            return Err(CommonError::new_invalid_coord(coord, self.size));
1✔
57
        }
2✔
58

2✔
59
        let index = self.get_index(coord);
2✔
60
        Ok(self.data[index])
2✔
61
    }
3✔
62

63
    /// Sets a pixel.
64
    pub fn set_pixel(&mut self, coord: Coord, value: GlyphPixel) -> Result<()> {
4✔
65
        if !self.is_coord_valid(coord) {
4✔
66
            return Err(CommonError::new_invalid_coord(coord, self.size));
1✔
67
        }
3✔
68

3✔
69
        let index = self.get_index(coord);
3✔
70
        self.data[index] = value;
3✔
71

3✔
72
        Ok(())
3✔
73
    }
4✔
74

75
    /// Returns a iterator over the glyph's coords.
76
    pub fn coords(&self) -> CoordIter {
5✔
77
        CoordIter::new(self.size())
5✔
78
    }
5✔
79

80
    /// Returns an iterator over all Glyph pixels.
81
    pub fn iter(&self) -> GlyphPixelIter {
5✔
82
        self.data.iter()
5✔
83
    }
5✔
84

85
    /// Returns a mutable iterator over all Glyph pixels.
86
    pub fn iter_mut(&mut self) -> GlyphPixelIterMut {
2✔
87
        self.data.iter_mut()
2✔
88
    }
2✔
89

90
    /// Returns an enumerate iterator over glyph's coords and pixels.
91
    pub fn enumerate(&self) -> GlyphPixelEnumerate {
1✔
92
        GlyphPixelEnumerate::new(self.coords(), self.iter())
1✔
93
    }
1✔
94

95
    /// Returns a mutable enumerate iterator over glyph's coords and pixels.
96
    pub fn enumerate_mut(&mut self) -> GlyphPixelEnumerateMut {
1✔
97
        GlyphPixelEnumerateMut::new(self.coords(), self.iter_mut())
1✔
98
    }
1✔
99

100
    fn is_coord_valid(&self, coord: Coord) -> bool {
7✔
101
        coord.x < self.size.width() && coord.y < self.size.height()
7✔
102
    }
7✔
103

104
    fn get_index(&self, coord: Coord) -> usize {
5✔
105
        coord.x * self.size.width() + coord.y
5✔
106
    }
5✔
107
}
108

109
impl Default for Glyph {
110
    /// Creates a Glyph with all pixels black.
111
    fn default() -> Self {
34✔
112
        Self {
34✔
113
            size: Size::new(GLYPH_WIDTH, GLYPH_HEIGHT),
34✔
114
            data: vec![GlyphPixel::Empty; GLYPH_WIDTH * GLYPH_HEIGHT],
34✔
115
        }
34✔
116
    }
34✔
117
}
118

119
impl PartialEq for Glyph {
120
    fn eq(&self, other: &Self) -> bool {
123,398✔
121
        self.data.iter().zip(other.data.iter()).all(|(a, b)| a == b)
31,589,633✔
122
    }
123,398✔
123
}
124

125
impl fmt::Debug for Glyph {
126
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
515✔
127
        let data: Vec<&GlyphPixel> = self.data.iter().collect();
515✔
128

515✔
129
        f.debug_struct("Glyph").field("data", &data).finish()
515✔
130
    }
515✔
131
}
132

133
#[cfg(test)]
134
mod tests {
135
    use assert_matches::assert_matches;
136

137
    use super::*;
138

139
    #[test]
140
    fn test_glyph_default() {
1✔
141
        let glyph = Glyph::default();
1✔
142

1✔
143
        assert_eq!(glyph.data.len(), GLYPH_WIDTH * GLYPH_HEIGHT);
1✔
144
        for pixel in glyph.data.iter() {
256✔
145
            assert_eq!(*pixel, GlyphPixel::Empty);
256✔
146
        }
147
    }
1✔
148

149
    #[test]
150
    fn test_glyph_size() {
1✔
151
        let glyph = Glyph::default();
1✔
152
        assert_eq!(glyph.size(), Size::new(GLYPH_WIDTH, GLYPH_HEIGHT));
1✔
153
    }
1✔
154

155
    #[test]
156
    fn test_glyph_get_pixel() {
1✔
157
        let coord = Coord::new(1, 1);
1✔
158
        let glyph = Glyph::default();
1✔
159

1✔
160
        let result = glyph.get_pixel(coord);
1✔
161
        assert!(result.is_ok());
1✔
162
        assert_eq!(result.unwrap(), GlyphPixel::Empty);
1✔
163
    }
1✔
164

165
    #[test]
166
    fn test_glyph_get_pixel_invalid_coord() {
1✔
167
        let coord = Coord::new(17, 1);
1✔
168
        let glyph = Glyph::default();
1✔
169

1✔
170
        let result = glyph.get_pixel(coord);
1✔
171
        assert!(result.is_err());
1✔
172
        assert_matches!(
1✔
173
            result.unwrap_err(),
1✔
174
            CommonError::InvalidCoord { coord: c, size: s } if c == coord && s == glyph.size()
1✔
175
        );
1✔
176
    }
1✔
177

178
    #[test]
179
    fn test_glyph_set_pixel() {
1✔
180
        let coord = Coord::new(1, 1);
1✔
181
        let mut glyph = Glyph::default();
1✔
182

1✔
183
        let result = glyph.set_pixel(coord, GlyphPixel::Solid);
1✔
184
        assert!(result.is_ok());
1✔
185

186
        let result = glyph.get_pixel(coord);
1✔
187
        assert!(result.is_ok());
1✔
188
        assert_eq!(result.unwrap(), GlyphPixel::Solid);
1✔
189
    }
1✔
190

191
    #[test]
192
    fn test_glyph_set_pixel_invalid_coord() {
1✔
193
        let coord = Coord::new(17, 1);
1✔
194
        let mut glyph = Glyph::default();
1✔
195

1✔
196
        let result = glyph.set_pixel(coord, GlyphPixel::Solid);
1✔
197
        assert!(result.is_err());
1✔
198
        assert_matches!(
1✔
199
            result.unwrap_err(),
1✔
200
            CommonError::InvalidCoord { coord: c, size: s } if c == coord && s == glyph.size()
1✔
201
        );
1✔
202
    }
1✔
203

204
    #[test]
205
    fn test_glyph_coords() {
1✔
206
        let glyph = Glyph::default();
1✔
207

1✔
208
        let mut x = 0usize;
1✔
209
        let mut y = 0usize;
1✔
210
        for coord in glyph.coords() {
256✔
211
            assert_eq!(coord.x, x);
256✔
212
            assert_eq!(coord.y, y);
256✔
213

214
            y += 1;
256✔
215
            if y == glyph.size().width() {
256✔
216
                y = 0;
16✔
217
                x += 1;
16✔
218
            }
240✔
219
        }
220
    }
1✔
221

222
    #[test]
223
    fn test_glyph_iter() {
1✔
224
        let glyph = Glyph::default();
1✔
225
        let default_pixel = GlyphPixel::Empty;
1✔
226

227
        for pixel in glyph.iter() {
256✔
228
            assert_eq!(pixel, &default_pixel);
256✔
229
        }
230
    }
1✔
231

232
    #[test]
233
    fn test_glyph_iter_mut() {
1✔
234
        let mut glyph = Glyph::default();
1✔
235
        let new_pixel = GlyphPixel::Solid;
1✔
236

237
        for pixel in glyph.iter_mut() {
256✔
238
            *pixel = new_pixel;
256✔
239
        }
256✔
240

241
        for pixel in glyph.iter() {
256✔
242
            assert_eq!(pixel, &new_pixel);
256✔
243
        }
244
    }
1✔
245

246
    #[test]
247
    fn test_glyph_enumerate() {
1✔
248
        let glyph = Glyph::default();
1✔
249
        let mut coorditer = glyph.coords();
1✔
250
        let mut pixeliter = glyph.iter();
1✔
251

252
        for (coord, pixel) in glyph.enumerate() {
256✔
253
            assert_eq!(coord, coorditer.next().unwrap());
256✔
254
            assert_eq!(pixel, pixeliter.next().unwrap());
256✔
255
        }
256
    }
1✔
257

258
    #[test]
259
    fn test_glyph_enumerate_mut() {
1✔
260
        let mut glyph = Glyph::default();
1✔
261
        let mut coorditer = glyph.coords();
1✔
262
        let old_pixel = GlyphPixel::Empty;
1✔
263
        let new_pixel = GlyphPixel::Solid;
1✔
264

265
        for (coord, pixel) in glyph.enumerate_mut() {
256✔
266
            assert_eq!(coord, coorditer.next().unwrap());
256✔
267
            assert_eq!(pixel, &old_pixel);
256✔
268

269
            *pixel = new_pixel;
256✔
270
        }
271

272
        for pixel in glyph.iter() {
256✔
273
            assert_eq!(pixel, &new_pixel);
256✔
274
        }
275
    }
1✔
276

277
    #[test]
278
    fn test_glyph_partialeq() {
1✔
279
        let glyph_1 = Glyph::default();
1✔
280
        let mut glyph_2 = Glyph::default();
1✔
281

1✔
282
        assert_eq!(glyph_1, glyph_2);
1✔
283

284
        glyph_2.data[0] = GlyphPixel::Solid;
1✔
285
        assert_ne!(glyph_1, glyph_2);
1✔
286
    }
1✔
287

288
    #[test]
289
    fn test_glyph_debug() {
1✔
290
        let glyph = Glyph::default();
1✔
291
        let data: Vec<&GlyphPixel> = glyph.data.iter().collect();
1✔
292

1✔
293
        let expected = format!("Glyph {{ data: {:?} }}", data);
1✔
294
        let result = format!("{:?}", glyph);
1✔
295

1✔
296
        assert_eq!(result, expected);
1✔
297
    }
1✔
298
}
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

© 2025 Coveralls, Inc