1use serde::Deserialize;
20use std::error::Error as StdError;
21use std::fmt::{Display, Formatter, Pointer};
22use std::io;
23
24use crate::memdx::opcode::OpCode;
25use crate::memdx::status::Status;
26
27pub type Result<T> = std::result::Result<T, Error>;
28
29#[derive(Debug, PartialEq)]
30pub struct Error {
31 inner: ErrorImpl,
32}
33
34impl Error {
35 pub(crate) fn new_protocol_error(msg: impl Into<String>) -> Self {
36 Self {
37 inner: ErrorImpl {
38 kind: Box::new(ErrorKind::Protocol { msg: msg.into() }),
39 source: None,
40 },
41 }
42 }
43
44 pub(crate) fn new_decompression_error() -> Self {
45 Self {
46 inner: ErrorImpl {
47 kind: Box::new(ErrorKind::Decompression {}),
48 source: None,
49 },
50 }
51 }
52
53 pub(crate) fn new_message_error(msg: impl Into<String>) -> Self {
54 Self {
55 inner: ErrorImpl {
56 kind: Box::new(ErrorKind::Message(msg.into())),
57 source: None,
58 },
59 }
60 }
61
62 pub(crate) fn new_cancelled_error(cancellation_kind: CancellationErrorKind) -> Self {
63 Self {
64 inner: ErrorImpl {
65 kind: Box::new(ErrorKind::Cancelled(cancellation_kind)),
66 source: None,
67 },
68 }
69 }
70
71 pub(crate) fn new_invalid_argument_error(
72 msg: impl Into<String>,
73 arg: impl Into<Option<String>>,
74 ) -> Self {
75 Self {
76 inner: ErrorImpl {
77 kind: Box::new(ErrorKind::InvalidArgument {
78 msg: msg.into(),
79 arg: arg.into(),
80 }),
81 source: None,
82 },
83 }
84 }
85
86 pub(crate) fn new_connection_failed_error(
87 reason: impl Into<String>,
88 source: Box<io::Error>,
89 ) -> Self {
90 Self {
91 inner: ErrorImpl {
92 kind: Box::new(ErrorKind::ConnectionFailed { msg: reason.into() }),
93 source: Some(source),
94 },
95 }
96 }
97
98 pub(crate) fn new_dispatch_error(opaque: u32, op_code: OpCode, source: Box<Error>) -> Self {
99 Self {
100 inner: ErrorImpl {
101 kind: Box::new(ErrorKind::Dispatch { opaque, op_code }),
102 source: Some(source),
103 },
104 }
105 }
106
107 pub(crate) fn new_close_error(msg: String, source: Box<Error>) -> Self {
108 Self {
109 inner: ErrorImpl {
110 kind: Box::new(ErrorKind::Close { msg }),
111 source: Some(source),
112 },
113 }
114 }
115
116 pub fn has_server_config(&self) -> Option<&Vec<u8>> {
117 if let ErrorKind::Server(ServerError { config, .. }) = self.inner.kind.as_ref() {
118 config.as_ref()
119 } else {
120 None
121 }
122 }
123
124 pub fn has_server_error_context(&self) -> Option<&Vec<u8>> {
125 if let ErrorKind::Server(ServerError { context, .. }) = self.inner.kind.as_ref() {
126 context.as_ref()
127 } else if let ErrorKind::Resource(ResourceError { cause, .. }) = self.inner.kind.as_ref() {
128 cause.context.as_ref()
129 } else {
130 None
131 }
132 }
133
134 pub fn has_opaque(&self) -> Option<u32> {
135 let inner_kind = self.inner.kind.as_ref();
136 if let ErrorKind::Server(ServerError { opaque, .. }) = inner_kind {
137 Some(*opaque)
138 } else if let ErrorKind::Resource(e) = inner_kind {
139 Some(e.cause.opaque)
140 } else if let ErrorKind::Dispatch { opaque, .. } = inner_kind {
141 Some(*opaque)
142 } else {
143 None
144 }
145 }
146
147 pub fn is_cancellation_error(&self) -> bool {
148 matches!(self.inner.kind.as_ref(), ErrorKind::Cancelled { .. })
149 }
150
151 pub fn is_dispatch_error(&self) -> bool {
152 matches!(self.inner.kind.as_ref(), ErrorKind::Dispatch { .. })
153 }
154
155 pub fn is_server_error_kind(&self, kind: ServerErrorKind) -> bool {
156 match self.inner.kind.as_ref() {
157 ErrorKind::Server(e) => e.kind == kind,
158 ErrorKind::Resource(e) => e.cause.kind == kind,
159 _ => false,
160 }
161 }
162
163 pub fn kind(&self) -> &ErrorKind {
164 &self.inner.kind
165 }
166
167 pub(crate) fn with<C: Into<Source>>(mut self, source: C) -> Error {
168 self.inner.source = Some(source.into());
169 self
170 }
171}
172
173type Source = Box<dyn StdError + Send + Sync>;
174
175#[derive(Debug)]
176struct ErrorImpl {
177 kind: Box<ErrorKind>,
178 source: Option<Source>,
179}
180
181impl PartialEq for ErrorImpl {
182 fn eq(&self, other: &Self) -> bool {
183 self.kind == other.kind
184 }
185}
186
187impl Display for Error {
188 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
189 write!(f, "{}", self.inner.kind)
190 }
191}
192
193impl StdError for Error {
194 fn source(&self) -> Option<&(dyn StdError + 'static)> {
195 self.inner
196 .source
197 .as_ref()
198 .map(|cause| &**cause as &(dyn StdError + 'static))
199 }
200}
201
202#[derive(Debug, Clone, PartialEq)]
203#[non_exhaustive]
204pub enum ErrorKind {
205 Server(ServerError),
206 Resource(ResourceError),
207 #[non_exhaustive]
208 Dispatch {
209 opaque: u32,
210 op_code: OpCode,
211 },
212 #[non_exhaustive]
213 Close {
214 msg: String,
215 },
216 #[non_exhaustive]
217 Protocol {
218 msg: String,
219 },
220 Cancelled(CancellationErrorKind),
221 #[non_exhaustive]
222 ConnectionFailed {
223 msg: String,
224 },
225 Io,
226 #[non_exhaustive]
227 InvalidArgument {
228 msg: String,
229 arg: Option<String>,
230 },
231 Decompression,
232 Message(String),
233}
234
235impl Display for ErrorKind {
236 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
237 match self {
238 ErrorKind::Server(e) => write!(f, "{e}"),
239 ErrorKind::Resource(e) => write!(f, "{e}"),
240 ErrorKind::Dispatch { opaque, op_code } => {
241 write!(f, "dispatch failed: opaque: {opaque}, op_code: {op_code}")
242 }
243 ErrorKind::Close { msg } => {
244 write!(f, "close error {msg}")
245 }
246 ErrorKind::Protocol { msg } => {
247 write!(f, "{msg}")
248 }
249 ErrorKind::Cancelled(kind) => {
250 write!(f, "request cancelled: {kind}")
251 }
252 ErrorKind::ConnectionFailed { msg } => {
253 write!(f, "connection failed {msg}")
254 }
255 ErrorKind::Io => {
256 write!(f, "connection error")
257 }
258 ErrorKind::InvalidArgument { msg, arg } => {
259 let base_msg = format!("invalid argument: {msg}");
260 if let Some(arg) = arg {
261 write!(f, "{base_msg}, arg: {arg}")
262 } else {
263 write!(f, "{base_msg}")
264 }
265 }
266 ErrorKind::Decompression => write!(f, "decompression error"),
267 ErrorKind::Message(msg) => write!(f, "{msg}"),
268 }
269 }
270}
271
272#[derive(Clone, Debug, PartialEq, Eq)]
273#[non_exhaustive]
274pub struct ResourceError {
275 cause: ServerError,
276 scope_name: String,
277 collection_name: String,
278}
279
280impl StdError for ResourceError {}
281
282impl ResourceError {
283 pub(crate) fn new(
284 cause: ServerError,
285 scope_name: impl Into<String>,
286 collection_name: impl Into<String>,
287 ) -> Self {
288 Self {
289 cause,
290 scope_name: scope_name.into(),
291 collection_name: collection_name.into(),
292 }
293 }
294
295 pub fn cause(&self) -> &ServerError {
296 &self.cause
297 }
298
299 pub fn scope_name(&self) -> &str {
300 &self.scope_name
301 }
302
303 pub fn collection_name(&self) -> &str {
304 &self.collection_name
305 }
306}
307
308impl Display for ResourceError {
309 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
310 write!(
311 f,
312 "Resource error: {}, scope: {}, collection: {}",
313 self.cause, self.scope_name, self.collection_name
314 )
315 }
316}
317
318#[derive(Clone, Debug, PartialEq, Eq)]
319#[non_exhaustive]
320pub struct ServerError {
321 kind: ServerErrorKind,
322 config: Option<Vec<u8>>,
323 context: Option<Vec<u8>>,
324 op_code: OpCode,
325 status: Status,
326 opaque: u32,
327}
328
329impl StdError for ServerError {}
330
331impl Display for ServerError {
332 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
333 let mut base_msg = format!(
334 "Server error: {}, status: 0x{:02x}, opcode: {}, opaque: {}",
335 self.kind,
336 u16::from(self.status),
337 self.op_code,
338 self.opaque
339 );
340
341 if let Some(context) = &self.context {
342 if let Some(parsed) = Self::parse_context(context) {
343 base_msg.push_str(" (");
344 if let Some(text) = &parsed.text {
345 base_msg.push_str(&format!("context: {text}, "));
346 }
347
348 if let Some(error_ref) = &parsed.error_ref {
349 base_msg.push_str(&format!("error_ref: {error_ref}"));
350 }
351 base_msg.push(')');
352 }
353 }
354
355 write!(f, "{base_msg}")
356 }
357}
358
359impl ServerError {
360 pub(crate) fn new(kind: ServerErrorKind, op_code: OpCode, status: Status, opaque: u32) -> Self {
361 Self {
362 kind,
363 config: None,
364 context: None,
365 op_code,
366 status,
367 opaque,
368 }
369 }
370
371 pub(crate) fn with_context(mut self, context: Vec<u8>) -> Self {
372 self.context = Some(context);
373 self
374 }
375
376 pub(crate) fn with_config(mut self, config: Vec<u8>) -> Self {
377 self.config = Some(config);
378 self
379 }
380
381 pub fn kind(&self) -> &ServerErrorKind {
382 &self.kind
383 }
384
385 pub fn config(&self) -> Option<&Vec<u8>> {
386 self.config.as_ref()
387 }
388
389 pub fn context(&self) -> Option<&Vec<u8>> {
390 self.context.as_ref()
391 }
392
393 pub fn op_code(&self) -> OpCode {
394 self.op_code
395 }
396
397 pub fn status(&self) -> Status {
398 self.status
399 }
400
401 pub fn opaque(&self) -> u32 {
402 self.opaque
403 }
404
405 pub fn parse_context(context: &[u8]) -> Option<ServerErrorContext> {
406 if context.is_empty() {
407 return None;
408 }
409
410 let context_json: ServerErrorContextJson = match serde_json::from_slice(context) {
411 Ok(c) => c,
412 Err(_) => {
413 return None;
414 }
415 };
416
417 let text = context_json.error.context;
418
419 let error_ref = context_json.error.error_ref;
420
421 let manifest_rev = context_json
422 .manifest_rev
423 .map(|manifest_rev| u64::from_str_radix(&manifest_rev, 16).unwrap_or_default());
424
425 Some(ServerErrorContext {
426 text,
427 error_ref,
428 manifest_rev,
429 })
430 }
431}
432
433#[derive(Clone, Debug, PartialEq, Eq)]
434#[non_exhaustive]
435pub struct ServerErrorContext {
436 pub text: Option<String>,
437 pub error_ref: Option<String>,
438 pub manifest_rev: Option<u64>,
439}
440
441#[derive(Clone, Debug, Eq, Hash, PartialEq)]
442#[non_exhaustive]
443pub enum ServerErrorKind {
444 KeyNotFound,
445 KeyExists,
446 TooBig,
447 NotStored,
448 BadDelta,
449 NotMyVbucket,
450 NoBucket,
451 Locked,
452 NotLocked,
453 Auth { msg: String },
454 RangeError,
455 Access,
456 RateLimitedNetworkIngress,
457 RateLimitedNetworkEgress,
458 RateLimitedMaxConnections,
459 RateLimitedMaxCommands,
460 RateLimitedScopeSizeLimitExceeded,
461 UnknownCommand,
462 NotSupported,
463 InternalError,
464 Busy,
465 TmpFail,
466 UnknownCollectionID,
467 UnknownScopeName,
468 UnknownCollectionName,
469 DurabilityInvalid,
470 DurabilityImpossible,
471 SyncWriteInProgress,
472 SyncWriteAmbiguous,
473 SyncWriteRecommitInProgress,
474 RangeScanCancelled,
475 RangeScanVBUUIDNotEqual,
476 InvalidArgs,
477
478 ConfigNotSet,
479 UnknownBucketName,
480 CasMismatch,
481
482 Subdoc { error: SubdocError },
483
484 UnknownStatus { status: Status },
485}
486
487impl Display for ServerErrorKind {
488 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
489 match self {
490 ServerErrorKind::NotMyVbucket => write!(f, "not my vbucket"),
491 ServerErrorKind::KeyExists => write!(f, "key exists"),
492 ServerErrorKind::NotStored => write!(f, "key not stored"),
493 ServerErrorKind::KeyNotFound => write!(f, "key not found"),
494 ServerErrorKind::TmpFail => write!(f, "temporary failure"),
495 ServerErrorKind::CasMismatch => write!(f, "cas mismatch"),
496 ServerErrorKind::Locked => write!(f, "locked"),
497 ServerErrorKind::NotLocked => write!(f, "not locked"),
498 ServerErrorKind::TooBig => write!(f, "too big"),
499 ServerErrorKind::UnknownCollectionID => write!(f, "unknown collection id"),
500 ServerErrorKind::NoBucket => write!(f, "no bucket selected"),
501 ServerErrorKind::UnknownBucketName => write!(f, "unknown bucket name"),
502 ServerErrorKind::Access => write!(f, "access error"),
503 ServerErrorKind::Auth { msg } => write!(f, "auth error {msg}"),
504 ServerErrorKind::ConfigNotSet => write!(f, "config not set"),
505 ServerErrorKind::UnknownScopeName => write!(f, "scope name unknown"),
506 ServerErrorKind::UnknownCollectionName => write!(f, "collection name unknown"),
507 ServerErrorKind::Subdoc { error } => write!(f, "{error}"),
508 ServerErrorKind::UnknownStatus { status } => {
509 write!(f, "server status unexpected for operation: {status}")
510 }
511 ServerErrorKind::BadDelta => write!(f, "bad delta"),
512 ServerErrorKind::UnknownCommand => write!(f, "unknown command"),
513 ServerErrorKind::RangeError => write!(f, "range error"),
514 ServerErrorKind::RateLimitedNetworkIngress => {
515 write!(f, "rate limited: network ingress")
516 }
517 ServerErrorKind::RateLimitedNetworkEgress => write!(f, "rate limited: network egress"),
518 ServerErrorKind::RateLimitedMaxConnections => {
519 write!(f, "rate limited: max connections")
520 }
521 ServerErrorKind::RateLimitedMaxCommands => write!(f, "rate limited: max commands"),
522 ServerErrorKind::RateLimitedScopeSizeLimitExceeded => {
523 write!(f, "rate limited: scope size limit exceeded")
524 }
525 ServerErrorKind::NotSupported => write!(f, "not supported"),
526 ServerErrorKind::InternalError => write!(f, "internal error"),
527 ServerErrorKind::Busy => write!(f, "busy"),
528 ServerErrorKind::DurabilityInvalid => write!(f, "durability invalid"),
529 ServerErrorKind::DurabilityImpossible => write!(f, "durability impossible"),
530 ServerErrorKind::SyncWriteInProgress => write!(f, "sync write in progress"),
531 ServerErrorKind::SyncWriteAmbiguous => write!(f, "sync write ambiguous"),
532 ServerErrorKind::SyncWriteRecommitInProgress => {
533 write!(f, "sync write recommit in progress")
534 }
535 ServerErrorKind::RangeScanCancelled => write!(f, "range scan cancelled"),
536 ServerErrorKind::RangeScanVBUUIDNotEqual => write!(f, "range scan vbUUID not equal"),
537 ServerErrorKind::InvalidArgs => write!(f, "invalid args"),
538 }
539 }
540}
541
542#[derive(Clone, Debug, PartialEq, Eq, Hash)]
543#[non_exhaustive]
544pub struct SubdocError {
545 kind: SubdocErrorKind,
546 op_index: Option<u8>,
547}
548
549impl StdError for SubdocError {}
550
551impl SubdocError {
552 pub(crate) fn new(kind: SubdocErrorKind, op_index: impl Into<Option<u8>>) -> Self {
553 Self {
554 kind,
555 op_index: op_index.into(),
556 }
557 }
558
559 pub fn is_error_kind(&self, kind: SubdocErrorKind) -> bool {
560 self.kind == kind
561 }
562
563 pub fn kind(&self) -> &SubdocErrorKind {
564 &self.kind
565 }
566
567 pub fn op_index(&self) -> Option<u8> {
568 self.op_index
569 }
570}
571
572impl Display for SubdocError {
573 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
574 if let Some(op_index) = self.op_index {
575 let base_msg = format!("Subdoc error: {}, op_index: {}", self.kind, op_index);
576 write!(f, "{base_msg}")
577 } else {
578 let base_msg = format!("Subdoc error: {}", self.kind);
579 write!(f, "{base_msg}")
580 }
581 }
582}
583
584#[derive(Clone, Debug, Eq, Hash, PartialEq)]
585#[non_exhaustive]
586pub enum SubdocErrorKind {
587 PathNotFound,
588 PathMismatch,
589 PathInvalid,
590 PathTooBig,
591 DocTooDeep,
592 CantInsert,
593 NotJSON,
594 BadRange,
595 BadDelta,
596 PathExists,
597 ValueTooDeep,
598 InvalidCombo,
599 XattrInvalidFlagCombo,
600 XattrInvalidKeyCombo,
601 XattrUnknownMacro,
602 XattrUnknownVAttr,
603 XattrCannotModifyVAttr,
604 InvalidXattrOrder,
605 XattrUnknownVattrMacro,
606 CanOnlyReviveDeletedDocuments,
607 DeletedDocumentCantHaveValue,
608 UnknownStatus { status: Status },
609}
610
611impl Display for SubdocErrorKind {
612 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
613 match self {
614 SubdocErrorKind::PathNotFound => write!(f, "subdoc path not found"),
615 SubdocErrorKind::PathMismatch => write!(f, "subdoc path mismatch"),
616 SubdocErrorKind::PathInvalid => write!(f, "subdoc path invalid"),
617 SubdocErrorKind::PathTooBig => write!(f, "subdoc path too big"),
618 SubdocErrorKind::DocTooDeep => write!(f, "subdoc doc too deep"),
619 SubdocErrorKind::CantInsert => write!(f, "subdoc can't insert"),
620 SubdocErrorKind::NotJSON => write!(f, "subdoc not JSON"),
621 SubdocErrorKind::BadRange => write!(f, "subdoc bad range"),
622 SubdocErrorKind::BadDelta => write!(f, "subdoc bad delta"),
623 SubdocErrorKind::PathExists => write!(f, "subdoc path exists"),
624 SubdocErrorKind::ValueTooDeep => write!(f, "subdoc value too deep"),
625 SubdocErrorKind::InvalidCombo => write!(f, "subdoc invalid combo"),
626 SubdocErrorKind::XattrInvalidFlagCombo => write!(f, "subdoc xattr invalid flag combo"),
627 SubdocErrorKind::XattrInvalidKeyCombo => write!(f, "subdoc xattr invalid key combo"),
628 SubdocErrorKind::XattrUnknownMacro => write!(f, "subdoc xattr unknown macro"),
629 SubdocErrorKind::XattrUnknownVAttr => write!(f, "subdoc xattr unknown vattr"),
630 SubdocErrorKind::XattrCannotModifyVAttr => {
631 write!(f, "subdoc xattr cannot modify vattr")
632 }
633 SubdocErrorKind::InvalidXattrOrder => write!(f, "subdoc invalid xattr order"),
634 SubdocErrorKind::XattrUnknownVattrMacro => {
635 write!(f, "subdoc xattr unknown vattr macro")
636 }
637 SubdocErrorKind::CanOnlyReviveDeletedDocuments => {
638 write!(f, "subdoc can only revive deleted documents")
639 }
640 SubdocErrorKind::DeletedDocumentCantHaveValue => {
641 write!(f, "subdoc deleted document can't have value")
642 }
643 SubdocErrorKind::UnknownStatus { status } => write!(
644 f,
645 "subdoc unknown status unexpected for operation: {status}"
646 ),
647 }
648 }
649}
650
651#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
652#[non_exhaustive]
653pub enum CancellationErrorKind {
654 Timeout,
655 RequestCancelled,
656 ClosedInFlight,
657}
658
659impl Display for CancellationErrorKind {
660 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
661 let txt = match self {
662 CancellationErrorKind::Timeout => "Timeout",
663 CancellationErrorKind::RequestCancelled => "Request cancelled",
664 CancellationErrorKind::ClosedInFlight => "Closed in flight",
665 };
666
667 write!(f, "{txt}")
668 }
669}
670
671impl<E> From<E> for Error
672where
673 ErrorKind: From<E>,
674{
675 fn from(err: E) -> Self {
676 Self {
677 inner: ErrorImpl {
678 kind: Box::new(ErrorKind::from(err)),
679 source: None,
680 },
681 }
682 }
683}
684
685impl From<ServerError> for Error {
686 fn from(value: ServerError) -> Self {
687 Self {
688 inner: ErrorImpl {
689 kind: Box::new(ErrorKind::Server(value)),
690 source: None,
691 },
692 }
693 }
694}
695
696impl From<ResourceError> for Error {
697 fn from(value: ResourceError) -> Self {
698 Self {
699 inner: ErrorImpl {
700 kind: Box::new(ErrorKind::Resource(value)),
701 source: None,
702 },
703 }
704 }
705}
706
707impl From<io::Error> for Error {
708 fn from(value: io::Error) -> Self {
709 Self {
710 inner: ErrorImpl {
711 kind: Box::new(ErrorKind::Io),
712 source: Some(Box::new(value)),
713 },
714 }
715 }
716}
717
718#[derive(Deserialize, Clone, Debug, PartialEq, Eq, Default)]
719struct ServerErrorContextJsonContext {
720 #[serde(alias = "context")]
721 context: Option<String>,
722 #[serde(alias = "ref")]
723 pub error_ref: Option<String>,
724}
725
726#[derive(Deserialize, Clone, Debug, PartialEq, Eq)]
727struct ServerErrorContextJson {
728 #[serde(alias = "error", default)]
729 error: ServerErrorContextJsonContext,
730 #[serde(alias = "manifest_uid")]
731 pub manifest_rev: Option<String>,
732}