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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
use failure_derive::Fail;

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[repr(i32)]
pub enum ZkError {
    /// This code is never returned from the server. It should not be used other than to indicate a
    /// range. Specifically error codes greater than this value are API errors (while values less
    /// than this indicate a system error.
    APIError = -100,
    /// Client authentication failed.
    AuthFailed = -115,
    /// Invalid arguments.
    BadArguments = -8,
    /// Version conflict in `set` operation. In case of reconfiguration: reconfig requested from
    /// config version X but last seen config has a different version Y.
    BadVersion = -103,
    /// Connection to the server has been lost.
    ConnectionLoss = -4,
    /// A data inconsistency was found.
    DataInconsistency = -3,
    /// Attempt to create ephemeral node on a local session.
    EphemeralOnLocalSession = -120,
    /// Invalid `Acl` specified.
    InvalidACL = -114,
    /// Invalid callback specified.
    InvalidCallback = -113,
    /// Error while marshalling or unmarshalling data.
    MarshallingError = -5,
    /// Not authenticated.
    NoAuth = -102,
    /// Ephemeral nodes may not have children.
    NoChildrenForEphemerals = -108,
    /// Request to create node that already exists.
    NodeExists = -110,
    /// Attempted to read a node that does not exist.
    NoNode = -101,
    /// The node has children.
    NotEmpty = -111,
    /// State-changing request is passed to read-only server.
    NotReadOnly = -119,
    /// Attempt to remove a non-existing watcher.
    NoWatcher = -121,
    /// No error occurred.
    Ok = 0,
    /// Operation timeout.
    OperationTimeout = -7,
    /// A runtime inconsistency was found.
    RuntimeInconsistency = -2,
    /// The session has been expired by the server.
    SessionExpired = -112,
    /// Session moved to another server, so operation is ignored.
    SessionMoved = -118,
    /// System and server-side errors. This is never thrown by the server, it shouldn't be used
    /// other than to indicate a range. Specifically error codes greater than this value, but lesser
    /// than `APIError`, are system errors.
    SystemError = -1,
    /// Operation is unimplemented.
    Unimplemented = -6,
}

impl From<i32> for ZkError {
    fn from(code: i32) -> Self {
        match code {
            -100 => ZkError::APIError,
            -115 => ZkError::AuthFailed,
            -8 => ZkError::BadArguments,
            -103 => ZkError::BadVersion,
            -4 => ZkError::ConnectionLoss,
            -3 => ZkError::DataInconsistency,
            -120 => ZkError::EphemeralOnLocalSession,
            -114 => ZkError::InvalidACL,
            -113 => ZkError::InvalidCallback,
            -5 => ZkError::MarshallingError,
            -102 => ZkError::NoAuth,
            -108 => ZkError::NoChildrenForEphemerals,
            -110 => ZkError::NodeExists,
            -101 => ZkError::NoNode,
            -111 => ZkError::NotEmpty,
            -119 => ZkError::NotReadOnly,
            -121 => ZkError::NoWatcher,
            0 => ZkError::Ok,
            -7 => ZkError::OperationTimeout,
            -2 => ZkError::RuntimeInconsistency,
            -112 => ZkError::SessionExpired,
            -118 => ZkError::SessionMoved,
            -1 => ZkError::SystemError,
            -6 => ZkError::Unimplemented,
            _ => panic!("unknown error code {}", code),
        }
    }
}

/// Errors that may cause a delete request to fail.
#[derive(Clone, Copy, PartialEq, Eq, Debug, Fail)]
pub enum Delete {
    /// No node exists with the given `path`.
    #[fail(display = "target node does not exist")]
    NoNode,

    /// The target node has a different version than was specified by the call to delete.
    #[fail(
        display = "target node has different version than expected ({})",
        expected
    )]
    BadVersion {
        /// The expected node version.
        expected: i32,
    },

    /// The target node has child nodes, and therefore cannot be deleted.
    #[fail(display = "target node has children, and cannot be deleted")]
    NotEmpty,
}

