1// Copyright 2020 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
45use anyhow::format_err;
6use futures::channel::{mpsc, oneshot};
7use thiserror::Error;
89/// Error types that may be used by the async hanging-get server.
10#[derive(Error, Debug)]
11pub enum HangingGetServerError {
12/// An existing observer was already present for the client.
13#[error("Cannot have multiple concurrent observers for a single client")]
14MultipleObservers,
1516/// The HangingGetBroker associated with this handle has been dropped.
17#[error("The HangingGetBroker associated with this handle has been dropped.")]
18NoBroker,
1920/// This handle is sending messages faster than the broker can process them.
21#[error("This handle is sending messages faster than the broker can process them.")]
22RateLimit,
2324/// Generic hanging-get server error.
25#[error("Error: {}", .0)]
26Generic(anyhow::Error),
27}
2829impl PartialEq for HangingGetServerError {
30fn eq(&self, other: &Self) -> bool {
31use HangingGetServerError::*;
32match (self, other) {
33 (MultipleObservers, MultipleObservers)
34 | (NoBroker, NoBroker)
35 | (RateLimit, RateLimit) => true,
36_ => false,
37 }
38 }
39}
4041impl From<mpsc::SendError> for HangingGetServerError {
42fn from(error: mpsc::SendError) -> Self {
43if error.is_disconnected() {
44 HangingGetServerError::NoBroker
45 } else if error.is_full() {
46 HangingGetServerError::RateLimit
47 } else {
48 HangingGetServerError::Generic(format_err!(
49"Unknown SendError error condition: {}",
50 error
51 ))
52 }
53 }
54}
5556impl From<oneshot::Canceled> for HangingGetServerError {
57fn from(e: oneshot::Canceled) -> Self {
58 HangingGetServerError::Generic(e.into())
59 }
60}
6162impl From<anyhow::Error> for HangingGetServerError {
63/// Try downcasting to more specific error types, falling back to `Generic` if that fails.
64fn from(e: anyhow::Error) -> Self {
65 e.downcast::<mpsc::SendError>().map_or_else(HangingGetServerError::Generic, Self::from)
66 }
67}
6869#[cfg(test)]
70mod tests {
71use super::*;
7273#[test]
74fn error_partial_eq_impl() {
75use HangingGetServerError::*;
76let variants = [MultipleObservers, NoBroker, RateLimit, Generic(format_err!("err"))];
77for (i, a) in variants.iter().enumerate() {
78for (j, b) in variants.iter().enumerate() {
79// variants with the same index are equal except `Generic` errors are _never_ equal.
80if i == j && i != 3 && j != 3 {
81assert_eq!(a, b);
82 } else {
83assert_ne!(a, b);
84 }
85 }
86 }
87 }
88}