1#![cfg_attr(docsrs, feature(doc_cfg))]
3
4use serde::{Deserialize, Deserializer};
5
6pub fn default_on_eof<'de, T, D>(d: D) -> Result<T, D::Error>
11where
12 D: Deserializer<'de>,
13 T: Deserialize<'de> + Default,
14{
15 let result = T::deserialize(d);
16 ignore_eof_error::<'de, T, D::Error>(result)
17}
18
19pub fn ignore_eof_error<'de, T, D>(result: Result<T, D>) -> Result<T, D>
20where
21 T: Deserialize<'de> + Default,
22 D: std::fmt::Display,
23{
24 match result {
25 Err(err) if err.to_string() == "io error: unexpected end of file" => Ok(T::default()),
26 Err(err) if err.to_string() == "io error: failed to fill whole buffer" => Ok(T::default()),
27 result => result,
28 }
29}
30
31#[cfg(test)]
32pub mod tests {
33 use {super::*, bincode::deserialize};
34
35 #[test]
36 fn test_default_on_eof() {
37 #[derive(serde_derive::Serialize, serde_derive::Deserialize, Debug, PartialEq, Eq)]
38 struct Foo {
39 bar: u16,
40 #[serde(deserialize_with = "default_on_eof")]
41 baz: Option<u16>,
42 #[serde(deserialize_with = "default_on_eof")]
43 quz: String,
44 }
45
46 let data = vec![1, 0];
47 assert_eq!(
48 Foo {
49 bar: 1,
50 baz: None,
51 quz: "".to_string(),
52 },
53 deserialize(&data).unwrap()
54 );
55
56 let data = vec![1, 0, 0];
57 assert_eq!(
58 Foo {
59 bar: 1,
60 baz: None,
61 quz: "".to_string(),
62 },
63 deserialize(&data).unwrap()
64 );
65
66 let data = vec![1, 0, 1];
67 assert_eq!(
68 Foo {
69 bar: 1,
70 baz: None,
71 quz: "".to_string(),
72 },
73 deserialize(&data).unwrap()
74 );
75
76 let data = vec![1, 0, 1, 0];
77 assert_eq!(
78 Foo {
79 bar: 1,
80 baz: None,
81 quz: "".to_string(),
82 },
83 deserialize(&data).unwrap()
84 );
85
86 let data = vec![1, 0, 1, 0, 0, 1];
87 assert_eq!(
88 Foo {
89 bar: 1,
90 baz: Some(0),
91 quz: "".to_string(),
92 },
93 deserialize(&data).unwrap()
94 );
95
96 let data = vec![1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 116];
97 assert_eq!(
98 Foo {
99 bar: 1,
100 baz: Some(0),
101 quz: "t".to_string(),
102 },
103 deserialize(&data).unwrap()
104 );
105 }
106
107 #[test]
108 #[should_panic]
109 fn test_default_on_eof_additional_untagged_fields() {
110 #[derive(serde_derive::Serialize, serde_derive::Deserialize, Debug, PartialEq, Eq)]
113 struct Foo {
114 bar: u16,
115 #[serde(deserialize_with = "default_on_eof")]
116 baz: Option<u16>,
117 quz: String,
118 }
119
120 let data = vec![1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 116];
122 assert_eq!(
123 Foo {
124 bar: 1,
125 baz: Some(0),
126 quz: "t".to_string(),
127 },
128 deserialize(&data).unwrap()
129 );
130
131 let data = vec![1, 0, 1, 0];
133 assert_eq!(
134 Foo {
135 bar: 1,
136 baz: None,
137 quz: "".to_string(),
138 },
139 deserialize(&data).unwrap()
140 );
141 }
142}