screeps/enums/action_error_codes/
structurespawn_error_codes.rs

1use std::{error::Error, fmt};
2
3use num_derive::FromPrimitive;
4use serde_repr::{Deserialize_repr, Serialize_repr};
5
6use crate::{constants::ErrorCode, FromReturnCode};
7
8/// Error codes used by
9/// [StructureSpawn::spawn_creep](crate::StructureSpawn::spawn_creep).
10///
11/// [Screeps API Docs](https://docs.screeps.com/api/#StructureSpawn.spawnCreep).
12///
13/// [Screeps Engine Source Code](https://github.com/screeps/engine/blob/97c9d12385fed686655c13b09f5f2457dd83a2bf/src/game/structures.js#L1063)
14#[derive(
15    Debug, PartialEq, Eq, Clone, Copy, Hash, FromPrimitive, Deserialize_repr, Serialize_repr,
16)]
17#[repr(i8)]
18pub enum SpawnCreepErrorCode {
19    NotOwner = -1,
20    NameExists = -3,
21    Busy = -4,
22    NotEnoughEnergy = -6,
23    InvalidArgs = -10,
24    RclNotEnough = -14,
25}
26
27impl FromReturnCode for SpawnCreepErrorCode {
28    type Error = Self;
29
30    fn result_from_i8(val: i8) -> Result<(), Self::Error> {
31        let maybe_result = Self::try_result_from_i8(val);
32        #[cfg(feature = "unsafe-return-conversion")]
33        unsafe {
34            maybe_result.unwrap_unchecked()
35        }
36        #[cfg(not(feature = "unsafe-return-conversion"))]
37        maybe_result.unwrap()
38    }
39
40    fn try_result_from_i8(val: i8) -> Option<Result<(), Self::Error>> {
41        match val {
42            0 => Some(Ok(())),
43            -1 => Some(Err(SpawnCreepErrorCode::NotOwner)),
44            -3 => Some(Err(SpawnCreepErrorCode::NameExists)),
45            -4 => Some(Err(SpawnCreepErrorCode::Busy)),
46            -6 => Some(Err(SpawnCreepErrorCode::NotEnoughEnergy)),
47            -10 => Some(Err(SpawnCreepErrorCode::InvalidArgs)),
48            -14 => Some(Err(SpawnCreepErrorCode::RclNotEnough)),
49            _ => None,
50        }
51    }
52}
53
54impl fmt::Display for SpawnCreepErrorCode {
55    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56        let msg: &'static str = match self {
57            SpawnCreepErrorCode::NotOwner => "you are not the owner of this spawn",
58            SpawnCreepErrorCode::NameExists => "there is a creep with the same name already",
59            SpawnCreepErrorCode::Busy => "the spawn is already in process of spawning another creep",
60            SpawnCreepErrorCode::NotEnoughEnergy => "the spawn and its extensions contain not enough energy to create a creep with the given body",
61            SpawnCreepErrorCode::InvalidArgs => "body is not properly described or name was not provided",
62            SpawnCreepErrorCode::RclNotEnough => "your room controller level is insufficient to use this spawn",
63        };
64
65        write!(f, "{}", msg)
66    }
67}
68
69impl Error for SpawnCreepErrorCode {}
70
71impl From<SpawnCreepErrorCode> for ErrorCode {
72    fn from(value: SpawnCreepErrorCode) -> Self {
73        // Safety: SpawnCreepErrorCode is repr(i8), so we can cast it to get the
74        // discriminant value, which will match the raw return code value that ErrorCode
75        // expects.   Ref: https://doc.rust-lang.org/reference/items/enumerations.html#r-items.enum.discriminant.coercion.intro
76        // Safety: SpawnCreepErrorCode discriminants are always error code values, and
77        // thus the Result returned here will always be an `Err` variant, so we can
78        // always extract the error without panicking
79        Self::result_from_i8(value as i8).unwrap_err()
80    }
81}
82
83/// Error codes used by
84/// [StructureSpawn::recycle_creep](crate::StructureSpawn::recycle_creep).
85///
86/// [Screeps API Docs](https://docs.screeps.com/api/#StructureSpawn.recycleCreep).
87///
88/// [Screeps Engine Source Code](https://github.com/screeps/engine/blob/97c9d12385fed686655c13b09f5f2457dd83a2bf/src/game/structures.js#L1269)
89#[derive(
90    Debug, PartialEq, Eq, Clone, Copy, Hash, FromPrimitive, Deserialize_repr, Serialize_repr,
91)]
92#[repr(i8)]
93pub enum RecycleCreepErrorCode {
94    NotOwner = -1,
95    InvalidTarget = -7,
96    NotInRange = -9,
97    RclNotEnough = -14,
98}
99
100impl FromReturnCode for RecycleCreepErrorCode {
101    type Error = Self;
102
103    fn result_from_i8(val: i8) -> Result<(), Self::Error> {
104        let maybe_result = Self::try_result_from_i8(val);
105        #[cfg(feature = "unsafe-return-conversion")]
106        unsafe {
107            maybe_result.unwrap_unchecked()
108        }
109        #[cfg(not(feature = "unsafe-return-conversion"))]
110        maybe_result.unwrap()
111    }
112
113    fn try_result_from_i8(val: i8) -> Option<Result<(), Self::Error>> {
114        match val {
115            0 => Some(Ok(())),
116            -1 => Some(Err(RecycleCreepErrorCode::NotOwner)),
117            -7 => Some(Err(RecycleCreepErrorCode::InvalidTarget)),
118            -9 => Some(Err(RecycleCreepErrorCode::NotInRange)),
119            -14 => Some(Err(RecycleCreepErrorCode::RclNotEnough)),
120            _ => None,
121        }
122    }
123}
124
125impl fmt::Display for RecycleCreepErrorCode {
126    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
127        let msg: &'static str = match self {
128            RecycleCreepErrorCode::NotOwner => {
129                "you are not the owner of this spawn or the target creep"
130            }
131            RecycleCreepErrorCode::InvalidTarget => "the specified target object is not a creep",
132            RecycleCreepErrorCode::NotInRange => "the target creep is too far away",
133            RecycleCreepErrorCode::RclNotEnough => {
134                "your room controller level is insufficient to use this spawn"
135            }
136        };
137
138        write!(f, "{}", msg)
139    }
140}
141
142impl Error for RecycleCreepErrorCode {}
143
144impl From<RecycleCreepErrorCode> for ErrorCode {
145    fn from(value: RecycleCreepErrorCode) -> Self {
146        // Safety: RecycleCreepErrorCode is repr(i8), so we can cast it to get the
147        // discriminant value, which will match the raw return code value that ErrorCode
148        // expects.   Ref: https://doc.rust-lang.org/reference/items/enumerations.html#r-items.enum.discriminant.coercion.intro
149        // Safety: RecycleCreepErrorCode discriminants are always error code values, and
150        // thus the Result returned here will always be an `Err` variant, so we can
151        // always extract the error without panicking
152        Self::result_from_i8(value as i8).unwrap_err()
153    }
154}
155
156/// Error codes used by
157/// [StructureSpawn::renew_creep](crate::StructureSpawn::renew_creep).
158///
159/// [Screeps API Docs](https://docs.screeps.com/api/#StructureSpawn.renewCreep).
160///
161/// [Screeps Engine Source Code](https://github.com/screeps/engine/blob/97c9d12385fed686655c13b09f5f2457dd83a2bf/src/game/structures.js#L1237)
162#[derive(
163    Debug, PartialEq, Eq, Clone, Copy, Hash, FromPrimitive, Deserialize_repr, Serialize_repr,
164)]
165#[repr(i8)]
166pub enum RenewCreepErrorCode {
167    NotOwner = -1,
168    Busy = -4,
169    NotEnoughEnergy = -6,
170    InvalidTarget = -7,
171    Full = -8,
172    NotInRange = -9,
173    RclNotEnough = -14,
174}
175
176impl FromReturnCode for RenewCreepErrorCode {
177    type Error = Self;
178
179    fn result_from_i8(val: i8) -> Result<(), Self::Error> {
180        let maybe_result = Self::try_result_from_i8(val);
181        #[cfg(feature = "unsafe-return-conversion")]
182        unsafe {
183            maybe_result.unwrap_unchecked()
184        }
185        #[cfg(not(feature = "unsafe-return-conversion"))]
186        maybe_result.unwrap()
187    }
188
189    fn try_result_from_i8(val: i8) -> Option<Result<(), Self::Error>> {
190        match val {
191            0 => Some(Ok(())),
192            -1 => Some(Err(RenewCreepErrorCode::NotOwner)),
193            -4 => Some(Err(RenewCreepErrorCode::Busy)),
194            -6 => Some(Err(RenewCreepErrorCode::NotEnoughEnergy)),
195            -7 => Some(Err(RenewCreepErrorCode::InvalidTarget)),
196            -8 => Some(Err(RenewCreepErrorCode::Full)),
197            -9 => Some(Err(RenewCreepErrorCode::NotInRange)),
198            -14 => Some(Err(RenewCreepErrorCode::RclNotEnough)),
199            _ => None,
200        }
201    }
202}
203
204impl fmt::Display for RenewCreepErrorCode {
205    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
206        let msg: &'static str = match self {
207            RenewCreepErrorCode::NotOwner => "you are not the owner of the spawn, or the creep",
208            RenewCreepErrorCode::Busy => "the spawn is spawning another creep",
209            RenewCreepErrorCode::NotEnoughEnergy => "the spawn does not have enough energy",
210            RenewCreepErrorCode::InvalidTarget => {
211                "the specified target object is not a creep, or the creep has claim body part"
212            }
213            RenewCreepErrorCode::Full => "the target creep's time to live timer is full",
214            RenewCreepErrorCode::NotInRange => "the target creep is too far away",
215            RenewCreepErrorCode::RclNotEnough => {
216                "your room controller level is insufficient to use this spawn"
217            }
218        };
219
220        write!(f, "{}", msg)
221    }
222}
223
224impl Error for RenewCreepErrorCode {}
225
226impl From<RenewCreepErrorCode> for ErrorCode {
227    fn from(value: RenewCreepErrorCode) -> Self {
228        // Safety: RenewCreepErrorCode is repr(i8), so we can cast it to get the
229        // discriminant value, which will match the raw return code value that ErrorCode
230        // expects.   Ref: https://doc.rust-lang.org/reference/items/enumerations.html#r-items.enum.discriminant.coercion.intro
231        // Safety: RenewCreepErrorCode discriminants are always error code values, and
232        // thus the Result returned here will always be an `Err` variant, so we can
233        // always extract the error without panicking
234        Self::result_from_i8(value as i8).unwrap_err()
235    }
236}