oc_wasm_opencomputers/
error.rs

1//! Provides an error type used for higher level calls.
2
3use core::fmt::{Display, Formatter};
4
5/// The errors that a component call can return.
6#[derive(Clone, Debug, Eq, Hash, PartialEq)]
7pub enum Error {
8	/// The call was addressed to a component that does not exist, is not accessible, or is of the
9	/// wrong type.
10	///
11	/// The underlying syscall error is encapsulated.
12	BadComponent(oc_wasm_safe::error::Error),
13
14	/// An unsupported screen resolution, viewport size, or screen coordinate was requested.
15	BadCoordinate,
16
17	/// An unsupported colour depth was requested.
18	BadDepth,
19
20	/// The filename passed to a function is structurally invalid to be a filename.
21	BadFilename,
22
23	/// The character to use to fill the screen lies outside the basic multilingual plane and
24	/// therefore cannot be used for filling.
25	BadFillCharacter,
26
27	/// An index number is outside the range of slots for an inventory or tanks for a
28	/// fluid-containing block.
29	///
30	/// In the case of item inventories, this is only returned if the block is in fact an
31	/// inventory; [`NoInventory`](Self::NoInventory) is returned for non-inventories. In the case
32	/// of fluid containers, this is also returned if the block is not a fluid container at all (it
33	/// is treated as a fluid container with zero tanks), but not if the block is in an unloaded
34	/// chunk.
35	BadInventorySlot,
36
37	/// An item is not usable for the requested purpose.
38	///
39	/// For example, an item that does not hold fluid cannot have its fluid level or capacity
40	/// queried.
41	BadItem,
42
43	/// A set-colour request tried to set a colour by palette index, and the palette index was
44	/// unacceptable. This could be because the palette index was outside the range of the palette
45	/// for the current bit depth, or it could be because the current bit depth does not support a
46	/// palette at all.
47	BadPaletteIndex,
48
49	/// The address specified when binding a GPU does not exist, is inaccessible, or is not a
50	/// screen; or, a GPU operation which requires a screen was executed when the GPU is unbound or
51	/// the screen to which it was bound has been disconnected.
52	BadScreen,
53
54	/// The robot cannot move because there is something in the way.
55	Blocked(super::robot::BlockContent),
56
57	/// The checksum passed when trying to make an EEPROM read-only does not match the checksum of
58	/// the contents of the EEPROM.
59	ChecksumMismatch,
60
61	/// The data (e.g. to write to a file or EEPROM or send over a communication interface) is too
62	/// large.
63	DataTooLarge,
64
65	/// The named file or directory does not exist.
66	FileNotFound,
67
68	/// The robot tried to move to a position that is too far away from support (and does not have
69	/// a suitable hover upgrade to allow such movement), tried to move into an unloaded chunk, or
70	/// the destination is otherwise unsuitable for a reason other than there being something in
71	/// the way.
72	ImpossibleMove,
73
74	/// An attempt was made to move an item or fluid into an inventory slot or tank, but it could
75	/// not be inserted because the slot or tank is full, or the existing contents are not
76	/// compatible with the new addition.
77	InventoryFull,
78
79	/// A seek in a file would place the file pointer at a negative position.
80	NegativeSeek,
81
82	/// There is no item in an inventory slot when one is required.
83	NoItem,
84
85	/// There is no inventory in the specified location. This includes if the inventory is in an
86	/// unloaded chunk.
87	///
88	/// This is also returned when attempting to access a fluid tank in an unloaded chunk, but not
89	/// when attempting to access a fluid tank in a block that does not contain any tanks; in the
90	/// latter case, [`BadInventorySlot`](Self::BadInventorySlot) is used instead.
91	NoInventory,
92
93	/// The computer does not have enough energy to perform the operation.
94	NotEnoughEnergy,
95
96	/// The storage (e.g. EEPROM or filesystem) cannot be written to because it is read-only.
97	StorageReadOnly,
98
99	/// There are too many open descriptors.
100	TooManyDescriptors,
101
102	/// There are too many listening network ports.
103	TooManyOpenPorts,
104
105	/// There are too many parts in a packet.
106	TooManyParts,
107
108	/// The operation is not supported for this component.
109	///
110	/// For example:
111	/// * An attempt was made to set a filesystem’s label, but this particular filesystem does not
112	///   support labels.
113	/// * An attempt was made to access item stack information in an inventory, but detailed item
114	///   information access is disabled in the configuration file.
115	Unsupported,
116
117	/// The operation failed but no more detailed information is available at the type level. The
118	/// individual method may document more specific reasons for this error to appear.
119	Failed,
120}
121
122impl Error {
123	/// Returns a string describing the error.
124	#[must_use = "This function is only useful for its return value"]
125	pub fn as_str(&self) -> &'static str {
126		match self {
127			Self::BadComponent(_) => "nonexistent or incorrect component",
128			Self::BadCoordinate => "bad coordinate",
129			Self::BadDepth => "bad depth",
130			Self::BadFilename => "bad filename",
131			Self::BadFillCharacter => "bad fill character",
132			Self::BadInventorySlot => "bad inventory slot",
133			Self::BadItem => "bad item",
134			Self::BadPaletteIndex => "bad palette index",
135			Self::BadScreen => "bad screen",
136			Self::Blocked(super::robot::BlockContent::Entity) => "blocked by entity",
137			Self::Blocked(super::robot::BlockContent::Air) => "blocked by air",
138			Self::Blocked(super::robot::BlockContent::Liquid) => "blocked by liquid",
139			Self::Blocked(super::robot::BlockContent::Replaceable) => "blocked by replaceable",
140			Self::Blocked(super::robot::BlockContent::Passable) => "blocked by passable",
141			Self::Blocked(super::robot::BlockContent::Solid) => "blocked by solid",
142			Self::ChecksumMismatch => "checksum mismatch",
143			Self::DataTooLarge => "data too large",
144			Self::FileNotFound => "file not found",
145			Self::ImpossibleMove => "impossible move",
146			Self::InventoryFull => "inventory full",
147			Self::NegativeSeek => "seek to negative position",
148			Self::NoInventory => "no inventory",
149			Self::NoItem => "no item",
150			Self::NotEnoughEnergy => "not enough energy",
151			Self::StorageReadOnly => "storage is read-only",
152			Self::TooManyDescriptors => "too many descriptors",
153			Self::TooManyOpenPorts => "too many open ports",
154			Self::TooManyParts => "too many parts",
155			Self::Unsupported => "unsupported",
156			Self::Failed => "failed",
157		}
158	}
159}
160
161impl Display for Error {
162	fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> {
163		match self {
164			Self::BadComponent(e) => write!(f, "nonexistent or incorrect component: {e}"),
165			_ => self.as_str().fmt(f),
166		}
167	}
168}
169
170#[cfg(feature = "std")]
171impl std::error::Error for Error {
172	fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
173		match self {
174			Self::BadComponent(underlying) => Some(underlying),
175			Self::BadCoordinate
176			| Self::BadDepth
177			| Self::BadFilename
178			| Self::BadFillCharacter
179			| Self::BadInventorySlot
180			| Self::BadItem
181			| Self::BadPaletteIndex
182			| Self::BadScreen
183			| Self::Blocked(_)
184			| Self::ChecksumMismatch
185			| Self::DataTooLarge
186			| Self::FileNotFound
187			| Self::ImpossibleMove
188			| Self::InventoryFull
189			| Self::NegativeSeek
190			| Self::NoInventory
191			| Self::NoItem
192			| Self::NotEnoughEnergy
193			| Self::StorageReadOnly
194			| Self::TooManyDescriptors
195			| Self::TooManyOpenPorts
196			| Self::TooManyParts
197			| Self::Unsupported
198			| Self::Failed => None,
199		}
200	}
201}
202
203impl From<oc_wasm_safe::error::Error> for Error {
204	fn from(source: oc_wasm_safe::error::Error) -> Self {
205		match source {
206			oc_wasm_safe::error::Error::BadParameters | oc_wasm_safe::error::Error::Other => {
207				Self::Failed
208			}
209			oc_wasm_safe::error::Error::TooManyDescriptors => Self::TooManyDescriptors,
210			_ => Self::BadComponent(source),
211		}
212	}
213}
214
215impl From<oc_wasm_safe::component::MethodCallError<'_>> for Error {
216	fn from(source: oc_wasm_safe::component::MethodCallError<'_>) -> Self {
217		source.simplify().into()
218	}
219}