vmotherboard/chipset/builder/
errors.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use crate::chipset::PciConflict;
5use crate::chipset::io_ranges::IoRangeConflict;
6use std::fmt::Debug;
7use thiserror::Error;
8
9/// An error occurred as part of Chipset initialization
10// DEVNOTE: many of these _could_ potentially be lifted to compile time through
11// the use of a `typed_builder`...
12#[derive(Debug, Error)]
13#[expect(clippy::enum_variant_names)] // these are descriptive
14pub enum ChipsetBuilderError {
15    /// detected static mmio intercept region conflict
16    #[error("static mmio intercept region conflict: {0}")]
17    MmioConflict(IoRangeConflict<u64>),
18    /// detected static pio intercept region conflict
19    #[error("static pio intercept region conflict: {0}")]
20    PioConflict(IoRangeConflict<u16>),
21    /// detected static pci address conflict
22    #[error("static pci conflict: {0}")]
23    PciConflict(PciConflict),
24}
25
26#[derive(Debug, Error)]
27#[error("detected one or more errors during vmotherboard init:")]
28pub struct FinalChipsetBuilderError(#[source] pub ErrorList);
29
30#[derive(Debug)]
31pub struct ErrorList {
32    err: ChipsetBuilderError,
33    next: Option<Box<Self>>,
34}
35
36impl std::fmt::Display for ErrorList {
37    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38        write!(f, "{}", self.err)
39    }
40}
41
42impl ErrorList {
43    fn new(err: ChipsetBuilderError) -> Self {
44        Self { err, next: None }
45    }
46
47    fn chain(self: Box<Self>, err: ChipsetBuilderError) -> Self {
48        Self {
49            err,
50            next: Some(self),
51        }
52    }
53}
54
55pub trait ErrorListExt {
56    fn append(&mut self, err: ChipsetBuilderError);
57}
58
59impl ErrorListExt for Option<ErrorList> {
60    fn append(&mut self, err: ChipsetBuilderError) {
61        *self = Some(match self.take() {
62            Some(existing) => Box::new(existing).chain(err),
63            None => ErrorList::new(err),
64        })
65    }
66}
67
68impl std::error::Error for ErrorList {
69    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
70        self.next.as_ref().map(|x| x as _)
71    }
72}