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