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 {}