1
1
use std:: { error:: Error , fmt} ;
2
2
3
- use serde:: { de , Deserialize , Deserializer , Serialize , Serializer } ;
3
+ use serde:: { Deserialize , Serialize } ;
4
4
5
- use crate :: constants:: { Direction , ROOM_SIZE } ;
6
-
7
- pub ( crate ) const ROOM_AREA : usize = ( ROOM_SIZE as usize ) * ( ROOM_SIZE as usize ) ;
5
+ use crate :: constants:: ROOM_SIZE ;
8
6
9
7
#[ derive( Debug , Clone , Copy ) ]
10
- pub struct OutOfBoundsError ( u8 ) ;
8
+ pub struct OutOfBoundsError ( pub u8 ) ;
11
9
12
10
impl fmt:: Display for OutOfBoundsError {
13
11
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
@@ -17,65 +15,13 @@ impl fmt::Display for OutOfBoundsError {
17
15
18
16
impl Error for OutOfBoundsError { }
19
17
20
- /// Converts a [`RoomXY`] coordinate pair to a linear index appropriate for use
21
- /// with the internal representation of a [`CostMatrix`] or [`LocalCostMatrix`].
22
- ///
23
- /// [`CostMatrix`]: crate::objects::CostMatrix
24
- /// [`LocalCostMatrix`]: crate::local::LocalCostMatrix
25
- #[ inline]
26
- pub const fn xy_to_linear_index ( xy : RoomXY ) -> usize {
27
- xy. x . u8 ( ) as usize * ROOM_SIZE as usize + xy. y . u8 ( ) as usize
28
- }
29
-
30
- /// Converts a linear index from the internal representation of a [`CostMatrix`]
31
- /// or [`LocalCostMatrix`] to a [`RoomXY`] coordinate pair for the position the
32
- /// index represents.
33
- ///
34
- /// [`CostMatrix`]: crate::objects::CostMatrix
35
- /// [`LocalCostMatrix`]: crate::local::LocalCostMatrix
36
- #[ inline]
37
- pub fn linear_index_to_xy ( idx : usize ) -> RoomXY {
38
- assert ! ( idx < ROOM_AREA , "Out of bounds index: {idx}" ) ;
39
- // SAFETY: bounds checking above ensures both are within range.
40
- RoomXY {
41
- x : unsafe { RoomCoordinate :: unchecked_new ( ( idx / ( ROOM_SIZE as usize ) ) as u8 ) } ,
42
- y : unsafe { RoomCoordinate :: unchecked_new ( ( idx % ( ROOM_SIZE as usize ) ) as u8 ) } ,
43
- }
44
- }
45
-
46
- /// Converts a [`RoomXY`] coordinate pair to a terrain index appropriate for use
47
- /// with the internal representation of [`RoomTerrain`] or [`LocalRoomTerrain`].
48
- ///
49
- /// [`RoomTerrain`]: crate::objects::RoomTerrain
50
- /// [`LocalRoomTerrain`]: crate::local::LocalRoomTerrain
51
- #[ inline]
52
- pub const fn xy_to_terrain_index ( xy : RoomXY ) -> usize {
53
- xy. y . u8 ( ) as usize * ROOM_SIZE as usize + xy. x . u8 ( ) as usize
54
- }
55
-
56
- /// Converts a terrain index from the internal representation of a
57
- /// [`RoomTerrain`] or [`LocalRoomTerrain`] to a [`RoomXY`] coordinate pair for
58
- /// the position the index represents.
59
- ///
60
- /// [`RoomTerrain`]: crate::objects::RoomTerrain
61
- /// [`LocalRoomTerrain`]: crate::local::LocalRoomTerrain
62
- #[ inline]
63
- pub fn terrain_index_to_xy ( idx : usize ) -> RoomXY {
64
- assert ! ( idx < ROOM_AREA , "Out of bounds index: {idx}" ) ;
65
- // SAFETY: bounds checking above ensures both are within range.
66
- RoomXY {
67
- x : unsafe { RoomCoordinate :: unchecked_new ( ( idx % ( ROOM_SIZE as usize ) ) as u8 ) } ,
68
- y : unsafe { RoomCoordinate :: unchecked_new ( ( idx / ( ROOM_SIZE as usize ) ) as u8 ) } ,
69
- }
70
- }
71
-
72
18
/// An X or Y coordinate in a room, restricted to the valid range of
73
19
/// coordinates.
74
20
#[ derive(
75
21
Debug , Hash , Default , Clone , Copy , PartialEq , Eq , PartialOrd , Ord , Serialize , Deserialize ,
76
22
) ]
77
23
#[ serde( try_from = "u8" , into = "u8" ) ]
78
- pub struct RoomCoordinate ( u8 ) ;
24
+ pub struct RoomCoordinate ( pub u8 ) ;
79
25
80
26
impl RoomCoordinate {
81
27
/// Create a `RoomCoordinate` from a `u8`, returning an error if the
@@ -110,7 +56,7 @@ impl RoomCoordinate {
110
56
}
111
57
112
58
/// Get whether this coordinate represents an edge position (0 or 49)
113
- pub const fn is_edge ( self ) -> bool {
59
+ pub const fn is_room_edge ( self ) -> bool {
114
60
self . 0 == 0 || self . 0 == ROOM_SIZE - 1
115
61
}
116
62
@@ -180,139 +126,6 @@ impl fmt::Display for RoomCoordinate {
180
126
}
181
127
}
182
128
183
- /// An X/Y pair representing a given coordinate relative to any room.
184
- #[ derive( Debug , Default , Hash , Clone , Copy , PartialEq , Eq ) ]
185
- pub struct RoomXY {
186
- pub x : RoomCoordinate ,
187
- pub y : RoomCoordinate ,
188
- }
189
-
190
- impl RoomXY {
191
- /// Create a `RoomXY` from a pair of `u8`, without checking whether it's in
192
- /// the range of valid values.
193
- ///
194
- /// # Safety
195
- /// Calling this method with `x >= ROOM_SIZE` or `y >= ROOM_SIZE` can result
196
- /// in undefined behaviour when the resulting `RoomXY` is used.
197
- #[ inline]
198
- pub unsafe fn unchecked_new ( x : u8 , y : u8 ) -> Self {
199
- RoomXY {
200
- x : RoomCoordinate :: unchecked_new ( x) ,
201
- y : RoomCoordinate :: unchecked_new ( y) ,
202
- }
203
- }
204
-
205
- /// Get whether this coordinate pair represents an edge position (0 or 49
206
- /// for either coordinate)
207
- pub const fn is_edge ( self ) -> bool {
208
- self . x . is_edge ( ) || self . y . is_edge ( )
209
- }
210
-
211
- /// Get the coordinate adjusted by a certain value, returning `None` if the
212
- /// result is outside the valid room area.
213
- ///
214
- /// Example usage:
215
- ///
216
- /// ```
217
- /// use screeps::local::RoomXY;
218
- ///
219
- /// let zero = unsafe { RoomXY::unchecked_new(0, 0) };
220
- /// let one = unsafe { RoomXY::unchecked_new(1, 1) };
221
- /// let forty_nine = unsafe { RoomXY::unchecked_new(49, 49) };
222
- ///
223
- /// assert_eq!(zero.checked_add((1, 1)), Some(one));
224
- /// assert_eq!(zero.checked_add((-1, 0)), None);
225
- /// assert_eq!(zero.checked_add((49, 49)), Some(forty_nine));
226
- /// assert_eq!(forty_nine.checked_add((1, 1)), None);
227
- /// ```
228
- pub fn checked_add ( self , rhs : ( i8 , i8 ) ) -> Option < RoomXY > {
229
- let x = match self . x . checked_add ( rhs. 0 ) {
230
- Some ( x) => x,
231
- None => return None ,
232
- } ;
233
- let y = match self . y . checked_add ( rhs. 1 ) {
234
- Some ( y) => y,
235
- None => return None ,
236
- } ;
237
- Some ( RoomXY { x, y } )
238
- }
239
-
240
- /// Get the coordinate adjusted by a certain value, saturating at the edges
241
- /// of the room if the result would be outside the valid room area.
242
- ///
243
- /// Example usage:
244
- ///
245
- /// ```
246
- /// use screeps::local::RoomXY;
247
- ///
248
- /// let zero = unsafe { RoomXY::unchecked_new(0, 0) };
249
- /// let one = unsafe { RoomXY::unchecked_new(1, 1) };
250
- /// let forty_nine = unsafe { RoomXY::unchecked_new(49, 49) };
251
- ///
252
- /// assert_eq!(zero.saturating_add((1, 1)), one);
253
- /// assert_eq!(zero.saturating_add((-1, 0)), zero);
254
- /// assert_eq!(zero.saturating_add((49, 49)), forty_nine);
255
- /// assert_eq!(zero.saturating_add((i8::MAX, i8::MAX)), forty_nine);
256
- /// assert_eq!(forty_nine.saturating_add((1, 1)), forty_nine);
257
- /// assert_eq!(forty_nine.saturating_add((i8::MIN, i8::MIN)), zero);
258
- /// ```
259
- pub fn saturating_add ( self , rhs : ( i8 , i8 ) ) -> RoomXY {
260
- let x = self . x . saturating_add ( rhs. 0 ) ;
261
- let y = self . y . saturating_add ( rhs. 1 ) ;
262
- RoomXY { x, y }
263
- }
264
-
265
- /// Get the neighbor of a given `RoomXY` in the given direction, returning
266
- /// `None` if the result is outside the valid room area.
267
- ///
268
- /// Example usage:
269
- ///
270
- /// ```
271
- /// use screeps::{constants::Direction::*, local::RoomXY};
272
- ///
273
- /// let zero = unsafe { RoomXY::unchecked_new(0, 0) };
274
- /// let one = unsafe { RoomXY::unchecked_new(1, 1) };
275
- /// let forty_nine = unsafe { RoomXY::unchecked_new(49, 49) };
276
- ///
277
- /// assert_eq!(zero.checked_add_direction(BottomRight), Some(one));
278
- /// assert_eq!(zero.checked_add_direction(TopLeft), None);
279
- /// assert_eq!(one.checked_add_direction(TopLeft), Some(zero));
280
- /// assert_eq!(forty_nine.checked_add_direction(BottomRight), None);
281
- /// ```
282
- pub fn checked_add_direction ( self , rhs : Direction ) -> Option < RoomXY > {
283
- let ( dx, dy) = rhs. into ( ) ;
284
- self . checked_add ( ( dx as i8 , dy as i8 ) )
285
- }
286
-
287
- /// Get the neighbor of a given `RoomXY` in the given direction, saturating
288
- /// at the edges if the result is outside the valid room area.
289
- ///
290
- /// Example usage:
291
- ///
292
- /// ```
293
- /// use screeps::{constants::Direction::*, local::RoomXY};
294
- ///
295
- /// let zero = unsafe { RoomXY::unchecked_new(0, 0) };
296
- /// let one = unsafe { RoomXY::unchecked_new(1, 1) };
297
- /// let forty_nine = unsafe { RoomXY::unchecked_new(49, 49) };
298
- ///
299
- /// assert_eq!(zero.saturating_add_direction(BottomRight), one);
300
- /// assert_eq!(zero.saturating_add_direction(TopLeft), zero);
301
- /// assert_eq!(one.saturating_add_direction(TopLeft), zero);
302
- /// assert_eq!(forty_nine.saturating_add_direction(BottomRight), forty_nine);
303
- /// ```
304
- pub fn saturating_add_direction ( self , rhs : Direction ) -> RoomXY {
305
- let ( dx, dy) = rhs. into ( ) ;
306
- self . saturating_add ( ( dx as i8 , dy as i8 ) )
307
- }
308
- }
309
-
310
- impl fmt:: Display for RoomXY {
311
- fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
312
- write ! ( f, "({}, {})" , self . x, self . y)
313
- }
314
- }
315
-
316
129
impl From < RoomCoordinate > for u8 {
317
130
fn from ( coord : RoomCoordinate ) -> u8 {
318
131
coord. 0
@@ -326,85 +139,3 @@ impl TryFrom<u8> for RoomCoordinate {
326
139
RoomCoordinate :: new ( coord)
327
140
}
328
141
}
329
-
330
- impl From < RoomXY > for ( u8 , u8 ) {
331
- fn from ( xy : RoomXY ) -> ( u8 , u8 ) {
332
- ( xy. x . 0 , xy. y . 0 )
333
- }
334
- }
335
-
336
- impl TryFrom < ( u8 , u8 ) > for RoomXY {
337
- type Error = OutOfBoundsError ;
338
-
339
- fn try_from ( xy : ( u8 , u8 ) ) -> Result < RoomXY , OutOfBoundsError > {
340
- Ok ( RoomXY {
341
- x : RoomCoordinate :: try_from ( xy. 0 ) ?,
342
- y : RoomCoordinate :: try_from ( xy. 1 ) ?,
343
- } )
344
- }
345
- }
346
-
347
- impl From < ( RoomCoordinate , RoomCoordinate ) > for RoomXY {
348
- fn from ( xy : ( RoomCoordinate , RoomCoordinate ) ) -> RoomXY {
349
- RoomXY { x : xy. 0 , y : xy. 1 }
350
- }
351
- }
352
-
353
- impl From < RoomXY > for ( RoomCoordinate , RoomCoordinate ) {
354
- fn from ( xy : RoomXY ) -> ( RoomCoordinate , RoomCoordinate ) {
355
- ( xy. x , xy. y )
356
- }
357
- }
358
-
359
- #[ derive( Serialize , Deserialize ) ]
360
- struct ReadableXY {
361
- x : RoomCoordinate ,
362
- y : RoomCoordinate ,
363
- }
364
-
365
- impl From < ReadableXY > for RoomXY {
366
- fn from ( ReadableXY { x, y } : ReadableXY ) -> RoomXY {
367
- RoomXY { x, y }
368
- }
369
- }
370
-
371
- impl From < RoomXY > for ReadableXY {
372
- fn from ( RoomXY { x, y } : RoomXY ) -> ReadableXY {
373
- ReadableXY { x, y }
374
- }
375
- }
376
-
377
- impl Serialize for RoomXY {
378
- fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
379
- where
380
- S : Serializer ,
381
- {
382
- if serializer. is_human_readable ( ) {
383
- ReadableXY :: from ( * self ) . serialize ( serializer)
384
- } else {
385
- let xy: ( u8 , u8 ) = ( * self ) . into ( ) ;
386
- let packed: u16 = ( ( xy. 0 as u16 ) << 8 ) | ( xy. 1 as u16 ) ;
387
- packed. serialize ( serializer)
388
- }
389
- }
390
- }
391
-
392
- impl < ' de > Deserialize < ' de > for RoomXY {
393
- fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
394
- where
395
- D : Deserializer < ' de > ,
396
- {
397
- if deserializer. is_human_readable ( ) {
398
- ReadableXY :: deserialize ( deserializer) . map ( Into :: into)
399
- } else {
400
- let packed = u16:: deserialize ( deserializer) ?;
401
- let xy = ( ( ( packed >> 8 ) & 0xFF ) as u8 , ( packed & 0xFF ) as u8 ) ;
402
- RoomXY :: try_from ( xy) . map_err ( |err : OutOfBoundsError | {
403
- de:: Error :: invalid_value (
404
- de:: Unexpected :: Unsigned ( err. 0 as u64 ) ,
405
- & format ! ( "a non-negative integer less-than {ROOM_SIZE}" ) . as_str ( ) ,
406
- )
407
- } )
408
- }
409
- }
410
- }
0 commit comments