Skip to content

Commit b407b77

Browse files
Allow SecretKey to be deserialized from an owned string
Deserializing directly into a borrowed string only covers the edge case in which one passes a borrowed string to the deserializer. If we are given an owned version, the deserialization fails with: invalid type: string "foobar", expected a borrowed string'
1 parent 5f1622f commit b407b77

File tree

1 file changed

+64
-2
lines changed

1 file changed

+64
-2
lines changed

src/macros.rs

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,23 @@ macro_rules! serde_impl(
6565
use ::serde::de::Error;
6666
use core::str::FromStr;
6767

68+
struct Visitor;
69+
70+
impl<'de> ::serde::de::Visitor<'de> for Visitor {
71+
type Value = $t;
72+
73+
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
74+
write!(formatter, "a string")
75+
}
76+
77+
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> where
78+
E: Error, {
79+
$t::from_str(v).map_err(E::custom)
80+
}
81+
}
82+
6883
if d.is_human_readable() {
69-
let sl: &str = ::serde::Deserialize::deserialize(d)?;
70-
$t::from_str(sl).map_err(D::Error::custom)
84+
d.deserialize_str(Visitor)
7185
} else {
7286
let sl: &[u8] = ::serde::Deserialize::deserialize(d)?;
7387
if sl.len() != $len {
@@ -161,3 +175,51 @@ macro_rules! serde_impl_from_slice {
161175
macro_rules! serde_impl_from_slice(
162176
($t:ident) => ()
163177
);
178+
179+
#[cfg(all(test, feature = "serde"))]
180+
mod tests {
181+
use std::{str::FromStr, fmt, convert::{TryInto, Infallible}};
182+
use serde_test::*;
183+
184+
#[derive(Debug)]
185+
struct Foo([u8; 6]);
186+
serde_impl!(Foo, 6);
187+
impl_array_newtype!(Foo, u8, 6);
188+
189+
impl FromStr for Foo {
190+
type Err = Infallible;
191+
192+
fn from_str(s: &str) -> Result<Self, Self::Err> {
193+
let x = s.bytes().take(6).collect::<Vec<_>>();
194+
195+
Ok(Foo(x.try_into().unwrap()))
196+
}
197+
}
198+
199+
impl fmt::Display for Foo {
200+
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
201+
unimplemented!()
202+
}
203+
}
204+
205+
206+
#[test]
207+
fn deserialize_from_borrowed_string() {
208+
let value = Foo(*b"foobar");
209+
let tokens = [
210+
Token::BorrowedStr("foobar")
211+
];
212+
213+
assert_de_tokens(&value.readable(), &tokens)
214+
}
215+
216+
#[test]
217+
fn deserialize_from_owned_string() {
218+
let value = Foo(*b"foobar");
219+
let tokens = [
220+
Token::String("foobar")
221+
];
222+
223+
assert_de_tokens(&value.readable(), &tokens)
224+
}
225+
}

0 commit comments

Comments
 (0)