nextcloud-client-api 0.1.0

implementation of the socket API for the NextCloud client
Documentation
use core::{
    fmt::{Display, Formatter, Result as FmtResult},
    result::Result as StdResult,
};

use thiserror::Error as ThisError;

use crate::api_verb::ApiVerb;

pub(crate) struct Message {
    pub(crate) verb: ApiVerb,
    pub(crate) msg: String,
}

#[derive(Debug, ThisError)]
#[non_exhaustive]
pub enum Error {
    #[error("failed to parse status: {0}")]
    ParsingFailed(String),
}

impl From<Message> for String {
    #[inline]
    fn from(value: Message) -> Self {
        Self::from(&value)
    }
}

impl From<&Message> for String {
    #[inline]
    fn from(value: &Message) -> Self {
        format!("{}:{}", value.verb, value.msg)
    }
}

impl TryFrom<String> for Message {
    type Error = Error;

    fn try_from(value: String) -> StdResult<Self, Self::Error> {
        Self::try_from(value.as_str())
    }
}

impl TryFrom<&str> for Message {
    type Error = Error;

    fn try_from(value: &str) -> StdResult<Self, Self::Error> {
        let parts = value.split_once(':');

        let parts_converted = match parts {
            None => (
                ApiVerb::try_from(value)
                    .map_err(|err| Error::ParsingFailed(format!("invalid message: {err}")))?,
                String::new(),
            ),
            Some((verb, msg)) => (
                ApiVerb::try_from(verb)
                    .map_err(|err| Error::ParsingFailed(format!("invalid message: {err}")))?,
                msg.to_owned(),
            ),
        };

        Ok(Self {
            verb: parts_converted.0,
            msg: parts_converted.1,
        })
    }
}

impl Display for Message {
    #[expect(clippy::min_ident_chars, reason = "defined by trait")]
    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
        write!(f, "{}", String::from(self))
    }
}