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