ocpp_rs 0.4.2

no_std + alloc OCPP 1.6 and 2.1 protocol library (OCPP-J parse/serialize, CallResult correlation).
Documentation
use alloc::string::{FromUtf8Error, String, ToString};
use core::{fmt::Display, num::ParseIntError};

use crate::validate::ConstraintViolation;

pub type Result<T> = core::result::Result<T, Error>;

#[derive(Debug)]
pub enum Error {
    SerdeJson(serde_json::Error),
    ParseInt(ParseIntError),
    Utf8(FromUtf8Error),
    InvalidMessageCallType,
    InvalidMessageCallTypeParsing,
    /// Message type number outside the supported OCPP-J range (or unknown).
    UnsupportedMessageType(u8),
    /// No pending CALL was registered for this CALLRESULT `messageId`.
    UnknownPendingMessageId(String),
    /// Action name string is not a known OCPP 1.6 or 2.1 CALL action.
    UnknownActionName(String),
    /// `CallResult` payload matched multiple response schemas and no single action was supplied.
    AmbiguousCallResult(String),
    CallTypeMismatch(CallTypeMismatch),
    /// OCPP-J requires CALLRESULT / CALLERROR details payloads to be JSON objects.
    InvalidPayloadShape(&'static str),
    /// `MessageId` longer than 36 characters, or (with `schema_validate`) a payload bounds failure.
    ConstraintViolation(ConstraintViolation),
    Custom(String),
}

impl Error {
    pub fn custom(val: impl Display + ToString) -> Self {
        Self::Custom(val.to_string())
    }
}

impl From<&str> for Error {
    fn from(s: &str) -> Self {
        Self::Custom(s.to_string())
    }
}

impl From<ConstraintViolation> for Error {
    fn from(v: ConstraintViolation) -> Self {
        Self::ConstraintViolation(v)
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
        match self {
            Self::SerdeJson(e) => write!(f, "SerdeJson: {e}"),
            Self::ParseInt(e) => write!(f, "ParseInt: {e}"),
            Self::Utf8(e) => write!(f, "Utf8: {e}"),
            Self::InvalidMessageCallType => write!(f, "InvalidMessageCallType"),
            Self::InvalidMessageCallTypeParsing => write!(f, "InvalidMessageCallTypeParsing"),
            Self::UnsupportedMessageType(t) => write!(f, "UnsupportedMessageType: {t}"),
            Self::UnknownPendingMessageId(id) => {
                write!(f, "UnknownPendingMessageId: {id}")
            }
            Self::UnknownActionName(name) => write!(f, "UnknownActionName: {name}"),
            Self::AmbiguousCallResult(detail) => write!(f, "AmbiguousCallResult: {detail}"),
            Self::CallTypeMismatch(e) => write!(f, "CallTypeMismatch: {e:?}"),
            Self::InvalidPayloadShape(msg) => write!(f, "InvalidPayloadShape: {msg}"),
            Self::ConstraintViolation(e) => write!(f, "ConstraintViolation: {e}"),
            Self::Custom(e) => write!(f, "{e}"),
        }
    }
}

impl core::error::Error for Error {}

#[derive(Debug)]
pub struct CallTypeMismatch {
    pub expected: i32,
    pub found: i32,
}