/// Errors that may cause a `set_data` request to fail.
#[derive(Clone, Copy, PartialEq, Eq, Debug, Fail)]
pub enum SetData {
    /// No node exists with the given `path`.
    #[fail(display = "target node does not exist")]
    NoNode,

    /// The target node has a different version than was specified by the call to `set_data`.
    #[fail(
        display = "target node has different version than expected ({})",
        expected
    )]
    BadVersion {
        /// The expected node version.
        expected: i32,
    },

    /// The target node's permission does not accept data modification or requires different
    /// authentication to be altered.
    #[fail(display = "insuficient authentication")]
    NoAuth,
}

/// Errors that may cause a create request to fail.
#[derive(Clone, Copy, PartialEq, Eq, Debug, Fail)]
pub enum Create {
    /// A node with the given `path` already exists.
    #[fail(display = "target node already exists")]
    NodeExists,

    /// The parent node of the given `path` does not exist.
    #[fail(display = "parent node of target does not exist")]
    NoNode,

    /// The parent node of the given `path` is ephemeral, and cannot have children.
    #[fail(display = "parent node is ephemeral, and cannot have children")]
    NoChildrenForEphemerals,

    /// The given ACL is invalid.
    #[fail(display = "the given ACL is invalid")]
    InvalidAcl,
}

/// Errors that may cause a `get_acl` request to fail.
#[derive(Clone, Copy, PartialEq, Eq, Debug, Fail)]
pub enum GetAcl {
    /// No node exists with the given `path`.
    #[fail(display = "target node does not exist")]
    NoNode,
}

/// Errors that may cause a `set_acl` request to fail.
#[derive(Clone, Copy, PartialEq, Eq, Debug, Fail)]
pub enum SetAcl {
    /// No node exists with the given `path`.
    #[fail(display = "target node does not exist")]
    NoNode,

    /// The target node has a different version than was specified by the call to `set_acl`.
    #[fail(
        display = "target node has different version than expected ({})",
        expected
    )]
    BadVersion {
        /// The expected node version.
        expected: i32,
    },

    /// The given ACL is invalid.
    #[fail(display = "the given ACL is invalid")]
    InvalidAcl,

    /// The target node's permission does not accept acl modification or requires different
    /// authentication to be altered.
    #[fail(display = "insufficient authentication")]
    NoAuth,
}

/// Errors that may cause a `check` request to fail.
#[derive(Clone, Copy, PartialEq, Eq, Debug, Fail)]
pub enum Check {
    /// No node exists with the given `path`.
    #[fail(display = "target node does not exist")]
    NoNode,

    /// The target node has a different version than was specified by the call to `check`.
    #[fail(
        display = "target node has different version than expected ({})",
        expected
    )]
    BadVersion {
        /// The expected node version.
        expected: i32,
    },
}

/// The result of a failed `multi` request.
#[derive(Clone, Copy, PartialEq, Eq, Debug, Fail)]
pub enum Multi {
    /// A failed `delete` request.
    #[fail(display = "delete failed: {}", 0)]
    Delete(Delete),

    /// A failed `set_data` request.
    #[fail(display = "set_data failed: {}", 0)]
    SetData(SetData),

    /// A failed `create` request.
    #[fail(display = "create failed: {}", 0)]
    Create(Create),

    /// A failed `check` request.
    #[fail(display = "check failed")]
    Check(Check),

    /// The request would have succeeded, but a later request in the `multi`
    /// batch failed and caused this request to get rolled back.
    #[fail(display = "request rolled back due to later failed request")]
    RolledBack,

    /// The request was skipped because an earlier request in the `multi` batch
    /// failed. It is unknown whether this request would have succeeded.
    #[fail(display = "request failed due to earlier failed request")]
    Skipped,
}

impl From<Delete> for Multi {
    fn from(err: Delete) -> Self {
        Multi::Delete(err)
    }
}

impl From<SetData> for Multi {
    fn from(err: SetData) -> Self {
        Multi::SetData(err)
    }
}

impl From<Create> for Multi {
    fn from(err: Create) -> Self {
        Multi::Create(err)
    }
}

impl From<Check> for Multi {
    fn from(err: Check) -> Self {
        Multi::Check(err)
    }
}