Skip to main content

qubit_metadata/
error.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026.
4 *    Haixing Hu, Qubit Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9//! Error types and lightweight type introspection for [`Metadata`](crate::Metadata).
10
11use std::fmt;
12
13use serde_json::Value;
14
15/// Coarse-grained JSON value kinds used by [`MetadataError`] and inspection APIs.
16///
17/// `Metadata` stores arbitrary [`serde_json::Value`] instances, so it cannot
18/// recover the caller's original Rust type. `MetadataValueKind` is therefore a
19/// JSON-level classification, analogous to the stricter `data_type()` concept
20/// in `qubit-value`, but tailored to an open-ended JSON model.
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
22pub enum MetadataValueKind {
23    /// JSON `null`.
24    Null,
25    /// JSON boolean.
26    Bool,
27    /// JSON number.
28    Number,
29    /// JSON string.
30    String,
31    /// JSON array.
32    Array,
33    /// JSON object.
34    Object,
35}
36
37impl MetadataValueKind {
38    /// Returns the JSON kind of `value`.
39    #[inline]
40    pub fn of(value: &Value) -> Self {
41        match value {
42            Value::Null => Self::Null,
43            Value::Bool(_) => Self::Bool,
44            Value::Number(_) => Self::Number,
45            Value::String(_) => Self::String,
46            Value::Array(_) => Self::Array,
47            Value::Object(_) => Self::Object,
48        }
49    }
50}
51
52impl From<&Value> for MetadataValueKind {
53    #[inline]
54    fn from(value: &Value) -> Self {
55        Self::of(value)
56    }
57}
58
59impl fmt::Display for MetadataValueKind {
60    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61        let text = match self {
62            Self::Null => "null",
63            Self::Bool => "bool",
64            Self::Number => "number",
65            Self::String => "string",
66            Self::Array => "array",
67            Self::Object => "object",
68        };
69        f.write_str(text)
70    }
71}
72
73/// Errors produced by explicit `Metadata` accessors such as
74/// [`Metadata::try_get`](crate::Metadata::try_get) and
75/// [`Metadata::try_set`](crate::Metadata::try_set).
76#[derive(Debug, Clone, PartialEq, Eq)]
77pub enum MetadataError {
78    /// The requested key does not exist.
79    MissingKey(String),
80    /// Serialization into [`serde_json::Value`] failed while storing a value.
81    SerializationError {
82        /// Metadata key being written.
83        key: String,
84        /// Human-readable serde error message.
85        message: String,
86    },
87    /// Deserialization from [`serde_json::Value`] failed while loading a value.
88    DeserializationError {
89        /// Metadata key being read.
90        key: String,
91        /// Fully-qualified Rust type name requested by the caller.
92        expected: &'static str,
93        /// Actual JSON kind stored under the key.
94        actual: MetadataValueKind,
95        /// Human-readable serde error message.
96        message: String,
97    },
98}
99
100impl MetadataError {
101    /// Constructs a deserialization error for key `key`.
102    #[inline]
103    pub(crate) fn deserialization_error<T>(
104        key: &str,
105        value: &Value,
106        error: serde_json::Error,
107    ) -> Self {
108        Self::DeserializationError {
109            key: key.to_string(),
110            expected: std::any::type_name::<T>(),
111            actual: MetadataValueKind::of(value),
112            message: error.to_string(),
113        }
114    }
115
116    /// Constructs a serialization error for key `key`.
117    #[inline]
118    pub(crate) fn serialization_error(key: String, error: serde_json::Error) -> Self {
119        Self::SerializationError {
120            key,
121            message: error.to_string(),
122        }
123    }
124}
125
126impl fmt::Display for MetadataError {
127    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
128        match self {
129            Self::MissingKey(key) => write!(f, "Metadata key not found: {key}"),
130            Self::SerializationError { key, message } => {
131                write!(f, "Failed to serialize metadata value for key '{key}': {message}")
132            }
133            Self::DeserializationError {
134                key,
135                expected,
136                actual,
137                message,
138            } => write!(
139                f,
140                "Failed to deserialize metadata key '{key}' as {expected} from JSON {actual}: {message}"
141            ),
142        }
143    }
144}
145
146impl std::error::Error for MetadataError {}
147
148/// Result type used by explicit `Metadata` operations that report failure
149/// reasons instead of collapsing them into `None`.
150pub type MetadataResult<T> = Result<T, MetadataError>;