diff options
-rw-r--r-- | serde_v8/ser.rs | 27 | ||||
-rw-r--r-- | serde_v8/tests/ser.rs | 24 |
2 files changed, 47 insertions, 4 deletions
diff --git a/serde_v8/ser.rs b/serde_v8/ser.rs index 0c6c52da0..31d3e3144 100644 --- a/serde_v8/ser.rs +++ b/serde_v8/ser.rs @@ -377,6 +377,9 @@ macro_rules! forward_to { }; } +const MAX_SAFE_INTEGER: i64 = (1 << 53) - 1; +const MIN_SAFE_INTEGER: i64 = -MAX_SAFE_INTEGER; + impl<'a, 'b, 'c> ser::Serializer for Serializer<'a, 'b, 'c> { type Ok = v8::Local<'a, v8::Value>; type Error = Error; @@ -399,8 +402,6 @@ impl<'a, 'b, 'c> ser::Serializer for Serializer<'a, 'b, 'c> { serialize_u16(u16, serialize_u32, 'a); serialize_f32(f32, serialize_f64, 'a); - serialize_u64(u64, serialize_f64, 'a); - serialize_i64(i64, serialize_f64, 'a); } fn serialize_i32(self, v: i32) -> JsResult<'a> { @@ -411,6 +412,28 @@ impl<'a, 'b, 'c> ser::Serializer for Serializer<'a, 'b, 'c> { Ok(v8::Integer::new_from_unsigned(&mut self.scope.borrow_mut(), v).into()) } + fn serialize_i64(self, v: i64) -> JsResult<'a> { + let s = &mut self.scope.borrow_mut(); + // If i64 can fit in max safe integer bounds then serialize as v8::Number + // otherwise serialize as v8::BigInt + if (MIN_SAFE_INTEGER..=MAX_SAFE_INTEGER).contains(&v) { + Ok(v8::Number::new(s, v as _).into()) + } else { + Ok(v8::BigInt::new_from_i64(s, v).into()) + } + } + + fn serialize_u64(self, v: u64) -> JsResult<'a> { + let s = &mut self.scope.borrow_mut(); + // If u64 can fit in max safe integer bounds then serialize as v8::Number + // otherwise serialize as v8::BigInt + if v <= (MAX_SAFE_INTEGER as u64) { + Ok(v8::Number::new(s, v as _).into()) + } else { + Ok(v8::BigInt::new_from_u64(s, v).into()) + } + } + fn serialize_f64(self, v: f64) -> JsResult<'a> { Ok(v8::Number::new(&mut self.scope.borrow_mut(), v).into()) } diff --git a/serde_v8/tests/ser.rs b/serde_v8/tests/ser.rs index 76a43bdcc..0d8d42fe6 100644 --- a/serde_v8/tests/ser.rs +++ b/serde_v8/tests/ser.rs @@ -109,7 +109,13 @@ sertest!(ser_option_some, Some(true), "x === true"); sertest!(ser_option_null, None as Option<bool>, "x === null"); sertest!(ser_unit_null, (), "x === null"); sertest!(ser_bool, true, "x === true"); -sertest!(ser_u64, 32, "x === 32"); +sertest!(ser_u64, 9007199254740991_u64, "x === 9007199254740991"); +sertest!(ser_big_int, 9007199254740992_i64, "x === 9007199254740992n"); +sertest!( + ser_neg_big_int, + -9007199254740992_i64, + "x === -9007199254740992n" +); sertest!(ser_f64, 12345.0, "x === 12345.0"); sertest!(ser_string, "Hello", "x === 'Hello'"); sertest!(ser_bytes, b"\x01\x02\x03", "arrEqual(x, [1, 2, 3])"); @@ -145,7 +151,21 @@ sertest!( //// sertest!(ser_json_bool, json!(true), "x === true"); sertest!(ser_json_null, json!(null), "x === null"); -sertest!(ser_json_int, json!(123), "x === 123"); +sertest!( + ser_json_int, + json!(9007199254740991_u64), + "x === 9007199254740991" +); +sertest!( + ser_json_big_int, + json!(9007199254740992_i64), + "x === 9007199254740992n" +); +sertest!( + ser_json_neg_big_int, + json!(-9007199254740992_i64), + "x === -9007199254740992n" +); sertest!(ser_json_f64, json!(123.45), "x === 123.45"); sertest!(ser_json_string, json!("Hello World"), "x === 'Hello World'"); sertest!(ser_json_obj_empty, json!({}), "objEqual(x, {})"); |