Skip to main content

aetheris_protocol/
error.rs

1//! Protocol error types using thiserror.
2
3use crate::types::{ClientId, ComponentKind, NetworkId};
4
5/// Errors from the transport layer.
6#[derive(Debug, thiserror::Error)]
7pub enum TransportError {
8    /// The specified client is not connected.
9    #[error("Client {0:?} is not connected")]
10    ClientNotConnected(ClientId),
11    /// The datagram sent is larger than the MTU.
12    #[error("Datagram exceeds MTU limit ({size} > {max})")]
13    PayloadTooLarge {
14        /// The calculated size.
15        size: usize,
16        /// The MTU limit.
17        max: usize,
18    },
19    /// An underlying I/O error occurred.
20    #[error("Transport I/O error: {0}")]
21    Io(#[from] std::io::Error),
22    /// A mutex was poisoned.
23    #[error("Lock poisoned")]
24    LockPoisoned,
25}
26
27/// Errors from the serialization layer.
28#[derive(Debug, thiserror::Error)]
29pub enum EncodeError {
30    /// The buffer was insufficiently sized.
31    #[error("Buffer overflow: need {needed} bytes, have {available}")]
32    BufferOverflow {
33        /// Needed bytes.
34        needed: usize,
35        /// Provided bytes.
36        available: usize,
37    },
38    /// The payload could not be parsed cleanly.
39    #[error("Malformed payload at byte offset {offset}: {message}")]
40    MalformedPayload {
41        /// The byte offset at which parsing failed.
42        offset: usize,
43        /// The descriptive error message.
44        message: String,
45    },
46    /// Discovered a component kind that is not registered.
47    #[error("Unknown component kind: {0:?}")]
48    UnknownComponent(ComponentKind),
49    /// An underlying I/O error occurred.
50    #[error("I/O error: {0}")]
51    Io(#[from] std::io::Error),
52}
53
54/// Errors from the ECS adapter.
55#[derive(Debug, thiserror::Error)]
56pub enum WorldError {
57    /// An entity was required but not found.
58    #[error("Entity {0:?} not found")]
59    EntityNotFound(NetworkId),
60    /// The entity already exists.
61    #[error("Entity {0:?} already exists")]
62    EntityAlreadyExists(NetworkId),
63}
64
65#[cfg(test)]
66mod tests {
67    use super::*;
68    use std::io::{Error as IoError, ErrorKind};
69
70    #[test]
71    fn test_error_displays() {
72        // TransportError
73        let err1 = TransportError::ClientNotConnected(ClientId(42));
74        assert_eq!(err1.to_string(), "Client ClientId(42) is not connected");
75
76        let err2 = TransportError::PayloadTooLarge {
77            size: 1500,
78            max: 1200,
79        };
80        assert_eq!(err2.to_string(), "Datagram exceeds MTU limit (1500 > 1200)");
81
82        let err3 = TransportError::Io(IoError::new(ErrorKind::ConnectionReset, "connection reset"));
83        assert_eq!(err3.to_string(), "Transport I/O error: connection reset");
84
85        // EncodeError
86        let err4 = EncodeError::BufferOverflow {
87            needed: 256,
88            available: 128,
89        };
90        assert_eq!(
91            err4.to_string(),
92            "Buffer overflow: need 256 bytes, have 128"
93        );
94
95        let err5 = EncodeError::MalformedPayload {
96            offset: 10,
97            message: "unexpected EOF".to_string(),
98        };
99        assert_eq!(
100            err5.to_string(),
101            "Malformed payload at byte offset 10: unexpected EOF"
102        );
103
104        let err6 = EncodeError::UnknownComponent(ComponentKind(99));
105        assert_eq!(
106            err6.to_string(),
107            "Unknown component kind: ComponentKind(99)"
108        );
109
110        // WorldError
111        let err7 = WorldError::EntityNotFound(NetworkId(123));
112        assert_eq!(err7.to_string(), "Entity NetworkId(123) not found");
113
114        let err8 = WorldError::EntityAlreadyExists(NetworkId(456));
115        assert_eq!(err8.to_string(), "Entity NetworkId(456) already exists");
116    }
117}