1use js_sys::{Array, JsString, Map, Number, Object, Uint8Array};
2use serde::ser::{self, Error as _, Serialize};
3use wasm_bindgen::prelude::*;
4use wasm_bindgen::JsCast;
5
6use super::{static_str_to_js, Error, ObjectExt};
7
8type Result<T = JsValue> = super::Result<T>;
9
10pub struct VariantSerializer<S> {
13 variant: &'static str,
14 inner: S,
15}
16
17impl<S> VariantSerializer<S> {
18 pub const fn new(variant: &'static str, inner: S) -> Self {
19 Self { variant, inner }
20 }
21
22 fn end(self, inner: impl FnOnce(S) -> Result) -> Result {
23 let value = inner(self.inner)?;
24 let obj = Object::new();
25 obj.unchecked_ref::<ObjectExt>()
26 .set(static_str_to_js(self.variant), value);
27 Ok(obj.into())
28 }
29}
30
31impl<S: ser::SerializeTupleStruct<Ok = JsValue, Error = Error>> ser::SerializeTupleVariant
32 for VariantSerializer<S>
33{
34 type Ok = JsValue;
35 type Error = Error;
36
37 fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<()> {
38 self.inner.serialize_field(value)
39 }
40
41 fn end(self) -> Result {
42 self.end(S::end)
43 }
44}
45
46impl<S: ser::SerializeStruct<Ok = JsValue, Error = Error>> ser::SerializeStructVariant
47 for VariantSerializer<S>
48{
49 type Ok = JsValue;
50 type Error = Error;
51
52 fn serialize_field<T: ?Sized + Serialize>(
53 &mut self,
54 key: &'static str,
55 value: &T,
56 ) -> Result<()> {
57 self.inner.serialize_field(key, value)
58 }
59
60 fn end(self) -> Result {
61 self.end(S::end)
62 }
63}
64
65pub struct ArraySerializer<'s> {
66 serializer: &'s Serializer,
67 target: Array,
68 idx: u32,
69}
70
71impl<'s> ArraySerializer<'s> {
72 pub fn new(serializer: &'s Serializer) -> Self {
73 Self {
74 serializer,
75 target: Array::new(),
76 idx: 0,
77 }
78 }
79}
80
81impl ser::SerializeSeq for ArraySerializer<'_> {
82 type Ok = JsValue;
83 type Error = Error;
84
85 fn serialize_element<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<()> {
86 self.target.set(self.idx, value.serialize(self.serializer)?);
87 self.idx += 1;
88 Ok(())
89 }
90
91 fn end(self) -> Result {
92 Ok(self.target.into())
93 }
94}
95
96impl ser::SerializeTuple for ArraySerializer<'_> {
97 type Ok = JsValue;
98 type Error = Error;
99
100 fn serialize_element<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<()> {
101 ser::SerializeSeq::serialize_element(self, value)
102 }
103
104 fn end(self) -> Result {
105 ser::SerializeSeq::end(self)
106 }
107}
108
109impl ser::SerializeTupleStruct for ArraySerializer<'_> {
110 type Ok = JsValue;
111 type Error = Error;
112
113 fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<()> {
114 ser::SerializeTuple::serialize_element(self, value)
115 }
116
117 fn end(self) -> Result {
118 ser::SerializeTuple::end(self)
119 }
120}
121
122pub enum MapResult {
123 Map(Map),
124 Object(Object),
125}
126
127pub struct MapSerializer<'s> {
128 serializer: &'s Serializer,
129 target: MapResult,
130 next_key: Option<JsValue>,
131}
132
133impl<'s> MapSerializer<'s> {
134 pub fn new(serializer: &'s Serializer, as_object: bool) -> Self {
135 Self {
136 serializer,
137 target: if as_object {
138 MapResult::Object(Object::new())
139 } else {
140 MapResult::Map(Map::new())
141 },
142 next_key: None,
143 }
144 }
145}
146
147impl ser::SerializeMap for MapSerializer<'_> {
148 type Ok = JsValue;
149 type Error = Error;
150
151 fn serialize_key<T: ?Sized + Serialize>(&mut self, key: &T) -> Result<()> {
152 debug_assert!(self.next_key.is_none());
153 self.next_key = Some(key.serialize(self.serializer)?);
154 Ok(())
155 }
156
157 fn serialize_value<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<()> {
158 let key = self.next_key.take().unwrap_throw();
159 let value_ser = value.serialize(self.serializer)?;
160 match &self.target {
161 MapResult::Map(map) => {
162 map.set(&key, &value_ser);
163 }
164 MapResult::Object(object) => {
165 let key = key.dyn_into::<JsString>().map_err(|_| {
166 Error::custom("Map key is not a string and cannot be an object key")
167 })?;
168 object.unchecked_ref::<ObjectExt>().set(key, value_ser);
169 }
170 }
171 Ok(())
172 }
173
174 fn end(self) -> Result {
175 debug_assert!(self.next_key.is_none());
176 match self.target {
177 MapResult::Map(map) => Ok(map.into()),
178 MapResult::Object(object) => Ok(object.into()),
179 }
180 }
181}
182
183pub struct ObjectSerializer<'s> {
184 serializer: &'s Serializer,
185 target: ObjectExt,
186}
187
188impl<'s> ObjectSerializer<'s> {
189 pub fn new(serializer: &'s Serializer) -> Self {
190 Self {
191 serializer,
192 target: Object::new().unchecked_into::<ObjectExt>(),
193 }
194 }
195}
196
197impl ser::SerializeStruct for ObjectSerializer<'_> {
198 type Ok = JsValue;
199 type Error = Error;
200
201 fn serialize_field<T: ?Sized + Serialize>(
202 &mut self,
203 key: &'static str,
204 value: &T,
205 ) -> Result<()> {
206 let value = value.serialize(self.serializer)?;
207 self.target.set(static_str_to_js(key), value);
208 Ok(())
209 }
210
211 fn end(self) -> Result {
212 Ok(self.target.into())
213 }
214}
215
216#[derive(Default)]
218pub struct Serializer {
219 serialize_missing_as_null: bool,
220 serialize_maps_as_objects: bool,
221 serialize_large_number_types_as_bigints: bool,
222 serialize_bytes_as_arrays: bool,
223}
224
225impl Serializer {
226 pub const fn new() -> Self {
228 Self {
229 serialize_missing_as_null: false,
230 serialize_maps_as_objects: false,
231 serialize_large_number_types_as_bigints: false,
232 serialize_bytes_as_arrays: false,
233 }
234 }
235
236 pub const fn json_compatible() -> Self {
241 Self {
242 serialize_missing_as_null: true,
243 serialize_maps_as_objects: true,
244 serialize_large_number_types_as_bigints: false,
245 serialize_bytes_as_arrays: true,
246 }
247 }
248
249 pub const fn serialize_missing_as_null(mut self, value: bool) -> Self {
252 self.serialize_missing_as_null = value;
253 self
254 }
255
256 pub const fn serialize_maps_as_objects(mut self, value: bool) -> Self {
259 self.serialize_maps_as_objects = value;
260 self
261 }
262
263 pub const fn serialize_large_number_types_as_bigints(mut self, value: bool) -> Self {
266 self.serialize_large_number_types_as_bigints = value;
267 self
268 }
269
270 pub const fn serialize_bytes_as_arrays(mut self, value: bool) -> Self {
273 self.serialize_bytes_as_arrays = value;
274 self
275 }
276}
277
278macro_rules! forward_to_into {
279 ($($name:ident($ty:ty);)*) => {
280 $(fn $name(self, v: $ty) -> Result {
281 Ok(v.into())
282 })*
283 };
284}
285
286impl<'s> ser::Serializer for &'s Serializer {
287 type Ok = JsValue;
288 type Error = Error;
289
290 type SerializeSeq = ArraySerializer<'s>;
291 type SerializeTuple = ArraySerializer<'s>;
292 type SerializeTupleStruct = ArraySerializer<'s>;
293 type SerializeTupleVariant = VariantSerializer<ArraySerializer<'s>>;
294 type SerializeMap = MapSerializer<'s>;
295 type SerializeStruct = ObjectSerializer<'s>;
296 type SerializeStructVariant = VariantSerializer<ObjectSerializer<'s>>;
297
298 forward_to_into! {
299 serialize_bool(bool);
300
301 serialize_i8(i8);
302 serialize_i16(i16);
303 serialize_i32(i32);
304
305 serialize_u8(u8);
306 serialize_u16(u16);
307 serialize_u32(u32);
308
309 serialize_f32(f32);
310 serialize_f64(f64);
311
312 serialize_str(&str);
313 }
314
315 fn serialize_i64(self, v: i64) -> Result {
316 if self.serialize_large_number_types_as_bigints {
317 return Ok(v.into());
318 }
319
320 const MIN_SAFE_INTEGER: i64 = Number::MIN_SAFE_INTEGER as i64;
323 const MAX_SAFE_INTEGER: i64 = Number::MAX_SAFE_INTEGER as i64;
324
325 if (MIN_SAFE_INTEGER..=MAX_SAFE_INTEGER).contains(&v) {
326 self.serialize_f64(v as _)
327 } else {
328 Err(Error::custom(format_args!(
329 "{} can't be represented as a JavaScript number",
330 v
331 )))
332 }
333 }
334
335 fn serialize_u64(self, v: u64) -> Result {
336 if self.serialize_large_number_types_as_bigints {
337 return Ok(v.into());
338 }
339
340 if v <= Number::MAX_SAFE_INTEGER as u64 {
341 self.serialize_f64(v as _)
342 } else {
343 Err(Error::custom(format_args!(
344 "{} can't be represented as a JavaScript number",
345 v
346 )))
347 }
348 }
349
350 fn serialize_i128(self, v: i128) -> Result {
351 Ok(JsValue::from(v))
352 }
353
354 fn serialize_u128(self, v: u128) -> Result {
355 Ok(JsValue::from(v))
356 }
357
358 fn serialize_char(self, v: char) -> Result {
359 Ok(JsString::from(v).into())
360 }
361
362 fn serialize_bytes(self, v: &[u8]) -> Result {
363 let view = unsafe { Uint8Array::view(v) };
368 if self.serialize_bytes_as_arrays {
369 Ok(JsValue::from(Array::from(view.as_ref())))
370 } else {
371 Ok(JsValue::from(Uint8Array::new(view.as_ref())))
372 }
373 }
374
375 fn serialize_none(self) -> Result {
376 self.serialize_unit()
377 }
378
379 fn serialize_some<T: ?Sized + Serialize>(self, value: &T) -> Result {
380 value.serialize(self)
381 }
382
383 fn serialize_unit(self) -> Result {
384 Ok(if self.serialize_missing_as_null {
385 JsValue::NULL
386 } else {
387 JsValue::UNDEFINED
388 })
389 }
390
391 fn serialize_unit_struct(self, _name: &'static str) -> Result {
392 self.serialize_unit()
393 }
394
395 fn serialize_unit_variant(
397 self,
398 _name: &'static str,
399 _variant_index: u32,
400 variant: &'static str,
401 ) -> Result {
402 Ok(static_str_to_js(variant).into())
403 }
404
405 fn serialize_newtype_struct<T: ?Sized + Serialize>(
406 self,
407 _name: &'static str,
408 value: &T,
409 ) -> Result {
410 value.serialize(self)
411 }
412
413 fn serialize_newtype_variant<T: ?Sized + Serialize>(
414 self,
415 _name: &'static str,
416 _variant_index: u32,
417 variant: &'static str,
418 value: &T,
419 ) -> Result {
420 VariantSerializer::new(variant, self.serialize_newtype_struct(variant, value)?).end(Ok)
421 }
422
423 fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
426 Ok(ArraySerializer::new(self))
427 }
428
429 fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple> {
430 self.serialize_seq(Some(len))
431 }
432
433 fn serialize_tuple_struct(
434 self,
435 _name: &'static str,
436 len: usize,
437 ) -> Result<Self::SerializeTupleStruct> {
438 self.serialize_tuple(len)
439 }
440
441 fn serialize_tuple_variant(
442 self,
443 _name: &'static str,
444 _variant_index: u32,
445 variant: &'static str,
446 len: usize,
447 ) -> Result<Self::SerializeTupleVariant> {
448 Ok(VariantSerializer::new(
449 variant,
450 self.serialize_tuple_struct(variant, len)?,
451 ))
452 }
453
454 fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
456 Ok(MapSerializer::new(self, self.serialize_maps_as_objects))
457 }
458
459 fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeStruct> {
461 Ok(ObjectSerializer::new(self))
462 }
463
464 fn serialize_struct_variant(
465 self,
466 _name: &'static str,
467 _variant_index: u32,
468 variant: &'static str,
469 len: usize,
470 ) -> Result<Self::SerializeStructVariant> {
471 Ok(VariantSerializer::new(
472 variant,
473 self.serialize_struct(variant, len)?,
474 ))
475 }
476}