From 499a8a79d63e278aca6847b7de420bbe15bb3c91 Mon Sep 17 00:00:00 2001 From: K Date: Sat, 19 Mar 2022 11:40:52 +0500 Subject: [PATCH 1/6] Update neon to 0.10 --- CHANGELOG.md | 4 ++++ Cargo.toml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ed32d2..e4242bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ Change Log ========== +## Version 0.10.0 + +* Update to neon 0.10.0 + ## Version 0.8.0 * Update to neon 0.8.0 diff --git a/Cargo.toml b/Cargo.toml index 0099ef1..0e1c86c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "neon-serde2" -version = "0.8.0" +version = "0.10.0" authors = [ "Damir Jelić ", "Gabriel Castro " @@ -15,7 +15,7 @@ serde = "1.0" error-chain = "0.12.4" [dependencies.neon] -version = "0.8" +version = "0.10" default-features = false features = ["default-panic-hook", "napi-6", "try-catch-api", "event-queue-api"] From ee8fd55b95f6f603c7f9b06535ec78ddc908b396 Mon Sep 17 00:00:00 2001 From: K Date: Sat, 19 Mar 2022 13:39:05 +0500 Subject: [PATCH 2/6] Re-implement Error type without deprecated error-chain --- Cargo.toml | 1 - src/de.rs | 74 +++++++++++++--------- src/errors.rs | 170 ++++++++++++++++++++++++++++++-------------------- src/lib.rs | 2 - src/ser.rs | 37 +++++------ 5 files changed, 166 insertions(+), 118 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0e1c86c..912d36d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,6 @@ readme = "readme.md" [dependencies] serde = "1.0" -error-chain = "0.12.4" [dependencies.neon] version = "0.10" diff --git a/src/de.rs b/src/de.rs index 4556c19..4ae2a3b 100644 --- a/src/de.rs +++ b/src/de.rs @@ -2,20 +2,19 @@ //! Deserialize a `JsValue` into a Rust data structure //! -use errors::Error as LibError; -use errors::ErrorKind; -use errors::Result as LibResult; -use neon::prelude::*; +use errors::{Error as LibError, Result as LibResult}; +use neon::{prelude::*, types::buffer::TypedArray}; use serde; -use serde::de::Visitor; -use serde::de::{DeserializeOwned, DeserializeSeed, EnumAccess, MapAccess, SeqAccess, Unexpected, - VariantAccess}; +use serde::de::{ + DeserializeOwned, DeserializeSeed, EnumAccess, MapAccess, SeqAccess, Unexpected, VariantAccess, + Visitor, +}; /// Deserialize an instance of type `T` from a `Handle` /// /// # Errors /// -/// Can fail for various reasons see `ErrorKind` +/// Can fail for various reasons see `Error` /// pub fn from_value<'j, C, T>(cx: &mut C, value: Handle<'j, JsValue>) -> LibResult where @@ -27,6 +26,12 @@ where Ok(t) } +/// Deserialize an instance of type `T` from an `Option>` +/// +/// # Errors +/// +/// Can fail for various reasons see `Error` +/// pub fn from_value_opt<'j, C, T>(cx: &mut C, value: Option>) -> LibResult where C: Context<'j>, @@ -50,14 +55,18 @@ impl<'a, 'j, C: Context<'j>> Deserializer<'a, 'j, C> { } #[doc(hidden)] -impl<'x, 'd, 'a, 'j, C: Context<'j>> serde::de::Deserializer<'x> for &'d mut Deserializer<'a, 'j, C> { +impl<'x, 'd, 'a, 'j, C: Context<'j>> serde::de::Deserializer<'x> + for &'d mut Deserializer<'a, 'j, C> +{ type Error = LibError; fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'x>, { - if self.input.downcast::(self.cx).is_ok() || self.input.downcast::(self.cx).is_ok() { + if self.input.downcast::(self.cx).is_ok() + || self.input.downcast::(self.cx).is_ok() + { visitor.visit_unit() } else if let Ok(val) = self.input.downcast::(self.cx) { visitor.visit_bool(val.value(self.cx)) @@ -79,9 +88,9 @@ impl<'x, 'd, 'a, 'j, C: Context<'j>> serde::de::Deserializer<'x> for &'d mut Des let mut deserializer = JsObjectAccess::new(self.cx, val)?; visitor.visit_map(&mut deserializer) } else { - bail!(ErrorKind::NotImplemented( - "unimplemented Deserializer::Deserializer", - )); + Err(LibError::NotImplemented { + name: "unimplemented Deserializer::Deserializer", + }) } } @@ -89,7 +98,9 @@ impl<'x, 'd, 'a, 'j, C: Context<'j>> serde::de::Deserializer<'x> for &'d mut Des where V: Visitor<'x>, { - if self.input.downcast::(self.cx).is_ok() || self.input.downcast::(self.cx).is_ok() { + if self.input.downcast::(self.cx).is_ok() + || self.input.downcast::(self.cx).is_ok() + { visitor.visit_none() } else { visitor.visit_some(self) @@ -112,18 +123,19 @@ impl<'x, 'd, 'a, 'j, C: Context<'j>> serde::de::Deserializer<'x> for &'d mut Des let prop_names = val.get_own_property_names(self.cx)?; let len = prop_names.len(self.cx); if len != 1 { - Err(ErrorKind::InvalidKeyType(format!( - "object key with {} properties", - len - )))? + return Err(LibError::InvalidKeyType { + key: format!("object key with {} properties", len), + }); } - let key = prop_names.get(self.cx, 0)?.downcast::(self.cx).or_throw(self.cx)?; + let key = prop_names + .get::(self.cx, 0)? + .downcast_or_throw::(self.cx)?; let enum_value = val.get(self.cx, key)?; let key_value = key.value(self.cx); visitor.visit_enum(JsEnumAccess::new(self.cx, key_value, Some(enum_value))) } else { let m = self.input.to_string(self.cx)?.value(self.cx); - Err(ErrorKind::InvalidKeyType(m))? + Err(LibError::InvalidKeyType { key: m }) } } @@ -131,8 +143,8 @@ impl<'x, 'd, 'a, 'j, C: Context<'j>> serde::de::Deserializer<'x> for &'d mut Des where V: Visitor<'x>, { - let buff = self.input.downcast::(self.cx).or_throw(self.cx)?; - let copy = self.cx.borrow(&buff, |buff| Vec::from(buff.as_slice())); + let buff = self.input.downcast_or_throw::(self.cx)?; + let copy = Vec::from(buff.as_slice(self.cx)); visitor.visit_bytes(©) } @@ -140,8 +152,11 @@ impl<'x, 'd, 'a, 'j, C: Context<'j>> serde::de::Deserializer<'x> for &'d mut Des where V: Visitor<'x>, { - let buff = self.input.downcast::(self.cx).or_throw(self.cx)?; - let copy = self.cx.borrow(&buff, |buff| Vec::from(buff.as_slice())); + let buff = self + .input + .downcast::(self.cx) + .or_throw(self.cx)?; + let copy = Vec::from(buff.as_slice(self.cx)); visitor.visit_byte_buf(copy) } @@ -247,9 +262,12 @@ impl<'x, 'a, 'j, C: Context<'j>> MapAccess<'x> for JsObjectAccess<'a, 'j, C> { V: DeserializeSeed<'x>, { if self.idx >= self.len { - return Err(ErrorKind::ArrayIndexOutOfBounds(self.len, self.idx))?; + return Err(LibError::ArrayIndexOutOfBounds { + length: self.len, + index: self.idx, + }); } - let prop_name = self.prop_names.get(self.cx, self.idx)?; + let prop_name = self.prop_names.get::(self.cx, self.idx)?; let value = self.input.get(self.cx, prop_name)?; self.idx += 1; @@ -351,7 +369,7 @@ impl<'x, 'a, 'j, C: Context<'j>> VariantAccess<'x> for JsVariantAccess<'a, 'j, C &"tuple variant", )) } - }, + } None => Err(serde::de::Error::invalid_type( Unexpected::UnitVariant, &"tuple variant", @@ -378,7 +396,7 @@ impl<'x, 'a, 'j, C: Context<'j>> VariantAccess<'x> for JsVariantAccess<'a, 'j, C &"struct variant", )) } - }, + } _ => Err(serde::de::Error::invalid_type( Unexpected::UnitVariant, &"struct variant", diff --git a/src/errors.rs b/src/errors.rs index 00c2ce8..54ca3db 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -3,88 +3,124 @@ use neon; use serde::{de, ser}; -use std::convert::From; -use std::fmt::Display; - -error_chain! { - errors { - /// nodejs has a hard coded limit on string length - /// trying to serialize a string that is too long will result in an error - StringTooLong(len: usize) { - description("String too long for nodejs") - display("String too long for nodejs len: {}", len) - } - /// when deserializing to a boolean `false` `undefined` `null` `number` - /// are valid inputs - /// any other types will result in error - UnableToCoerce(to_type: &'static str) { - description("Unable to coerce") - display("Unable to coerce value to type: {}", to_type) - } - /// occurs when deserializing a char from an empty string - EmptyString { - description("EmptyString") - display("EmptyString") - } - /// occurs when deserializing a char from a sting with - /// more than one character - StringTooLongForChar(len: usize) { - description("String too long to be a char") - display("String too long to be a char expected len: 1 got len: {}", len) - } - /// occurs when a deserializer expects a `null` or `undefined` - /// property and found another type - ExpectingNull { - description("ExpectingNull") - display("ExpectingNull") - } - /// occurs when deserializing to an enum and the source object has - /// a none-1 number of properties - InvalidKeyType(key: String) { - description("InvalidKeyType") - display("key: '{}'", key) - } - /// an internal deserialization error from an invalid array - ArrayIndexOutOfBounds(index: u32, length: u32) { - description("ArrayIndexOutOfBounds") - display( - "ArrayIndexOutOfBounds: attempt to access ({}) size: ({})", - index, - length - ) - } #[doc(hidden)] - /// This type of object is not supported - NotImplemented(name: &'static str) { - description("Not Implemented") - display("Not Implemented: '{}'", name) - } - /// A JS exception was thrown - Js(throw: neon::result::Throw) { - description("JS exception") - display("JS exception") - } - // failed to convert something to f64 - CastError { - description("CastError") - display("CastError") +use std::{convert::From, error, fmt, fmt::Display, result}; + +pub type Result = result::Result; + +#[derive(Debug)] +pub enum Error { + /// nodejs has a hard coded limit on string length + /// trying to serialize a string that is too long will result in an error + StringTooLong { len: usize }, + + /// when deserializing to a boolean `false` `undefined` `null` `number` + /// are valid inputs + /// any other types will result in error + UnableToCoerce { to_type: &'static str }, + + /// occurs when deserializing a char from an empty string + EmptyString, + + /// occurs when deserializing a char from a sting with + /// more than one character + StringTooLongForChar { len: usize }, + + /// occurs when a deserializer expects a `null` or `undefined` + /// property and found another type + ExpectingNull, + + /// occurs when deserializing to an enum and the source object has + /// a none-1 number of properties + InvalidKeyType { key: String }, + + /// an internal deserialization error from an invalid array + ArrayIndexOutOfBounds { index: u32, length: u32 }, + + #[doc(hidden)] + /// This type of object is not supported + NotImplemented { name: &'static str }, + + /// A JS exception was thrown + Js { throw: neon::result::Throw }, + + /// failed to convert something to f64 + CastError, + + /// Generic serialize error + Serialize { msg: String }, + + /// Generic deserialize error + Deserialize { msg: String }, +} + +impl error::Error for Error {} + +impl Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Error::StringTooLong { len } => { + "String too long for nodejs len: ".fmt(f)?; + len.fmt(f) + } + Error::UnableToCoerce { to_type } => { + "Unable to coerce value to type: ".fmt(f)?; + to_type.fmt(f) + } + Error::EmptyString => "EmptyString".fmt(f), + Error::StringTooLongForChar { len } => { + "String too long to be a char expected len: 1 got len: ".fmt(f)?; + len.fmt(f) + } + Error::ExpectingNull => "ExpectingNull".fmt(f), + Error::InvalidKeyType { key } => { + "Invalid type of key: '".fmt(f)?; + key.fmt(f)?; + '\''.fmt(f) + } + Error::ArrayIndexOutOfBounds { index, length } => { + "Array index out of bounds (".fmt(f)?; + index.fmt(f)?; + " of ".fmt(f)?; + length.fmt(f)?; + ")".fmt(f) + } + Error::NotImplemented { name } => { + "Not implemented: '".fmt(f)?; + name.fmt(f)?; + '\''.fmt(f) + } + Error::Js { throw: _ } => "JS exception".fmt(f), + Error::CastError => "Casting error".fmt(f), + Error::Serialize { msg } => { + "Serialize error: ".fmt(f)?; + msg.fmt(f) + } + Error::Deserialize { msg } => { + "Deserialize error: ".fmt(f)?; + msg.fmt(f) + } } } } impl ser::Error for Error { fn custom(msg: T) -> Self { - ErrorKind::Msg(msg.to_string()).into() + Self::Serialize { + msg: msg.to_string(), + } } } impl de::Error for Error { fn custom(msg: T) -> Self { - ErrorKind::Msg(msg.to_string()).into() + Self::Deserialize { + msg: msg.to_string(), + } } } impl From for Error { fn from(throw: neon::result::Throw) -> Self { - ErrorKind::Js(throw).into() + Error::Js { throw } } } diff --git a/src/lib.rs b/src/lib.rs index f72e374..87db9ef 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -74,8 +74,6 @@ //! ``` //! -#[macro_use] -extern crate error_chain; extern crate neon; extern crate num; #[macro_use] diff --git a/src/ser.rs b/src/ser.rs index e366f4f..325e273 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -2,18 +2,16 @@ //! Serialize a Rust data structure into a `JsValue` //! -use errors::Error; -use errors::ErrorKind; -use errors::Result as LibResult; -use neon::prelude::*; -use serde::ser::{self, Serialize}; -use std::marker::PhantomData; +use errors::{Error as LibError, Result as LibResult}; +use neon::{prelude::*, types::buffer::TypedArray}; use num; +use serde::{ser, ser::Serialize}; +use std::marker::PhantomData; fn as_num(n: T) -> LibResult { match num::cast::(n) { Some(n2) => Ok(n2), - None => bail!(ErrorKind::CastError) + None => Err(LibError::CastError), } } @@ -99,7 +97,7 @@ where C: Context<'j>, { type Ok = Handle<'j, JsValue>; - type Error = Error; + type Error = LibError; type SerializeSeq = ArraySerializer<'a, 'j, C>; type SerializeTuple = ArraySerializer<'a, 'j, C>; @@ -139,7 +137,6 @@ where Ok(JsNumber::new(self.cx, as_num::<_, f64>(v)?).upcast()) } - #[inline] fn serialize_u8(self, v: u8) -> Result { Ok(JsNumber::new(self.cx, as_num::<_, f64>(v)?).upcast()) @@ -179,21 +176,21 @@ where let mut b = [0; 4]; let result = v.encode_utf8(&mut b); let js_str = JsString::try_new(self.cx, result) - .map_err(|_| ErrorKind::StringTooLongForChar(4))?; + .map_err(|_| LibError::StringTooLongForChar { len: 4 })?; Ok(js_str.upcast()) } #[inline] fn serialize_str(self, v: &str) -> Result { let len = v.len(); - let js_str = JsString::try_new(self.cx, v).map_err(|_| ErrorKind::StringTooLong(len))?; + let js_str = JsString::try_new(self.cx, v).map_err(|_| LibError::StringTooLong { len })?; Ok(js_str.upcast()) } #[inline] fn serialize_bytes(self, v: &[u8]) -> Result { - let mut buff = JsBuffer::new(self.cx, as_num::<_, u32>(v.len())?)?; - self.cx.borrow_mut(&mut buff, |buff| buff.as_mut_slice().clone_from_slice(v)); + let mut buff = JsBuffer::new(self.cx, v.len())?; + buff.as_mut_slice(self.cx).clone_from_slice(v); Ok(buff.upcast()) } @@ -334,7 +331,7 @@ where C: Context<'j>, { type Ok = Handle<'j, JsValue>; - type Error = Error; + type Error = LibError; fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> where @@ -359,7 +356,7 @@ where C: Context<'j>, { type Ok = Handle<'j, JsValue>; - type Error = Error; + type Error = LibError; #[inline] fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> @@ -381,7 +378,7 @@ where C: Context<'j>, { type Ok = Handle<'j, JsValue>; - type Error = Error; + type Error = LibError; #[inline] fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> @@ -422,7 +419,7 @@ where C: Context<'j>, { type Ok = Handle<'j, JsValue>; - type Error = Error; + type Error = LibError; #[inline] fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> @@ -461,7 +458,7 @@ where C: Context<'j>, { type Ok = Handle<'j, JsValue>; - type Error = Error; + type Error = LibError; fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> where @@ -506,7 +503,7 @@ where C: Context<'j>, { type Ok = Handle<'j, JsValue>; - type Error = Error; + type Error = LibError; #[inline] fn serialize_field( @@ -553,7 +550,7 @@ where C: Context<'j>, { type Ok = Handle<'j, JsValue>; - type Error = Error; + type Error = LibError; #[inline] fn serialize_field( From c9c21b53895cac010f28ebc6eb00daf81dc7604d Mon Sep 17 00:00:00 2001 From: K Date: Sat, 19 Mar 2022 13:40:20 +0500 Subject: [PATCH 3/6] Remove serde_derive dependency in favor of derive feature of serde --- Cargo.toml | 4 ++-- src/lib.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 912d36d..9e8f925 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,5 +22,5 @@ features = ["default-panic-hook", "napi-6", "try-catch-api", "event-queue-api"] version = "0.4.0" default-features = false -[dev-dependencies] -serde_derive = "1.0" +[dev-dependencies.serde] +features = ["derive"] diff --git a/src/lib.rs b/src/lib.rs index 87db9ef..1b4c1c0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,7 +33,7 @@ //! extern crate neon_serde; //! extern crate neon; //! #[macro_use] -//! extern crate serde_derive; +//! extern crate serde; //! //! use neon::prelude::*; //! From 8e2aa32fdffc1eae659940c85757f7ecb661c195 Mon Sep 17 00:00:00 2001 From: K Date: Sat, 19 Mar 2022 13:41:11 +0500 Subject: [PATCH 4/6] Fixed doc tests --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 1b4c1c0..259b798 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,7 +30,7 @@ //! //! ```rust,no_run //! # #![allow(dead_code)] -//! extern crate neon_serde; +//! extern crate neon_serde2 as neon_serde; //! extern crate neon; //! #[macro_use] //! extern crate serde; From 4f5a08fbe98ab43ee9dba27f4adde177d11bf763 Mon Sep 17 00:00:00 2001 From: K Date: Sat, 19 Mar 2022 14:04:45 +0500 Subject: [PATCH 5/6] Switched to rust edition 2021 --- Cargo.toml | 1 + src/de.rs | 12 +++++++----- src/lib.rs | 11 ++--------- src/ser.rs | 2 +- 4 files changed, 11 insertions(+), 15 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9e8f925..78cbaec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ description = "Easily serialize object for use with neon, fork of neon-serde" license = "MIT" repository = "https://github.com/matrix-org/neon-serde" readme = "readme.md" +edition = "2021" [dependencies] serde = "1.0" diff --git a/src/de.rs b/src/de.rs index 4ae2a3b..aec16c9 100644 --- a/src/de.rs +++ b/src/de.rs @@ -2,12 +2,14 @@ //! Deserialize a `JsValue` into a Rust data structure //! -use errors::{Error as LibError, Result as LibResult}; +use crate::errors::{Error as LibError, Result as LibResult}; use neon::{prelude::*, types::buffer::TypedArray}; -use serde; -use serde::de::{ - DeserializeOwned, DeserializeSeed, EnumAccess, MapAccess, SeqAccess, Unexpected, VariantAccess, - Visitor, +use serde::{ + de::{ + DeserializeOwned, DeserializeSeed, EnumAccess, MapAccess, SeqAccess, Unexpected, + VariantAccess, Visitor, + }, + forward_to_deserialize_any, }; /// Deserialize an instance of type `T` from a `Handle` diff --git a/src/lib.rs b/src/lib.rs index 259b798..71ca27c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,10 +30,8 @@ //! //! ```rust,no_run //! # #![allow(dead_code)] -//! extern crate neon_serde2 as neon_serde; -//! extern crate neon; -//! #[macro_use] -//! extern crate serde; +//! use serde::{Serialize, Deserialize}; +//! use neon_serde2 as neon_serde; //! //! use neon::prelude::*; //! @@ -74,11 +72,6 @@ //! ``` //! -extern crate neon; -extern crate num; -#[macro_use] -extern crate serde; - pub mod de; pub mod errors; pub mod ser; diff --git a/src/ser.rs b/src/ser.rs index 325e273..f6d8568 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -2,7 +2,7 @@ //! Serialize a Rust data structure into a `JsValue` //! -use errors::{Error as LibError, Result as LibResult}; +use crate::errors::{Error as LibError, Result as LibResult}; use neon::{prelude::*, types::buffer::TypedArray}; use num; use serde::{ser, ser::Serialize}; From 9f6cb80c28c3a56d2d3f2f0a2d5bef93084b8986 Mon Sep 17 00:00:00 2001 From: K Date: Sat, 19 Mar 2022 14:05:31 +0500 Subject: [PATCH 6/6] Fixed clippy suggstions --- src/de.rs | 2 ++ src/lib.rs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/de.rs b/src/de.rs index aec16c9..fa80e54 100644 --- a/src/de.rs +++ b/src/de.rs @@ -76,7 +76,9 @@ impl<'x, 'd, 'a, 'j, C: Context<'j>> serde::de::Deserializer<'x> visitor.visit_string(val.value(self.cx)) } else if let Ok(val) = self.input.downcast::(self.cx) { let v = val.value(self.cx); + #[allow(clippy::float_cmp)] if v.trunc() == v { + #[allow(clippy::cast_possible_truncation)] visitor.visit_i64(v as i64) } else { visitor.visit_f64(v) diff --git a/src/lib.rs b/src/lib.rs index 71ca27c..7de7f4d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,7 +2,7 @@ #![deny(unused_variables)] #![deny(unused_mut)] #![deny(clippy)] -#![deny(clippy_pedantic)] +#![deny(clippy::pedantic)] #![allow(stutter)] #![recursion_limit = "128"]