dstar_gateway_core/session/client/
failed.rs

1//! `Failed<S, E>` — typestate-friendly error wrapper.
2
3/// A failed state transition.
4///
5/// `session` is the session in its **original** state (the
6/// transition failed, so the state did not change). `error` is the
7/// reason the transition failed. Used by fallible transitions so
8/// callers can retry without rebuilding from scratch.
9#[derive(Debug)]
10pub struct Failed<S, E> {
11    /// The session, still in its pre-transition state.
12    pub session: S,
13    /// Why the transition failed.
14    pub error: E,
15}
16
17impl<S: std::fmt::Debug, E: std::error::Error + 'static> std::fmt::Display for Failed<S, E> {
18    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19        write!(f, "session transition failed: {}", self.error)
20    }
21}
22
23impl<S: std::fmt::Debug, E: std::error::Error + 'static> std::error::Error for Failed<S, E> {
24    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
25        Some(&self.error)
26    }
27}
28
29#[cfg(test)]
30mod tests {
31    use super::*;
32
33    #[derive(Debug)]
34    struct DummySession;
35
36    #[test]
37    fn failed_carries_session_and_error() {
38        let f = Failed {
39            session: DummySession,
40            error: std::io::Error::new(std::io::ErrorKind::TimedOut, "test"),
41        };
42        let _: &dyn std::error::Error = &f;
43        assert!(f.to_string().contains("test"));
44    }
45}