Skip to main content

zerodds_rpc/
error.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 ZeroDDS Contributors
3
4//! Fehler-Typen fuer das DDS-RPC-Crate (C6.1.A).
5//!
6//! Wird von [`crate::common_types`], [`crate::topic_naming`],
7//! [`crate::annotations`] und [`crate::service_mapping`] geteilt.
8
9extern crate alloc;
10
11use alloc::string::{String, ToString};
12use core::fmt;
13
14/// Sammelfehler fuer die Foundation-Stufe der DDS-RPC-Implementierung.
15#[derive(Debug, Clone, PartialEq, Eq)]
16pub enum RpcError {
17    /// XCDR2-Encoding/Decoding hat das Wire-Format verletzt.
18    Codec(String),
19    /// DoS-Cap fuer Wire-Payload ueberschritten.
20    PayloadTooLarge {
21        /// Beobachtete Bytes.
22        got: usize,
23        /// Erlaubtes Maximum.
24        max: usize,
25    },
26    /// Service-Name ist leer oder enthaelt ungueltige Zeichen.
27    InvalidServiceName(String),
28    /// Methoden-Name ist leer oder ungueltig.
29    InvalidMethodName(String),
30    /// Methode ist `oneway`, hat aber ein non-`void` Return.
31    OnewayWithReturn(String),
32    /// Methode ist `oneway`, hat aber `out`/`inout`-Parameter.
33    OnewayWithOutParam {
34        /// Methoden-Name.
35        method: String,
36        /// Parameter-Name.
37        param: String,
38    },
39    /// Doppelte Methoden-Namen in einem `interface`.
40    DuplicateMethod(String),
41    /// Doppelte Parameter-Namen in einer Methode.
42    DuplicateParam {
43        /// Methoden-Name.
44        method: String,
45        /// Parameter-Name.
46        param: String,
47    },
48    /// Unbekannter `RemoteExceptionCode_t`-Diskriminator beim Decode.
49    UnknownExceptionCode(u32),
50    /// Service ohne Methoden — kein Endpoint kann gebaut werden.
51    EmptyService(String),
52    /// Request-Reply-Wartezeit ueberschritten (Foundation-Stufe C6.1.C).
53    Timeout,
54    /// Server-Side hat eine `RemoteExceptionCode` ungleich `Ok` zurueckgegeben.
55    /// Der Wert ist der raw Diskriminator — Caller kann
56    /// [`crate::common_types::RemoteExceptionCode::from_u32`] nutzen, um in
57    /// das Enum zu mappen.
58    RemoteException(u32),
59    /// Doppelt vergebener `service_instance_name` auf demselben Participant.
60    DuplicateInstanceName(String),
61    /// Generischer DCPS-Aufruf-Fehler (Topic-Anlegen, Writer-Create etc.).
62    Dcps(String),
63    /// QoS-Profile nicht in der `DdsXml`-Library gefunden.
64    QosProfileNotFound(String),
65}
66
67impl fmt::Display for RpcError {
68    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69        match self {
70            Self::Codec(s) => write!(f, "rpc codec error: {s}"),
71            Self::PayloadTooLarge { got, max } => {
72                write!(f, "rpc payload too large: {got} > {max}")
73            }
74            Self::InvalidServiceName(s) => write!(f, "invalid service name: {s:?}"),
75            Self::InvalidMethodName(s) => write!(f, "invalid method name: {s:?}"),
76            Self::OnewayWithReturn(m) => {
77                write!(f, "oneway method {m:?} must return void")
78            }
79            Self::OnewayWithOutParam { method, param } => write!(
80                f,
81                "oneway method {method:?} must not have out/inout param {param:?}"
82            ),
83            Self::DuplicateMethod(m) => write!(f, "duplicate method {m:?}"),
84            Self::DuplicateParam { method, param } => {
85                write!(f, "duplicate parameter {param:?} in method {method:?}")
86            }
87            Self::UnknownExceptionCode(v) => {
88                write!(f, "unknown RemoteExceptionCode_t discriminator {v}")
89            }
90            Self::EmptyService(n) => write!(f, "service {n:?} has no methods"),
91            Self::Timeout => write!(f, "rpc request timed out"),
92            Self::RemoteException(code) => {
93                write!(f, "remote exception code {code}")
94            }
95            Self::DuplicateInstanceName(n) => {
96                write!(f, "duplicate service instance name {n:?}")
97            }
98            Self::Dcps(s) => write!(f, "dcps error: {s}"),
99            Self::QosProfileNotFound(n) => {
100                write!(f, "qos profile {n:?} not found")
101            }
102        }
103    }
104}
105
106#[cfg(feature = "std")]
107impl std::error::Error for RpcError {}
108
109impl RpcError {
110    /// Convenience: Konstruktor fuer Codec-Fehler aus statischer Message.
111    #[must_use]
112    pub fn codec(msg: &str) -> Self {
113        Self::Codec(msg.to_string())
114    }
115}
116
117/// Result-Alias.
118pub type RpcResult<T> = core::result::Result<T, RpcError>;