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