1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
use thiserror::Error;

#[derive(Error, Debug)]
pub enum FsdMessageParseError {
    #[error("invalid field count. Expected {0}, found {1}.")]
    InvalidFieldCount(usize, usize),
    #[error("{0} is not a valid rating")]
    InvalidRating(String),
    #[error("{0} is not a valid protocol revision")]
    InvalidProtocolRevison(String),
    #[error("{0} is not a valid flight rules")]
    InvalidFlightRules(String),
    #[error("{0} is not a valid simulator type")]
    InvalidSimulatorType(String),
    #[error("{0} is not a valid ATC type")]
    InvalidAtcType(String),
    #[error("{0} is not a valid time")]
    InvalidTime(String),
    #[error("{0} is not a valid minute")]
    InvalidMinute(String),
    #[error("{0} is not a valid index")]
    InvalidIndex(String),
    #[error("{0} is not a valid ATC frequency")]
    InvalidFrequency(String),
    #[error("{0} is not a valid visibility range")]
    InvalidVisRange(String),
    #[error("{0} is not a valid lat / long coordinate")]
    InvalidCoordinate(String),
    #[error("{0} is not a transponder mode")]
    InvalidTransponderMode(String),
    #[error("{0} is not a transponder code")]
    InvalidTransponderCode(String),
    #[error("Unable to parse aircraft config: {0}")]
    InvalidAircraftConfig(String),
    #[error("{0} is not a valid pitch / bank / heading number")]
    InvalidPitchBankHeading(String),
    #[error("{0} is not a valid altitude")]
    InvalidAltitude(String),
    #[error("{0} is not a valid altitude difference")]
    InvalidAltitudeDifference(String),
    #[error("{0} is not a valid voice capability")]
    InvalidVoiceCapability(String),
    #[error("{0} is not a valid speed")]
    InvalidSpeed(String),
    #[error("{0} is not a valid client ID")]
    InvalidClientID(String),
    #[error("{0} is not a valid version number part")]
    InvalidVersionNumber(String),
    #[error("{0} is not a valid nosewheel angle")]
    InvalidNosewheelAngle(String),
    #[error("{0} is not a valid position velocity")]
    InvalidPositionVelocity(String),
    #[error("Unknown message type: {0}")]
    UnknownMessageType(String),
    #[error("{0} is not a valid ping time")]
    InvalidPingTime(String),
    #[error("{0} is not a valid server error")]
    InvalidServerError(String),
    #[error("{0} is not a valid client query type")]
    InvalidClientQueryType(String),
    #[error("{0} is not a valid new ATIS message")]
    InvalidNewAtisMessage(String),
    #[error("{0} is not a valid valid ATC status")]
    InvalidValidAtcStatus(String),
    #[error("{0} is not a valid valid ATIS line")]
    InvalidATISLine(String),
    #[error("{0} is not a valid valid shared state type")]
    InvalidSharedStateType(String),
    #[error("{0} is not a valid client capability")]
    InvalidClientCapability(String),
}

/// An error message received from the FSD server
#[derive(Debug, Clone, Error)]
pub enum FsdError {
    /// Attempted to log in with a callsign that is already in use
    #[error("Callsign in use")]
    CallsignInUse,
    /// Attempted to log in with an invalid callsign
    #[error("Invalid callsign")]
    InvalidCallsign,
    /// Client attempted to register itself more than once on server
    #[error("Already registered")]
    AlreadyRegistered,
    /// Packet with invalid syntax sent to the FSD server
    #[error("Syntax error")]
    SyntaxError,
    /// Client attempted to send a server message with the wrong 'from' callsign
    #[error("Invalid source callsign")]
    InvalidSourceCallsign,
    /// Attempted to log into the server with an invalid CID or password
    #[error("Invalid CID / password")]
    InvalidCidPassword,
    /// Attempted to perform an action (e.g. kill, flight plan request) on an invalid callsign
    #[error("No such callsign as {0}")]
    NoSuchCallsign(String),
    /// Attempted to retrieve a flight plan but no flight plan exists for that callsign
    #[error("No flight plan for {0}")]
    NoFlightPlan(String),
    /// Requested a METAR or weather information but no weather profile was found for this location
    #[error("No weather profile for {0}")]
    NoWeatherProfile(String),
    /// Attempted to connect using a protocol version not supported by the server
    #[error("Invalid protocol revision")]
    InvalidProtocolRevision,
    /// Attempted to log in with too high a rating
    #[error("Requested level too high")]
    RequestedLevelTooHigh,
    /// Server is full
    #[error("Server full")]
    ServerFull,
    /// Attemped to log in with a CID that has been suspended
    #[error("CID has been suspended")]
    CertificateSuspended,
    /// Attempted to perform an unauthorised ATC action (such as assume an aircraft)
    #[error("Invalid control")]
    InvalidControl,
    /// Attempted to log in to an ATC position which the user's rating does not allow
    #[error("Invalid position for rating")]
    InvalidPositionForRating,
    /// Connected with a client that is not approved for use on the network
    #[error("Unauthorised client")]
    UnauthorisedClient,
    /// Client did not respond to server's authentication challenge in time
    #[error("Authentication time out")]
    AuthTimeOut,
    /// Other error
    #[error("Other: {0}")]
    Other(String),
}
impl FsdError {
    pub fn error_number(&self) -> u8 {
        match *self {
            FsdError::CallsignInUse => 1,
            FsdError::InvalidCallsign => 2,
            FsdError::AlreadyRegistered => 3,
            FsdError::SyntaxError => 4,
            FsdError::InvalidSourceCallsign => 5,
            FsdError::InvalidCidPassword => 6,
            FsdError::NoSuchCallsign(_) => 7,
            FsdError::NoFlightPlan(_) => 8,
            FsdError::NoWeatherProfile(_) => 9,
            FsdError::InvalidProtocolRevision => 10,
            FsdError::RequestedLevelTooHigh => 11,
            FsdError::ServerFull => 12,
            FsdError::CertificateSuspended => 13,
            FsdError::InvalidControl => 14,
            FsdError::InvalidPositionForRating => 15,
            FsdError::UnauthorisedClient => 16,
            FsdError::AuthTimeOut => 17,
            FsdError::Other(_) => 18,
        }
    }
}