diff --git a/test_suite/tests/test_borrow.rs b/test_suite/tests/test_borrow.rs new file mode 100644 index 00000000..dd75f70b --- /dev/null +++ b/test_suite/tests/test_borrow.rs @@ -0,0 +1,199 @@ +#[macro_use] +extern crate serde_derive; + +extern crate serde; +use serde::{Deserialize, Deserializer}; + +extern crate serde_test; +use serde_test::{ + Error, + Token, + assert_de_tokens, + assert_de_tokens_error, +}; + +use std::borrow::Cow; + +#[test] +fn test_borrowed_str() { + assert_de_tokens( + &"borrowed", + &[ + Token::BorrowedStr("borrowed"), + ] + ); +} + +#[test] +fn test_borrowed_str_from_string() { + assert_de_tokens_error::<&str>( + &[ + Token::String("borrowed".to_owned()), + ], + Error::Message("invalid type: string \"borrowed\", expected a borrowed string".to_owned()), + ); +} + +#[test] +fn test_borrowed_str_from_str() { + assert_de_tokens_error::<&str>( + &[ + Token::Str("borrowed"), + ], + Error::Message("invalid type: string \"borrowed\", expected a borrowed string".to_owned()), + ); +} + +#[test] +fn test_string_from_borrowed_str() { + assert_de_tokens( + &"owned".to_owned(), + &[ + Token::BorrowedStr("owned"), + ] + ); +} + +#[test] +fn test_borrowed_bytes() { + assert_de_tokens( + &&b"borrowed"[..], + &[ + Token::BorrowedBytes(b"borrowed"), + ] + ); +} + +#[test] +fn test_borrowed_bytes_from_bytebuf() { + assert_de_tokens_error::<&[u8]>( + &[ + Token::ByteBuf(b"borrowed".to_vec()), + ], + Error::Message("invalid type: byte array, expected a borrowed byte array".to_owned()), + ); +} + +#[test] +fn test_borrowed_bytes_from_bytes() { + assert_de_tokens_error::<&[u8]>( + &[ + Token::Bytes(b"borrowed"), + ], + Error::Message("invalid type: byte array, expected a borrowed byte array".to_owned()), + ); +} + +#[test] +fn test_tuple() { + assert_de_tokens( + &("str", &b"bytes"[..]), + &[ + Token::TupleStart(2), + + Token::TupleSep, + Token::BorrowedStr("str"), + + Token::TupleSep, + Token::BorrowedBytes(b"bytes"), + + Token::TupleEnd, + ] + ); +} + +#[test] +fn test_struct() { + #[derive(Deserialize, Debug, PartialEq)] + struct Borrowing<'a, 'b> { + bs: &'a str, + bb: &'b [u8], + } + + assert_de_tokens( + &Borrowing { bs: "str", bb: b"bytes" }, + &[ + Token::StructStart("Borrowing", 2), + + Token::StructSep, + Token::BorrowedStr("bs"), + Token::BorrowedStr("str"), + + Token::StructSep, + Token::BorrowedStr("bb"), + Token::BorrowedBytes(b"bytes"), + + Token::StructEnd, + ] + ); +} + +#[test] +fn test_cow() { + #[derive(Deserialize)] + struct Cows<'a, 'b> { + copied: Cow<'a, str>, + + #[serde(borrow)] + borrowed: Cow<'b, str>, + } + + let tokens = vec![ + Token::StructStart("Cows", 2), + + Token::StructSep, + Token::Str("copied"), + Token::BorrowedStr("copied"), + + Token::StructSep, + Token::Str("borrowed"), + Token::BorrowedStr("borrowed"), + + Token::StructEnd, + ]; + + let mut de = serde_test::Deserializer::new(tokens.into_iter()); + let cows = Cows::deserialize(&mut de).unwrap(); + assert_eq!(de.next_token(), None); + + match cows.copied { + Cow::Owned(ref s) if s == "copied" => {} + _ => panic!("expected a copied string"), + } + + match cows.borrowed { + Cow::Borrowed("borrowed") => {} + _ => panic!("expected a borrowed string"), + } +} + +#[test] +fn test_lifetimes() { + #[derive(Deserialize)] + struct Cows<'a, 'b> { + _copied: Cow<'a, str>, + + #[serde(borrow)] + _borrowed: Cow<'b, str>, + } + + // Tests that `'de: 'a` is not required by the Deserialize impl. + fn _cows_lifetimes<'de: 'b, 'a, 'b, D>(deserializer: D) -> Cows<'a, 'b> + where D: Deserializer<'de> + { + Deserialize::deserialize(deserializer).unwrap() + } + + #[derive(Deserialize)] + struct Wrap<'a, 'b> { + #[serde(borrow = "'b")] + _cows: Cows<'a, 'b>, + } + + // Tests that `'de: 'a` is not required by the Deserialize impl. + fn _wrap_lifetimes<'de: 'b, 'a, 'b, D>(deserializer: D) -> Wrap<'a, 'b> + where D: Deserializer<'de> + { + Deserialize::deserialize(deserializer).unwrap() + } +}