diff --git a/libs/Cargo.lock b/libs/Cargo.lock index 02a7e5269..b3344141b 100644 --- a/libs/Cargo.lock +++ b/libs/Cargo.lock @@ -647,6 +647,7 @@ dependencies = [ "ripemd", "rusqlite", "rusqlite_migration", + "ryu", "sdk-common", "serde", "serde_json", @@ -3077,9 +3078,9 @@ checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "schannel" diff --git a/libs/sdk-core/Cargo.toml b/libs/sdk-core/Cargo.toml index 1a1fb5495..118261dd3 100644 --- a/libs/sdk-core/Cargo.toml +++ b/libs/sdk-core/Cargo.toml @@ -51,6 +51,7 @@ miniz_oxide = "0.7.1" tokio-stream = "0.1.14" serde_with = "3.3.0" regex = { workspace = true } +ryu = "1.0.18" [dev-dependencies] mockito = { workspace = true } diff --git a/libs/sdk-core/src/breez_services.rs b/libs/sdk-core/src/breez_services.rs index f46763ae9..e61aae281 100644 --- a/libs/sdk-core/src/breez_services.rs +++ b/libs/sdk-core/src/breez_services.rs @@ -1149,7 +1149,7 @@ impl BreezServices { Ok(dev_cmd) => match dev_cmd { DevCommand::GenerateDiagnosticData => self.generate_diagnostic_data().await, }, - Err(_) => Ok(serde_json::to_string_pretty( + Err(_) => Ok(crate::serializer::to_string_pretty( &self.node_api.execute_command(command).await?, )?), } @@ -1176,7 +1176,7 @@ impl BreezServices { "node": node_data, "sdk": sdk_data }); - Ok(serde_json::to_string_pretty(&result)?) + Ok(crate::serializer::to_string_pretty(&result)?) } /// This method sync the local state with the remote node state. @@ -2171,18 +2171,20 @@ impl BreezServices { } async fn generate_sdk_diagnostic_data(&self) -> SdkResult { - let state = serde_json::to_value(&self.persister.get_node_state()?)?; - let payments = serde_json::to_value( + let state = crate::serializer::value::to_value(&self.persister.get_node_state()?)?; + let payments = crate::serializer::value::to_value( &self .persister .list_payments(ListPaymentsRequest::default())?, )?; - let channels = serde_json::to_value(&self.persister.list_channels()?)?; - let settings = serde_json::to_value(&self.persister.list_settings()?)?; - let reverse_swaps = - serde_json::to_value(self.persister.list_reverse_swaps().map(sanitize_vec)?)?; - let swaps = serde_json::to_value(self.persister.list_swaps().map(sanitize_vec)?)?; - let lsp_id = serde_json::to_value(&self.persister.get_lsp_id()?)?; + let channels = crate::serializer::value::to_value(&self.persister.list_channels()?)?; + let settings = crate::serializer::value::to_value(&self.persister.list_settings()?)?; + let reverse_swaps = crate::serializer::value::to_value( + self.persister.list_reverse_swaps().map(sanitize_vec)?, + )?; + let swaps = + crate::serializer::value::to_value(self.persister.list_swaps().map(sanitize_vec)?)?; + let lsp_id = crate::serializer::value::to_value(&self.persister.get_lsp_id()?)?; let res = json!({ "node_state": state, diff --git a/libs/sdk-core/src/greenlight/node_api.rs b/libs/sdk-core/src/greenlight/node_api.rs index b23fc92c8..67ad629b9 100644 --- a/libs/sdk-core/src/greenlight/node_api.rs +++ b/libs/sdk-core/src/greenlight/node_api.rs @@ -1765,7 +1765,7 @@ impl NodeAPI for Greenlight { .await? .into_inner(); - Ok(serde_json::to_value(&resp)?) + Ok(crate::serializer::value::to_value(&resp)?) } NodeCommand::ListPeerChannels => { let resp = self @@ -1774,7 +1774,7 @@ impl NodeAPI for Greenlight { .list_peer_channels(cln::ListpeerchannelsRequest::default()) .await? .into_inner(); - Ok(serde_json::to_value(&resp)?) + Ok(crate::serializer::value::to_value(&resp)?) } NodeCommand::ListFunds => { let resp = self @@ -1783,7 +1783,7 @@ impl NodeAPI for Greenlight { .list_funds(cln::ListfundsRequest::default()) .await? .into_inner(); - Ok(serde_json::to_value(&resp)?) + Ok(crate::serializer::value::to_value(&resp)?) } NodeCommand::ListPayments => { let resp = self @@ -1792,7 +1792,7 @@ impl NodeAPI for Greenlight { .list_pays(cln::ListpaysRequest::default()) .await? .into_inner(); - Ok(serde_json::to_value(&resp)?) + Ok(crate::serializer::value::to_value(&resp)?) } NodeCommand::ListInvoices => { let resp = self @@ -1801,7 +1801,7 @@ impl NodeAPI for Greenlight { .list_invoices(cln::ListinvoicesRequest::default()) .await? .into_inner(); - Ok(serde_json::to_value(&resp)?) + Ok(crate::serializer::value::to_value(&resp)?) } NodeCommand::CloseAllChannels => { let peers_res = self @@ -1823,7 +1823,7 @@ impl NodeAPI for Greenlight { .getinfo(cln::GetinfoRequest::default()) .await? .into_inner(); - Ok(serde_json::to_value(&resp)?) + Ok(crate::serializer::value::to_value(&resp)?) } NodeCommand::Stop => { let resp = self @@ -1832,7 +1832,7 @@ impl NodeAPI for Greenlight { .stop(cln::StopRequest::default()) .await? .into_inner(); - Ok(serde_json::to_value(&resp)?) + Ok(crate::serializer::value::to_value(&resp)?) } } } diff --git a/libs/sdk-core/src/lib.rs b/libs/sdk-core/src/lib.rs index 4859002c0..ef4583bb0 100644 --- a/libs/sdk-core/src/lib.rs +++ b/libs/sdk-core/src/lib.rs @@ -178,6 +178,7 @@ mod lsps0; mod lsps2; mod models; mod persist; +mod serializer; mod support; mod swap_in; mod swap_out; diff --git a/libs/sdk-core/src/serializer.rs b/libs/sdk-core/src/serializer.rs new file mode 100644 index 000000000..59a6b74e5 --- /dev/null +++ b/libs/sdk-core/src/serializer.rs @@ -0,0 +1,896 @@ +use serde::{ser::SerializeStruct, Serialize}; + +pub fn to_string_pretty(value: &T) -> serde_json::Result +where + T: ?Sized + Serialize, +{ + let vec = to_vec_pretty(value)?; + let string = unsafe { + // We do not emit invalid UTF-8. + String::from_utf8_unchecked(vec) + }; + Ok(string) +} + +pub fn to_vec_pretty(value: &T) -> serde_json::Result> +where + T: ?Sized + Serialize, +{ + let mut writer = Vec::with_capacity(128); + to_writer_pretty(&mut writer, value)?; + Ok(writer) +} + +pub fn to_writer_pretty(writer: W, value: &T) -> serde_json::Result<()> +where + W: std::io::Write, + T: ?Sized + Serialize, +{ + let mut ser = serde_json::Serializer::pretty(writer); + let ser = HexSerializer::new(&mut ser); + value.serialize(ser) +} + +pub struct HexSerializer +where + S: serde::ser::Serializer, +{ + inner: S, +} + +impl HexSerializer +where + S: serde::ser::Serializer, +{ + pub fn new(inner: S) -> Self { + Self { inner } + } +} + +impl<'a, S: 'a> serde::ser::Serializer for HexSerializer +where + S: serde::ser::Serializer, +{ + type Ok = S::Ok; + type Error = S::Error; + + type SerializeSeq = S::SerializeSeq; + type SerializeTuple = S::SerializeTuple; + type SerializeTupleStruct = S::SerializeTupleStruct; + type SerializeTupleVariant = S::SerializeTupleVariant; + type SerializeMap = S::SerializeMap; + type SerializeStruct = HexSerializeStruct; + type SerializeStructVariant = S::SerializeStructVariant; + + fn serialize_bool(self, v: bool) -> Result { + self.inner.serialize_bool(v) + } + + fn serialize_i8(self, v: i8) -> Result { + self.inner.serialize_i8(v) + } + + fn serialize_i16(self, v: i16) -> Result { + self.inner.serialize_i16(v) + } + + fn serialize_i32(self, v: i32) -> Result { + self.inner.serialize_i32(v) + } + + fn serialize_i64(self, v: i64) -> Result { + self.inner.serialize_i64(v) + } + + fn serialize_u8(self, v: u8) -> Result { + self.inner.serialize_u8(v) + } + + fn serialize_u16(self, v: u16) -> Result { + self.inner.serialize_u16(v) + } + + fn serialize_u32(self, v: u32) -> Result { + self.inner.serialize_u32(v) + } + + fn serialize_u64(self, v: u64) -> Result { + self.inner.serialize_u64(v) + } + + fn serialize_f32(self, v: f32) -> Result { + self.inner.serialize_f32(v) + } + + fn serialize_f64(self, v: f64) -> Result { + self.inner.serialize_f64(v) + } + + fn serialize_char(self, v: char) -> Result { + self.inner.serialize_char(v) + } + + fn serialize_str(self, v: &str) -> Result { + self.inner.serialize_str(v) + } + + fn serialize_bytes(self, v: &[u8]) -> Result { + self.inner.serialize_bytes(v) + } + + fn serialize_none(self) -> Result { + self.inner.serialize_none() + } + + fn serialize_some(self, value: &T) -> Result + where + T: ?Sized + Serialize, + { + self.inner.serialize_some(value) + } + + fn serialize_unit(self) -> Result { + self.inner.serialize_unit() + } + + fn serialize_unit_struct(self, name: &'static str) -> Result { + self.inner.serialize_unit_struct(name) + } + + fn serialize_unit_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + ) -> Result { + self.inner + .serialize_unit_variant(name, variant_index, variant) + } + + fn serialize_newtype_struct( + self, + name: &'static str, + value: &T, + ) -> Result + where + T: ?Sized + Serialize, + { + self.inner.serialize_newtype_struct(name, value) + } + + fn serialize_newtype_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + value: &T, + ) -> Result + where + T: ?Sized + Serialize, + { + self.inner + .serialize_newtype_variant(name, variant_index, variant, value) + } + + fn serialize_seq(self, len: Option) -> Result { + self.inner.serialize_seq(len) + } + + fn serialize_tuple(self, len: usize) -> Result { + self.inner.serialize_tuple(len) + } + + fn serialize_tuple_struct( + self, + name: &'static str, + len: usize, + ) -> Result { + self.inner.serialize_tuple_struct(name, len) + } + + fn serialize_tuple_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + len: usize, + ) -> Result { + self.inner + .serialize_tuple_variant(name, variant_index, variant, len) + } + + fn serialize_map(self, len: Option) -> Result { + self.inner.serialize_map(len) + } + + fn serialize_struct( + self, + name: &'static str, + len: usize, + ) -> Result { + match self.inner.serialize_struct(name, len) { + Ok(s) => Ok(Self::SerializeStruct::new(s)), + Err(e) => Err(e), + } + } + + fn serialize_struct_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + len: usize, + ) -> Result { + self.inner + .serialize_struct_variant(name, variant_index, variant, len) + } +} + +pub struct HexSerializeStruct +where + S: SerializeStruct, +{ + inner: S, +} + +impl HexSerializeStruct +where + S: SerializeStruct, +{ + pub fn new(inner: S) -> Self { + Self { inner } + } +} + +impl SerializeStruct for HexSerializeStruct +where + S: SerializeStruct, +{ + type Ok = S::Ok; + type Error = S::Error; + + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> + where + T: ?Sized + Serialize, + { + // Finally, here's the hack. Serialize the value, and try to deserialize + // it as a Vec. If that works, hex encode the Vec, otherwise use + // the default serialization. + // Unfortunately there's no way to inspect the generic type parameter T + // here, otherwise this logic would work by simply checking whether the + // generic type parameter T is a Vec or not. + let as_vec = match serde_json::to_vec(value) { + Ok(as_vec) => as_vec, + Err(_) => return self.inner.serialize_field(key, value), + }; + let val: Vec = match serde_json::from_slice(&as_vec) { + Ok(val) => val, + Err(_) => return self.inner.serialize_field(key, value), + }; + self.inner.serialize_field(key, &hex::encode(&val)) + } + + fn end(self) -> Result { + self.inner.end() + } +} + +pub mod value { + use std::fmt::Display; + + use serde::{ser::Impossible, Serialize}; + use serde_json::{Error, Map, Result, Value}; + + pub fn to_value(value: T) -> Result + where + T: Serialize, + { + value.serialize(Serializer) + } + + pub struct Serializer; + + impl serde::Serializer for Serializer { + type Ok = Value; + type Error = Error; + + type SerializeSeq = SerializeVec; + type SerializeTuple = SerializeVec; + type SerializeTupleStruct = SerializeVec; + type SerializeTupleVariant = SerializeTupleVariant; + type SerializeMap = SerializeMap; + type SerializeStruct = SerializeMap; + type SerializeStructVariant = SerializeStructVariant; + + #[inline] + fn serialize_bool(self, value: bool) -> Result { + Ok(Value::Bool(value)) + } + + #[inline] + fn serialize_i8(self, value: i8) -> Result { + self.serialize_i64(value as i64) + } + + #[inline] + fn serialize_i16(self, value: i16) -> Result { + self.serialize_i64(value as i64) + } + + #[inline] + fn serialize_i32(self, value: i32) -> Result { + self.serialize_i64(value as i64) + } + + fn serialize_i64(self, value: i64) -> Result { + Ok(Value::Number(value.into())) + } + + fn serialize_i128(self, value: i128) -> Result { + if let Ok(value) = i64::try_from(value) { + Ok(Value::Number(value.into())) + } else { + Err(serde::ser::Error::custom("number out of range")) + } + } + + #[inline] + fn serialize_u8(self, value: u8) -> Result { + self.serialize_u64(value as u64) + } + + #[inline] + fn serialize_u16(self, value: u16) -> Result { + self.serialize_u64(value as u64) + } + + #[inline] + fn serialize_u32(self, value: u32) -> Result { + self.serialize_u64(value as u64) + } + + #[inline] + fn serialize_u64(self, value: u64) -> Result { + Ok(Value::Number(value.into())) + } + + fn serialize_u128(self, value: u128) -> Result { + if let Ok(value) = u64::try_from(value) { + Ok(Value::Number(value.into())) + } else { + Err(serde::ser::Error::custom("number out of range")) + } + } + + #[inline] + fn serialize_f32(self, float: f32) -> Result { + Ok(Value::from(float)) + } + + #[inline] + fn serialize_f64(self, float: f64) -> Result { + Ok(Value::from(float)) + } + + #[inline] + fn serialize_char(self, value: char) -> Result { + let mut s = String::new(); + s.push(value); + Ok(Value::String(s)) + } + + #[inline] + fn serialize_str(self, value: &str) -> Result { + Ok(Value::String(value.to_owned())) + } + + fn serialize_bytes(self, value: &[u8]) -> Result { + Ok(Value::String(hex::encode(value))) + } + + #[inline] + fn serialize_unit(self) -> Result { + Ok(Value::Null) + } + + #[inline] + fn serialize_unit_struct(self, _name: &'static str) -> Result { + self.serialize_unit() + } + + #[inline] + fn serialize_unit_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + ) -> Result { + self.serialize_str(variant) + } + + #[inline] + fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> Result + where + T: ?Sized + Serialize, + { + value.serialize(self) + } + + fn serialize_newtype_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + value: &T, + ) -> Result + where + T: ?Sized + Serialize, + { + let mut values = Map::new(); + values.insert(String::from(variant), to_value(value)?); + Ok(Value::Object(values)) + } + + #[inline] + fn serialize_none(self) -> Result { + self.serialize_unit() + } + + #[inline] + fn serialize_some(self, value: &T) -> Result + where + T: ?Sized + Serialize, + { + value.serialize(self) + } + + fn serialize_seq(self, len: Option) -> Result { + Ok(SerializeVec { + vec: Vec::with_capacity(len.unwrap_or(0)), + }) + } + + fn serialize_tuple(self, len: usize) -> Result { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + len: usize, + ) -> Result { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + len: usize, + ) -> Result { + Ok(SerializeTupleVariant { + name: String::from(variant), + vec: Vec::with_capacity(len), + }) + } + + fn serialize_map(self, _len: Option) -> Result { + Ok(SerializeMap { + map: Map::new(), + next_key: None, + }) + } + + fn serialize_struct( + self, + _name: &'static str, + len: usize, + ) -> Result { + self.serialize_map(Some(len)) + } + + fn serialize_struct_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + _len: usize, + ) -> Result { + Ok(SerializeStructVariant { + name: String::from(variant), + map: Map::new(), + }) + } + + fn collect_str(self, value: &T) -> Result + where + T: ?Sized + Display, + { + Ok(Value::String(value.to_string())) + } + } + + pub struct SerializeVec { + vec: Vec, + } + + pub struct SerializeTupleVariant { + name: String, + vec: Vec, + } + + pub struct SerializeMap { + map: Map, + next_key: Option, + } + + pub struct SerializeStructVariant { + name: String, + map: Map, + } + + impl serde::ser::SerializeSeq for SerializeVec { + type Ok = Value; + type Error = Error; + + fn serialize_element(&mut self, value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + self.vec.push(to_value(value)?); + Ok(()) + } + + fn end(self) -> Result { + Ok(Value::Array(self.vec)) + } + } + + impl serde::ser::SerializeTuple for SerializeVec { + type Ok = Value; + type Error = Error; + + fn serialize_element(&mut self, value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + serde::ser::SerializeSeq::serialize_element(self, value) + } + + fn end(self) -> Result { + serde::ser::SerializeSeq::end(self) + } + } + + impl serde::ser::SerializeTupleStruct for SerializeVec { + type Ok = Value; + type Error = Error; + + fn serialize_field(&mut self, value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + serde::ser::SerializeSeq::serialize_element(self, value) + } + + fn end(self) -> Result { + serde::ser::SerializeSeq::end(self) + } + } + + impl serde::ser::SerializeTupleVariant for SerializeTupleVariant { + type Ok = Value; + type Error = Error; + + fn serialize_field(&mut self, value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + self.vec.push(to_value(value)?); + Ok(()) + } + + fn end(self) -> Result { + let mut object = Map::new(); + + object.insert(self.name, Value::Array(self.vec)); + + Ok(Value::Object(object)) + } + } + + impl serde::ser::SerializeMap for SerializeMap { + type Ok = Value; + type Error = Error; + + fn serialize_key(&mut self, key: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + self.next_key = Some(key.serialize(MapKeySerializer)?); + Ok(()) + } + + fn serialize_value(&mut self, value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + let key = self.next_key.take(); + // Panic because this indicates a bug in the program rather than an + // expected failure. + let key = key.expect("serialize_value called before serialize_key"); + + // Finally, here's the hack. Serialize the value, and try to deserialize + // it as a Vec. If that works, hex encode the Vec, otherwise use + // the default serialization. + // Unfortunately there's no way to inspect the generic type parameter T + // here, otherwise this logic would work by simply checking whether the + // generic type parameter T is a Vec or not. + let as_vec = match serde_json::to_vec(value) { + Ok(as_vec) => as_vec, + Err(_) => { + self.map.insert(key, to_value(value)?); + return Ok(()); + } + }; + let val: Vec = match serde_json::from_slice(&as_vec) { + Ok(val) => val, + Err(_) => { + self.map.insert(key, to_value(value)?); + return Ok(()); + } + }; + + self.map.insert(key, to_value(hex::encode(&val))?); + Ok(()) + } + + fn end(self) -> Result { + Ok(Value::Object(self.map)) + } + } + + impl serde::ser::SerializeStruct for SerializeMap { + type Ok = Value; + type Error = Error; + + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + serde::ser::SerializeMap::serialize_entry(self, key, value) + } + + fn end(self) -> Result { + serde::ser::SerializeMap::end(self) + } + } + + impl serde::ser::SerializeStructVariant for SerializeStructVariant { + type Ok = Value; + type Error = Error; + + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + self.map.insert(String::from(key), to_value(value)?); + Ok(()) + } + + fn end(self) -> Result { + let mut object = Map::new(); + + object.insert(self.name, Value::Object(self.map)); + + Ok(Value::Object(object)) + } + } + + struct MapKeySerializer; + + fn key_must_be_a_string() -> Error { + serde::ser::Error::custom("key must be a string") + } + + fn float_key_must_be_finite() -> Error { + serde::ser::Error::custom("float key must be finite") + } + + impl serde::Serializer for MapKeySerializer { + type Ok = String; + type Error = Error; + + type SerializeSeq = Impossible; + type SerializeTuple = Impossible; + type SerializeTupleStruct = Impossible; + type SerializeTupleVariant = Impossible; + type SerializeMap = Impossible; + type SerializeStruct = Impossible; + type SerializeStructVariant = Impossible; + + #[inline] + fn serialize_unit_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + ) -> Result { + Ok(variant.to_owned()) + } + + #[inline] + fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> Result + where + T: ?Sized + Serialize, + { + value.serialize(self) + } + + fn serialize_bool(self, value: bool) -> Result { + Ok(value.to_string()) + } + + fn serialize_i8(self, value: i8) -> Result { + Ok(value.to_string()) + } + + fn serialize_i16(self, value: i16) -> Result { + Ok(value.to_string()) + } + + fn serialize_i32(self, value: i32) -> Result { + Ok(value.to_string()) + } + + fn serialize_i64(self, value: i64) -> Result { + Ok(value.to_string()) + } + + fn serialize_i128(self, value: i128) -> Result { + Ok(value.to_string()) + } + + fn serialize_u8(self, value: u8) -> Result { + Ok(value.to_string()) + } + + fn serialize_u16(self, value: u16) -> Result { + Ok(value.to_string()) + } + + fn serialize_u32(self, value: u32) -> Result { + Ok(value.to_string()) + } + + fn serialize_u64(self, value: u64) -> Result { + Ok(value.to_string()) + } + + fn serialize_u128(self, value: u128) -> Result { + Ok(value.to_string()) + } + + fn serialize_f32(self, value: f32) -> Result { + if value.is_finite() { + Ok(ryu::Buffer::new().format_finite(value).to_owned()) + } else { + Err(float_key_must_be_finite()) + } + } + + fn serialize_f64(self, value: f64) -> Result { + if value.is_finite() { + Ok(ryu::Buffer::new().format_finite(value).to_owned()) + } else { + Err(float_key_must_be_finite()) + } + } + + #[inline] + fn serialize_char(self, value: char) -> Result { + Ok({ + let mut s = String::new(); + s.push(value); + s + }) + } + + #[inline] + fn serialize_str(self, value: &str) -> Result { + Ok(value.to_owned()) + } + + fn serialize_bytes(self, _value: &[u8]) -> Result { + Err(key_must_be_a_string()) + } + + fn serialize_unit(self) -> Result { + Err(key_must_be_a_string()) + } + + fn serialize_unit_struct(self, _name: &'static str) -> Result { + Err(key_must_be_a_string()) + } + + fn serialize_newtype_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _value: &T, + ) -> Result + where + T: ?Sized + Serialize, + { + Err(key_must_be_a_string()) + } + + fn serialize_none(self) -> Result { + Err(key_must_be_a_string()) + } + + fn serialize_some(self, _value: &T) -> Result + where + T: ?Sized + Serialize, + { + Err(key_must_be_a_string()) + } + + fn serialize_seq(self, _len: Option) -> Result { + Err(key_must_be_a_string()) + } + + fn serialize_tuple(self, _len: usize) -> Result { + Err(key_must_be_a_string()) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result { + Err(key_must_be_a_string()) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result { + Err(key_must_be_a_string()) + } + + fn serialize_map(self, _len: Option) -> Result { + Err(key_must_be_a_string()) + } + + fn serialize_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result { + Err(key_must_be_a_string()) + } + + fn serialize_struct_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result { + Err(key_must_be_a_string()) + } + + fn collect_str(self, value: &T) -> Result + where + T: ?Sized + Display, + { + Ok(value.to_string()) + } + } +} diff --git a/tools/sdk-cli/Cargo.lock b/tools/sdk-cli/Cargo.lock index b9cd3423a..0cba2204d 100644 --- a/tools/sdk-cli/Cargo.lock +++ b/tools/sdk-cli/Cargo.lock @@ -556,6 +556,7 @@ dependencies = [ "ripemd", "rusqlite", "rusqlite_migration", + "ryu", "sdk-common", "serde", "serde_json", @@ -2944,9 +2945,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "schannel"