qubit_json/encode/json_encode_error_kind.rs
1// =============================================================================
2// Copyright (c) 2026 Haixing Hu.
3//
4// SPDX-License-Identifier: Apache-2.0
5//
6// Licensed under the Apache License, Version 2.0.
7// =============================================================================
8//! Defines stable categories for JSON encoding failures.
9
10use std::fmt;
11use std::str::FromStr;
12
13/// Represents the coarse category of a JSON encoding failure.
14///
15/// This exhaustive enum is the stable branching contract for strict JSON
16/// encoding. [`JsonEncodeError`](super::JsonEncodeError) keeps its internal
17/// representation private so new implementation details do not affect callers
18/// that branch through this category.
19///
20/// # Examples
21///
22/// ```
23/// use qubit_json::encode::JsonEncodeErrorKind;
24///
25/// let kind = "invalid_raw_json".parse::<JsonEncodeErrorKind>()?;
26/// assert_eq!(kind, JsonEncodeErrorKind::InvalidRawJson);
27/// # Ok::<(), &'static str>(())
28/// ```
29#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
30pub enum JsonEncodeErrorKind {
31 /// Resource accounting rejected the value or output.
32 Budget,
33 /// A `RawValue` field did not contain valid JSON text.
34 InvalidRawJson,
35 /// Serde could not serialize the source value.
36 Serialize,
37 /// The external destination writer rejected output bytes.
38 Write,
39}
40
41impl fmt::Display for JsonEncodeErrorKind {
42 /// Writes the stable snake-case category name.
43 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
44 formatter.write_str(match self {
45 Self::Budget => "budget",
46 Self::InvalidRawJson => "invalid_raw_json",
47 Self::Serialize => "serialize",
48 Self::Write => "write",
49 })
50 }
51}
52
53impl FromStr for JsonEncodeErrorKind {
54 type Err = &'static str;
55
56 /// Parses a stable category name without ASCII case sensitivity.
57 fn from_str(value: &str) -> Result<Self, Self::Err> {
58 if value.eq_ignore_ascii_case("budget") {
59 Ok(Self::Budget)
60 } else if value.eq_ignore_ascii_case("invalid_raw_json") {
61 Ok(Self::InvalidRawJson)
62 } else if value.eq_ignore_ascii_case("serialize") {
63 Ok(Self::Serialize)
64 } else if value.eq_ignore_ascii_case("write") {
65 Ok(Self::Write)
66 } else {
67 Err("unknown JsonEncodeErrorKind")
68 }
69 }
70}