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