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