Skip to main content

qubit_metadata/
metadata_error.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026 Haixing Hu.
4 *
5 *    SPDX-License-Identifier: Apache-2.0
6 *
7 *    Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10//! [`MetadataError`] — failures from explicit metadata APIs and schema checks.
11
12use std::fmt;
13
14use qubit_datatype::DataType;
15use qubit_value::{Value, ValueError};
16
17/// Errors produced by explicit metadata accessors and schema validation.
18#[derive(Debug, Clone, PartialEq, Eq)]
19pub enum MetadataError {
20    /// The requested key does not exist.
21    MissingKey(String),
22    /// A stored value cannot be converted to the requested type.
23    TypeMismatch {
24        /// Metadata key being read or validated.
25        key: String,
26        /// Expected data type.
27        expected: DataType,
28        /// Actual stored data type.
29        actual: DataType,
30        /// Human-readable conversion or validation message.
31        message: String,
32    },
33    /// A required schema field is missing from a metadata object.
34    MissingRequiredField {
35        /// Required metadata key.
36        key: String,
37        /// Expected data type for the missing field.
38        expected: DataType,
39    },
40    /// A metadata object contains a key not accepted by the schema.
41    UnknownField {
42        /// Unknown metadata key.
43        key: String,
44    },
45    /// A filter references a key that is not defined by the schema.
46    UnknownFilterField {
47        /// Unknown filter key.
48        key: String,
49    },
50    /// A filter uses an operator that is not compatible with the field type.
51    InvalidFilterOperator {
52        /// Metadata key being filtered.
53        key: String,
54        /// Filter operator name.
55        operator: &'static str,
56        /// Field data type defined by the schema.
57        data_type: DataType,
58        /// Human-readable validation message.
59        message: String,
60    },
61    /// A filter expression is structurally invalid.
62    InvalidFilterExpression {
63        /// Human-readable validation message.
64        message: String,
65    },
66}
67
68impl MetadataError {
69    /// Builds a conversion error for `key` using the requested type and stored value.
70    #[inline]
71    pub(crate) fn conversion_error(
72        key: &str,
73        expected: DataType,
74        value: &Value,
75        error: ValueError,
76    ) -> Self {
77        Self::TypeMismatch {
78            key: key.to_string(),
79            expected,
80            actual: value.data_type(),
81            message: error.to_string(),
82        }
83    }
84
85    /// Builds a schema type-mismatch error for `key`.
86    #[inline]
87    pub(crate) fn type_mismatch(key: &str, expected: DataType, actual: DataType) -> Self {
88        Self::TypeMismatch {
89            key: key.to_string(),
90            expected,
91            actual,
92            message: format!("expected {expected}, got {actual}"),
93        }
94    }
95}
96
97impl fmt::Display for MetadataError {
98    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
99        match self {
100            Self::MissingKey(key) => write!(f, "Metadata key not found: {key}"),
101            Self::TypeMismatch {
102                key,
103                expected,
104                actual,
105                message,
106            } => write!(
107                f,
108                "Metadata key '{key}' expected {expected} but actual {actual}: {message}"
109            ),
110            Self::MissingRequiredField { key, expected } => write!(
111                f,
112                "Required metadata key '{key}' is missing (expected {expected})"
113            ),
114            Self::UnknownField { key } => {
115                write!(f, "Metadata key '{key}' is not defined in schema")
116            }
117            Self::UnknownFilterField { key } => {
118                write!(
119                    f,
120                    "Metadata filter references key '{key}' not defined in schema"
121                )
122            }
123            Self::InvalidFilterOperator {
124                key,
125                operator,
126                data_type,
127                message,
128            } => write!(
129                f,
130                "Metadata filter operator '{operator}' is invalid for key '{key}' with type {data_type}: {message}"
131            ),
132            Self::InvalidFilterExpression { message } => {
133                write!(f, "Metadata filter expression is invalid: {message}")
134            }
135        }
136    }
137}
138
139impl std::error::Error for MetadataError {}