use super::messages::serializer::ButtplugSerializerError;
use super::messages::{
self,
ButtplugDeviceMessageType,
ButtplugMessage,
ButtplugMessageSpecVersion,
ErrorCode,
};
use crate::device::Endpoint;
#[cfg(feature = "server")]
use crate::server::comm_managers::ButtplugDeviceSpecificError;
use displaydoc::Display;
use futures::future::{self, BoxFuture};
use std::fmt;
use thiserror::Error;
pub type ButtplugResult<T = ()> = Result<T, ButtplugError>;
impl<T> From<ButtplugHandshakeError> for BoxFuture<'static, Result<T, ButtplugError>>
where
T: Send + 'static,
{
fn from(err: ButtplugHandshakeError) -> BoxFuture<'static, Result<T, ButtplugError>> {
ButtplugError::from(err).into()
}
}
#[derive(Debug, Error, Display, Clone)]
pub enum ButtplugHandshakeError {
UnexpectedHandshakeMessageReceived(String),
RequestServerInfoExpected,
HandshakeAlreadyHappened,
MessageSpecVersionMismatch(ButtplugMessageSpecVersion, ButtplugMessageSpecVersion),
UntypedDeserializedError(String),
}
impl<T> From<ButtplugMessageError> for BoxFuture<'static, Result<T, ButtplugError>>
where
T: Send + 'static,
{
fn from(err: ButtplugMessageError) -> BoxFuture<'static, Result<T, ButtplugError>> {
ButtplugError::from(err).into()
}
}
#[derive(Debug, Error, Display, Clone)]
pub enum ButtplugMessageError {
UnexpectedMessageType(String),
VersionError(&'static str, String, &'static str),
MessageConversionError(&'static str),
UnhandledMessage(String),
ValidationError(&'static str),
#[error(transparent)]
MessageSerializationError(#[from] ButtplugSerializerError),
UntypedDeserializedError(String),
}
impl<T> From<ButtplugPingError> for BoxFuture<'static, Result<T, ButtplugError>>
where
T: Send + 'static,
{
fn from(err: ButtplugPingError) -> BoxFuture<'static, Result<T, ButtplugError>> {
ButtplugError::from(err).into()
}
}
#[derive(Debug, Error, Display, Clone)]
pub enum ButtplugPingError {
PingedOut,
PingTimerNotRunning,
UntypedDeserializedError(String),
}
impl<T> From<ButtplugDeviceError> for BoxFuture<'static, Result<T, ButtplugError>>
where
T: Send + 'static,
{
fn from(err: ButtplugDeviceError) -> BoxFuture<'static, Result<T, ButtplugError>> {
ButtplugError::from(err).into()
}
}
#[derive(Debug, Error, Display, Clone)]
pub enum ButtplugDeviceError {
DeviceNotConnected(String),
MessageNotSupported(ButtplugDeviceMessageType),
DeviceFeatureCountMismatch(u32, u32),
DeviceFeatureIndexError(u32, u32),
DeviceConnectionError(String),
DeviceCommunicationError(String),
InvalidEndpoint(Endpoint),
UnhandledCommand(String),
#[cfg(feature = "server")]
#[error(transparent)]
DeviceSpecificError(#[from] ButtplugDeviceSpecificError),
#[cfg(not(feature = "server"))]
DeviceSpecificError(String),
DeviceNotAvailable(u32),
DeviceScanningAlreadyStarted,
DeviceScanningAlreadyStopped,
DevicePermissionError(String),
ProtocolAttributesNotFound(String),
ProtocolNotImplemented(String),
ProtocolSpecificError(&'static str, &'static str),
ProtocolRequirementError(String),
UntypedDeserializedError(String),
}
impl<T> From<ButtplugUnknownError> for BoxFuture<'static, Result<T, ButtplugError>>
where
T: Send + 'static,
{
fn from(err: ButtplugUnknownError) -> BoxFuture<'static, Result<T, ButtplugError>> {
ButtplugError::from(err).into()
}
}
#[derive(Debug, Error, Display, Clone)]
pub enum ButtplugUnknownError {
NoDeviceCommManagers,
UnexpectedType(String),
UntypedDeserializedError(String),
}
#[derive(Debug, Error, Clone)]
pub enum ButtplugError {
#[error(transparent)]
ButtplugHandshakeError(#[from] ButtplugHandshakeError),
#[error(transparent)]
ButtplugMessageError(#[from] ButtplugMessageError),
#[error(transparent)]
ButtplugPingError(#[from] ButtplugPingError),
#[error(transparent)]
ButtplugDeviceError(#[from] ButtplugDeviceError),
#[error(transparent)]
ButtplugUnknownError(#[from] ButtplugUnknownError),
}
impl From<ButtplugServerError> for ButtplugError {
fn from(error: ButtplugServerError) -> Self {
error.error().clone()
}
}
#[derive(Debug, Display, Clone)]
pub struct ButtplugServerError {
msg_id: u32,
error: ButtplugError,
}
impl ButtplugServerError {
pub fn new_message_error(msg_id: u32, error: ButtplugError) -> Self {
Self { msg_id, error }
}
pub fn new_system_error(error: ButtplugError) -> Self {
Self { msg_id: 0, error }
}
pub fn id(&self) -> u32 {
self.msg_id
}
pub fn error(&self) -> &ButtplugError {
&self.error
}
}
impl From<ButtplugError> for ButtplugServerError {
fn from(error: ButtplugError) -> Self {
ButtplugServerError::new_system_error(error)
}
}
impl From<ButtplugMessageError> for ButtplugServerError {
fn from(err: ButtplugMessageError) -> Self {
ButtplugServerError::new_system_error(err.into())
}
}
impl From<ButtplugUnknownError> for ButtplugServerError {
fn from(err: ButtplugUnknownError) -> Self {
ButtplugServerError::new_system_error(err.into())
}
}
impl From<ButtplugDeviceError> for ButtplugServerError {
fn from(err: ButtplugDeviceError) -> Self {
ButtplugServerError::new_system_error(err.into())
}
}
impl From<ButtplugPingError> for ButtplugServerError {
fn from(err: ButtplugPingError) -> Self {
ButtplugServerError::new_system_error(err.into())
}
}
impl From<ButtplugHandshakeError> for ButtplugServerError {
fn from(err: ButtplugHandshakeError) -> Self {
ButtplugServerError::new_system_error(err.into())
}
}
impl std::fmt::Display for ButtplugServerError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.error.fmt(f)
}
}
impl std::error::Error for ButtplugServerError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
self.error.source()
}
}
impl From<messages::Error> for ButtplugServerError {
fn from(error: messages::Error) -> Self {
ButtplugServerError::new_message_error(error.get_id(), ButtplugError::from(error))
}
}
impl<T> From<ButtplugServerError> for BoxFuture<'static, Result<T, ButtplugServerError>>
where
T: Send + 'static,
{
fn from(err: ButtplugServerError) -> BoxFuture<'static, Result<T, ButtplugServerError>> {
Box::pin(future::ready(Err(err)))
}
}
impl From<messages::Error> for ButtplugError {
fn from(error: messages::Error) -> Self {
match error.error_code {
ErrorCode::ErrorDevice => {
ButtplugDeviceError::UntypedDeserializedError(error.error_message).into()
}
ErrorCode::ErrorMessage => {
ButtplugMessageError::UntypedDeserializedError(error.error_message).into()
}
ErrorCode::ErrorHandshake => {
ButtplugHandshakeError::UntypedDeserializedError(error.error_message).into()
}
ErrorCode::ErrorUnknown => {
ButtplugUnknownError::UntypedDeserializedError(error.error_message).into()
}
ErrorCode::ErrorPing => {
ButtplugPingError::UntypedDeserializedError(error.error_message).into()
}
}
}
}