qubit_value/value_wire/
value_wire_payload_ref_v1.rs1use serde::{
12 Serialize,
13 Serializer,
14};
15
16use crate::multi_values::MultiValuesRepr;
17use crate::value::ValueRepr;
18#[cfg(feature = "json")]
19use crate::wire::JSON_NUMBER_TOKEN;
20#[cfg(feature = "big-decimal")]
21use crate::wire::{
22 MAX_BIG_DECIMAL_ABSOLUTE_SCALE,
23 is_valid_big_decimal_scale,
24};
25use crate::{
26 MultiValues,
27 Value,
28 ValueContainer,
29};
30
31use super::{
32 ValueWireEncodeError,
33 WireShapeRef,
34};
35
36#[must_use]
42pub struct ValueWirePayloadRefV1<'a> {
43 shape: WireShapeRef<'a>,
44}
45
46impl<'a> ValueWirePayloadRefV1<'a> {
47 pub fn from_value(value: &'a Value) -> Result<Self, ValueWireEncodeError> {
49 validate_value(value)?;
50 Ok(Self {
51 shape: WireShapeRef::Scalar(value.into()),
52 })
53 }
54
55 pub fn from_values(
57 values: &'a MultiValues,
58 ) -> Result<Self, ValueWireEncodeError> {
59 validate_values(values)?;
60 Ok(Self {
61 shape: WireShapeRef::Collection(values.into()),
62 })
63 }
64
65 pub fn from_container(
67 value: &'a ValueContainer,
68 ) -> Result<Self, ValueWireEncodeError> {
69 match value {
70 ValueContainer::Scalar(value) => validate_value(value)?,
71 ValueContainer::Collection(values) => validate_values(values)?,
72 }
73 Ok(Self {
74 shape: value.into(),
75 })
76 }
77
78 pub(in crate::value_wire) fn shape(&self) -> WireShapeRef<'a> {
80 self.shape
81 }
82}
83
84pub(in crate::value_wire) fn validate_value(
86 value: &Value,
87) -> Result<(), ValueWireEncodeError> {
88 #[cfg(feature = "big-decimal")]
89 if let ValueRepr::BigDecimal(value) = &value.repr {
90 validate_big_decimal_scale(value.as_bigint_and_exponent().1)?;
91 }
92 let non_finite = matches!(&value.repr, ValueRepr::Float32(value) if !value.is_finite())
93 || matches!(&value.repr, ValueRepr::Float64(value) if !value.is_finite());
94 if non_finite {
95 return Err(ValueWireEncodeError::NonFiniteFloat {
96 data_type: value.data_type(),
97 });
98 }
99 #[cfg(feature = "json")]
100 if let ValueRepr::Json(value) = &value.repr {
101 validate_json_value(value)?;
102 }
103 Ok(())
104}
105
106pub(in crate::value_wire) fn validate_values(
108 values: &MultiValues,
109) -> Result<(), ValueWireEncodeError> {
110 #[cfg(feature = "big-decimal")]
111 if let MultiValuesRepr::BigDecimal(values) = &values.repr {
112 for value in values {
113 validate_big_decimal_scale(value.as_bigint_and_exponent().1)?;
114 }
115 }
116 let non_finite = match &values.repr {
117 MultiValuesRepr::Float32(values) => {
118 values.iter().any(|value| !value.is_finite())
119 }
120 MultiValuesRepr::Float64(values) => {
121 values.iter().any(|value| !value.is_finite())
122 }
123 _ => false,
124 };
125 if non_finite {
126 return Err(ValueWireEncodeError::NonFiniteFloat {
127 data_type: values.data_type(),
128 });
129 }
130 #[cfg(feature = "json")]
131 if let MultiValuesRepr::Json(values) = &values.repr {
132 for value in values {
133 validate_json_value(value)?;
134 }
135 }
136 Ok(())
137}
138
139#[cfg(feature = "json")]
141fn validate_json_value(
142 value: &serde_json::Value,
143) -> Result<(), ValueWireEncodeError> {
144 match value {
145 serde_json::Value::Array(values) => {
146 for value in values {
147 validate_json_value(value)?;
148 }
149 }
150 serde_json::Value::Object(values) => {
151 if values.contains_key(JSON_NUMBER_TOKEN) {
152 return Err(ValueWireEncodeError::ReservedJsonObjectKey {
153 key: JSON_NUMBER_TOKEN,
154 });
155 }
156 for value in values.values() {
157 validate_json_value(value)?;
158 }
159 }
160 serde_json::Value::Null
161 | serde_json::Value::Bool(_)
162 | serde_json::Value::Number(_)
163 | serde_json::Value::String(_) => {}
164 }
165 Ok(())
166}
167
168#[cfg(feature = "big-decimal")]
170fn validate_big_decimal_scale(scale: i64) -> Result<(), ValueWireEncodeError> {
171 if is_valid_big_decimal_scale(scale) {
172 return Ok(());
173 }
174 Err(ValueWireEncodeError::BigDecimalScaleTooLarge {
175 scale,
176 maximum_absolute_scale: MAX_BIG_DECIMAL_ABSOLUTE_SCALE,
177 })
178}
179
180impl<'a> TryFrom<&'a Value> for ValueWirePayloadRefV1<'a> {
181 type Error = ValueWireEncodeError;
182 fn try_from(value: &'a Value) -> Result<Self, Self::Error> {
184 Self::from_value(value)
185 }
186}
187
188impl<'a> TryFrom<&'a MultiValues> for ValueWirePayloadRefV1<'a> {
189 type Error = ValueWireEncodeError;
190 fn try_from(values: &'a MultiValues) -> Result<Self, Self::Error> {
192 Self::from_values(values)
193 }
194}
195
196impl<'a> TryFrom<&'a ValueContainer> for ValueWirePayloadRefV1<'a> {
197 type Error = ValueWireEncodeError;
198 fn try_from(value: &'a ValueContainer) -> Result<Self, Self::Error> {
200 Self::from_container(value)
201 }
202}
203
204impl Serialize for ValueWirePayloadRefV1<'_> {
205 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
207 where
208 S: Serializer,
209 {
210 self.shape().serialize(serializer)
211 }
212}