Skip to main content

gproxy_protocol/transform/identity/
error.rs

1use std::fmt;
2
3/// Errors from flow identity allocation and scoped identity persistence.
4#[derive(Debug)]
5pub enum IdentityError {
6    InvalidIdentity(String),
7    ResourceIdRequired,
8    NoGeneratedPrefix,
9    DuplicateSourceIdentity {
10        role: IdentityRoleName,
11        dialect: String,
12        source_id: String,
13        first_index: u64,
14        duplicate_index: u64,
15    },
16    AmbiguousSourceIdentity(String),
17    Collision(String),
18    MissingState,
19    ExpiredState,
20    Conflict,
21    StateStore(crate::capability::CapabilityError),
22    StateEncoding(serde_json::Error),
23}
24
25/// String form of a role keeps errors independent of future role additions.
26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
27pub enum IdentityRoleName {
28    Response,
29    Message,
30    OutputItem,
31    ToolCall,
32    Resource,
33}
34
35impl fmt::Display for IdentityError {
36    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37        match self {
38            Self::InvalidIdentity(reason) => write!(f, "invalid identity: {reason}"),
39            Self::ResourceIdRequired => f.write_str("resource identity requires a source id"),
40            Self::NoGeneratedPrefix => {
41                f.write_str("identity role has no configured generated prefix")
42            }
43            Self::DuplicateSourceIdentity {
44                role,
45                dialect,
46                source_id,
47                first_index,
48                duplicate_index,
49            } => write!(
50                f,
51                "duplicate {role:?} source id {source_id:?} in {dialect}: logical indexes {first_index} and {duplicate_index} are ambiguous"
52            ),
53            Self::AmbiguousSourceIdentity(reason) => {
54                write!(f, "ambiguous source identity: {reason}")
55            }
56            Self::Collision(id) => write!(f, "identity collision could not be resolved: {id}"),
57            Self::MissingState => f.write_str("identity state is missing"),
58            Self::ExpiredState => f.write_str("identity state has expired"),
59            Self::Conflict => f.write_str("identity state compare-and-exchange conflicted"),
60            Self::StateStore(reason) => write!(f, "identity state store failed: {reason}"),
61            Self::StateEncoding(reason) => write!(f, "identity state encoding failed: {reason}"),
62        }
63    }
64}
65
66impl std::error::Error for IdentityError {
67    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
68        match self {
69            Self::StateStore(error) => Some(error),
70            Self::StateEncoding(error) => Some(error),
71            _ => None,
72        }
73    }
74}