1use std::{
6 cmp,
7 fs::File,
8 io::{Cursor, Error, ErrorKind},
9};
10
11pub trait Truncate {
16 fn truncate(&mut self, new_len: usize) -> Result<(), Error>;
30}
31
32impl Truncate for File {
33 fn truncate(&mut self, new_len: usize) -> Result<(), Error> {
35 self.set_len(new_len as u64)
36 }
37}
38
39impl Truncate for Vec<u8> {
40 fn truncate(&mut self, new_len: usize) -> Result<(), Error> {
43 if new_len <= self.len() {
44 self.truncate(new_len);
45 Ok(())
46 } else {
47 Err(Error::new(
48 ErrorKind::InvalidInput,
49 format!(
50 "tried to truncate to greater length ({} > {})",
51 new_len,
52 self.len()
53 ),
54 ))
55 }
56 }
57}
58
59impl<'a> Truncate for &'a [u8] {
60 fn truncate(&mut self, new_len: usize) -> Result<(), Error> {
63 if new_len <= self.len() {
64 *self = &self[..new_len];
65 Ok(())
66 } else {
67 Err(Error::new(
68 ErrorKind::InvalidInput,
69 format!(
70 "tried to truncate to greater length ({} > {})",
71 new_len,
72 self.len()
73 ),
74 ))
75 }
76 }
77}
78
79impl<T> Truncate for Cursor<T>
80where
81 T: Truncate,
82{
83 fn truncate(&mut self, new_len: usize) -> Result<(), Error> {
86 self.get_mut().truncate(new_len)?;
87 self.set_position(cmp::min(new_len as u64, self.position()));
88 Ok(())
89 }
90}
91
92impl<T> Truncate for &mut T
93where
94 T: Truncate,
95{
96 fn truncate(&mut self, new_len: usize) -> Result<(), Error> {
97 (**self).truncate(new_len)
98 }
99}
100
101#[cfg(test)]
102mod tests {
103 use super::*;
104 use std::io::{Seek, SeekFrom, Write};
105
106 #[test]
107 fn vec() {
108 let mut v: Vec<u8> = vec![0, 1, 2, 3];
109
110 Truncate::truncate(&mut v, 3).unwrap();
112 assert_eq!(v, &[0, 1, 2]);
113
114 let e = Truncate::truncate(&mut v, 4).unwrap_err();
116 assert_eq!(e.kind(), ErrorKind::InvalidInput);
117 }
118
119 #[test]
120 fn slice() {
121 let mut v: &[u8] = &[0, 1, 2, 3];
122
123 v.truncate(3).unwrap();
124 assert_eq!(v, &[0, 1, 2]);
125
126 let e = v.truncate(4).unwrap_err();
128 assert_eq!(e.kind(), ErrorKind::InvalidInput);
129 }
130
131 #[test]
132 fn cursor() {
133 let mut v: Cursor<&[u8]> = Cursor::new(&[0, 1, 2, 3]);
134
135 v.set_position(4); v.truncate(3).unwrap();
137 assert_eq!(v.get_ref(), &[0, 1, 2]);
138 assert_eq!(v.position(), 3);
139
140 let e = v.truncate(4).unwrap_err();
142 assert_eq!(e.kind(), ErrorKind::InvalidInput);
143 }
144
145 #[test]
146 fn file() {
147 let mut f = tempfile::tempfile().unwrap();
148 f.write_all(&[0, 1, 2, 3]).unwrap();
149 f.seek(SeekFrom::Start(0)).unwrap();
150
151 f.truncate(3).unwrap();
152 assert_eq!(f.seek(SeekFrom::End(0)).unwrap(), 3);
153
154 }
156}