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