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