deser_incomplete/random_trailer/
mod.rs1#![allow(clippy::len_without_is_empty)]
2
3#[cfg(feature = "serde_json")]
4pub(crate) mod json;
5#[cfg(feature = "serde_yaml")]
6pub(crate) mod yaml;
7
8pub trait RandomTrailer {
19 fn prepare_string_with_tag(&self, input: &mut String, tag: &str);
21
22 fn prepare_vec_with_tag(&self, input: &mut Vec<u8>, tag: &str);
24
25 #[must_use]
38 fn remove_trailer(&self, string_like: &mut impl StringLike, random_tag: &str) -> bool;
39}
40
41#[derive(Clone, Debug, Default)]
42pub struct NoopRandomTrailer;
43
44impl RandomTrailer for NoopRandomTrailer {
45 fn prepare_string_with_tag(&self, _input: &mut String, _tag: &str) {}
46
47 fn prepare_vec_with_tag(&self, _input: &mut Vec<u8>, _tag: &str) {}
48
49 fn remove_trailer(&self, _string_like: &mut impl StringLike, _random_tag: &str) -> bool {
50 false
51 }
52}
53
54pub struct InputPlusTrailer<SliceType>(pub SliceType);
56
57pub trait StringLike: std::fmt::Debug {
60 fn len(&self) -> usize;
62 fn ends_with_string(&self, string: &str) -> bool;
63 fn ends_with_2_strings(&self, s1: &str, s2: &str) -> bool;
65 fn truncate_to_bytes(&mut self, target_len: usize);
66}
67
68impl StringLike for &str {
69 fn len(&self) -> usize {
70 (*self).len()
71 }
72
73 fn ends_with_string(&self, string: &str) -> bool {
74 self.ends_with(string)
75 }
76
77 fn ends_with_2_strings(&self, s1: &str, s2: &str) -> bool {
78 self.ends_with(s2) && self[0..self.len() - s2.len()].ends_with(s1)
79 }
80
81 fn truncate_to_bytes(&mut self, target_len: usize) {
82 *self = &self[..target_len];
83 }
84}
85
86impl StringLike for &[u8] {
87 fn len(&self) -> usize {
88 (*self).len()
89 }
90
91 fn ends_with_string(&self, string: &str) -> bool {
92 self.ends_with(string.as_bytes())
93 }
94
95 fn ends_with_2_strings(&self, s1: &str, s2: &str) -> bool {
96 self.ends_with(s2.as_bytes()) && self[0..self.len() - s2.len()].ends_with(s1.as_bytes())
97 }
98
99 fn truncate_to_bytes(&mut self, target_len: usize) {
100 *self = &self[..target_len];
101 }
102}
103
104impl StringLike for String {
105 fn len(&self) -> usize {
106 self.len()
107 }
108
109 fn ends_with_string(&self, string: &str) -> bool {
110 self.ends_with(string)
111 }
112
113 fn ends_with_2_strings(&self, s1: &str, s2: &str) -> bool {
114 self.ends_with(s2) && self[0..self.len() - s2.len()].ends_with(s1)
115 }
116
117 fn truncate_to_bytes(&mut self, target_len: usize) {
118 self.truncate(target_len);
119 }
120}
121
122impl StringLike for Vec<u8> {
123 fn len(&self) -> usize {
124 self.len()
125 }
126
127 fn ends_with_string(&self, string: &str) -> bool {
128 self.ends_with(string.as_bytes())
129 }
130
131 fn ends_with_2_strings(&self, s1: &str, s2: &str) -> bool {
132 self.ends_with(s2.as_bytes()) && self[0..self.len() - s2.len()].ends_with(s1.as_bytes())
133 }
134
135 fn truncate_to_bytes(&mut self, target_len: usize) {
136 self.truncate(target_len);
137 }
138}
139
140#[cfg(test)]
141impl StringLike for std::borrow::Cow<'_, str> {
142 fn len(&self) -> usize {
143 (**self).len()
144 }
145
146 fn ends_with_string(&self, string: &str) -> bool {
147 self.ends_with(string)
148 }
149
150 fn ends_with_2_strings(&self, s1: &str, s2: &str) -> bool {
151 self.ends_with(s2) && self[0..self.len() - s2.len()].ends_with(s1)
152 }
153
154 fn truncate_to_bytes(&mut self, target_len: usize) {
155 match self {
156 std::borrow::Cow::Borrowed(slice) => {
157 slice.truncate_to_bytes(target_len);
158 }
159 std::borrow::Cow::Owned(string) => {
160 string.truncate_to_bytes(target_len);
161 }
162 }
163 }
164}