ascom-alpaca 1.0.0-beta.10

Rust implementation of the ASCOM Alpaca API for astronomy devices
Documentation
use super::{Error, ResponseWithTransaction};
use crate::response::ValueResponse;
use crate::{ASCOMError, ASCOMErrorCode, ASCOMResult};
use axum::Json;
use axum::response::{IntoResponse, Response};
use http::StatusCode;
use serde::Serialize;

impl<T: Serialize> IntoResponse for ResponseWithTransaction<ValueResponse<T>> {
    fn into_response(self) -> Response {
        Json(self).into_response()
    }
}

impl<T: Serialize> IntoResponse for ResponseWithTransaction<ASCOMResult<T>> {
    fn into_response(self) -> Response {
        #[derive(Serialize)]
        struct Repr<T> {
            #[serde(flatten)]
            error: ASCOMError,
            #[serde(rename = "Value")]
            #[serde(skip_serializing_if = "Option::is_none")]
            value: Option<T>,
        }

        Json(ResponseWithTransaction {
            transaction: self.transaction,
            response: match self.response {
                Ok(value) => Repr {
                    error: ASCOMError::OK,
                    value: Some(value),
                },
                Err(error) => {
                    if error.code == ASCOMErrorCode::NOT_IMPLEMENTED {
                        tracing::warn!("Alpaca method is not implemented");
                    } else {
                        tracing::error!(%error, "Alpaca method returned an error");
                    }
                    Repr { error, value: None }
                }
            },
        })
        .into_response()
    }
}

impl<T> IntoResponse for ResponseWithTransaction<super::Result<T>>
where
    ResponseWithTransaction<ASCOMResult<T>>: IntoResponse,
{
    fn into_response(self) -> Response {
        match self.response {
            Ok(response) => Ok(Ok(response)),
            Err(Error::Ascom(err)) => Ok(Err(err)),
            Err(err @ (Error::MissingParameter { .. } | Error::BadParameter { .. })) => {
                Err((StatusCode::BAD_REQUEST, err.to_string()))
            }
            Err(err @ (Error::UnknownDeviceNumber { .. } | Error::UnknownAction { .. })) => {
                Err((StatusCode::NOT_FOUND, err.to_string()))
            }
        }
        .map(|ascom_result| ResponseWithTransaction {
            transaction: self.transaction,
            response: ascom_result,
        })
        .into_response()
    }
}