qubit_json/value/json_value_encoder.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//! Strict projection from Serde values into materialized JSON values.
9
10use serde::Serialize;
11use serde_json::Value;
12
13use self::internal::JsonValueSerializer;
14use crate::encode::JsonSerializationError;
15
16mod internal;
17
18/// Projects serializable values into strict materialized JSON.
19///
20/// The encoder accepts the full signed and unsigned 64-bit JSON integer range,
21/// rejects wider numeric values and non-finite floats, validates map keys, and
22/// rejects duplicate object keys. It owns no resource budget; use
23/// [`crate::encode::JsonEncoder`] when encoded text and resource accounting are
24/// required.
25///
26/// # Examples
27///
28/// ```
29/// use qubit_json::value::JsonValueEncoder;
30/// use serde_json::json;
31///
32/// let encoder = JsonValueEncoder::new();
33/// let value = encoder.encode(&json!({"ok": true}))?;
34/// assert_eq!(value, json!({"ok": true}));
35/// # Ok::<(), qubit_json::encode::JsonSerializationError>(())
36/// ```
37#[derive(Debug, Clone, Copy, Default)]
38pub struct JsonValueEncoder {
39 /// Prevents external struct literals while reserving room for future
40 /// policy.
41 private: (),
42}
43
44impl JsonValueEncoder {
45 /// Creates a strict encoder with the default immutable policy.
46 ///
47 /// # Returns
48 ///
49 /// A reusable encoder that performs no resource accounting.
50 #[must_use]
51 #[inline(always)]
52 pub const fn new() -> Self {
53 Self { private: () }
54 }
55
56 /// Projects one serializable value into strict JSON.
57 ///
58 /// # Type Parameters
59 ///
60 /// * `T` - Source type traversed through its Serde representation.
61 ///
62 /// # Parameters
63 ///
64 /// * `value` - Borrowed value to project without taking ownership.
65 ///
66 /// # Returns
67 ///
68 /// The fully materialized JSON value.
69 ///
70 /// # Errors
71 ///
72 /// Returns a strict value error whose precise kind distinguishes number,
73 /// object-key, RawValue, capacity, serializer-contract, and opaque custom
74 /// failures without retaining arbitrary diagnostic text.
75 pub fn encode<T>(&self, value: &T) -> Result<Value, JsonSerializationError>
76 where
77 T: Serialize + ?Sized,
78 {
79 let () = self.private;
80 value.serialize(JsonValueSerializer)
81 }
82}