oxide-update-engine-types 0.1.2

Serializable types for the oxide-update-engine framework.
Documentation
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

//! Errors generated by the types crate.

use crate::spec::{AsError, EngineSpec};
use derive_where::derive_where;
use std::{borrow::Cow, collections::VecDeque, error, fmt};

/// An error that occurs while executing a nested engine.
#[derive_where(Debug)]
pub enum NestedEngineError<S: EngineSpec> {
    Creation {
        error: S::Error,
    },
    StepFailed {
        component: S::Component,
        id: S::StepId,
        description: Cow<'static, str>,
        error: S::Error,
    },
    Aborted {
        component: S::Component,
        id: S::StepId,
        description: Cow<'static, str>,
        message: String,
    },
}

impl<S: EngineSpec> fmt::Display for NestedEngineError<S> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::Creation { .. } => {
                write!(f, "error while creating nested engine")
            }
            Self::StepFailed { description, .. } => {
                write!(f, "step failed: {description}")
            }
            Self::Aborted { description, message, .. } => {
                write!(
                    f,
                    "execution aborted while running step \
                     \"{description}\": {message}"
                )
            }
        }
    }
}

impl<S: EngineSpec> error::Error for NestedEngineError<S> {
    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
        match self {
            Self::Creation { error } => Some(error.as_error()),
            Self::StepFailed { error, .. } => Some(error.as_error()),
            Self::Aborted { .. } => None,
        }
    }
}

/// An error that occurred while converting an event into or from its
/// generic form.
#[derive(Debug)]
pub struct ConvertGenericError {
    pub path: VecDeque<ConvertGenericPathElement>,
    pub error: serde_json::Error,
}

impl ConvertGenericError {
    pub fn new(elem: &'static str, error: serde_json::Error) -> Self {
        Self {
            path: VecDeque::from_iter([ConvertGenericPathElement::Path(elem)]),
            error,
        }
    }

    pub fn parent(mut self, elem: &'static str) -> Self {
        self.path.push_front(ConvertGenericPathElement::Path(elem));
        self
    }

    pub fn parent_array(mut self, elem: &'static str, index: usize) -> Self {
        self.path
            .push_front(ConvertGenericPathElement::ArrayIndex(elem, index));
        self
    }
}

impl fmt::Display for ConvertGenericError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str("error converting path: ")?;
        for (idx, element) in self.path.iter().enumerate() {
            match element {
                ConvertGenericPathElement::Path(path) => f.write_str(path)?,
                ConvertGenericPathElement::ArrayIndex(path, index) => {
                    write!(f, "{path}[{index}]")?
                }
            }
            if idx < self.path.len() - 1 {
                f.write_str(".")?;
            }
        }

        Ok(())
    }
}

impl error::Error for ConvertGenericError {
    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
        Some(&self.error)
    }
}

/// A path element for a [`ConvertGenericError`].
#[derive(Debug, Eq, PartialEq)]
pub enum ConvertGenericPathElement {
    Path(&'static str),
    ArrayIndex(&'static str, usize),
}

/// The `GroupDisplay::add_event_report` method was called with an
/// unknown key.
#[derive(Clone, Debug)]
pub struct UnknownReportKey {}

impl fmt::Display for UnknownReportKey {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str("unknown report key")
    }
}

impl error::Error for UnknownReportKey {}