1use std::io::{
2 self,
3 Write
4};
5
6use std::fs::File;
7use std::path::Path;
8
9use crate::writer::Writer;
10use crate::context::{Context, DefaultContext};
11use crate::endianness::Endianness;
12use crate::Error;
13
14use crate::error::{
15 error_end_of_output_buffer,
16 error_output_buffer_is_too_small
17};
18
19struct BufferCollector< 'a, C: Context > {
20 context: &'a mut C,
21 buffer: &'a mut [u8],
22 position: usize
23}
24
25impl< 'a, C: Context > Writer< C > for BufferCollector< 'a, C > {
26 #[inline]
27 fn write_bytes( &mut self, slice: &[u8] ) -> Result< (), C::Error > {
28 let buffer = self.buffer.get_mut( self.position..self.position + slice.len() ).ok_or_else( error_end_of_output_buffer )?;
29 buffer.copy_from_slice( slice );
30 self.position += slice.len();
31 Ok(())
32 }
33
34 #[inline]
35 fn context( &self ) -> &C {
36 &self.context
37 }
38
39 #[inline]
40 fn context_mut( &mut self ) -> &mut C {
41 &mut self.context
42 }
43
44 #[inline(always)]
45 fn can_write_at_least( &self, size: usize ) -> Option< bool > {
46 Some( self.buffer.get( self.position..self.position + size ).is_some() )
47 }
48}
49
50struct WritingCollector< C: Context, T: Write > {
51 context: C,
52 writer: T
53}
54
55impl< C: Context, T: Write > Writer< C > for WritingCollector< C, T > {
56 #[inline]
57 fn write_bytes( &mut self, slice: &[u8] ) -> Result< (), C::Error > {
58 self.writer.write_all( slice ).map_err( |error| {
59 let error = Error::from_io_error( error );
60 <C::Error as From< Error >>::from( error )
61 })
62 }
63
64 #[inline]
65 fn context( &self ) -> &C {
66 &self.context
67 }
68
69 #[inline]
70 fn context_mut( &mut self ) -> &mut C {
71 &mut self.context
72 }
73}
74
75struct SizeCalculatorCollector {
76 size: usize
77}
78
79impl< C: Context > Writer< C > for SizeCalculatorCollector {
80 #[inline]
81 fn write_bytes( &mut self, slice: &[u8] ) -> Result< (), C::Error > {
82 self.size += slice.len();
83 Ok(())
84 }
85
86 #[inline]
87 fn write_u8( &mut self, _: u8 ) -> Result< (), C::Error > {
88 self.size += 1;
89 Ok(())
90 }
91
92 #[inline]
93 fn write_u16( &mut self, _: u16 ) -> Result< (), C::Error > {
94 self.size += 2;
95 Ok(())
96 }
97
98 #[inline]
99 fn write_u32( &mut self, _: u32 ) -> Result< (), C::Error > {
100 self.size += 4;
101 Ok(())
102 }
103
104 #[inline]
105 fn write_u64( &mut self, _: u64 ) -> Result< (), C::Error > {
106 self.size += 8;
107 Ok(())
108 }
109
110 #[inline]
111 fn write_u128( &mut self, _: u128 ) -> Result< (), C::Error > {
112 self.size += 16;
113 Ok(())
114 }
115
116 #[inline]
117 fn endianness( &self ) -> Endianness {
118 Endianness::NATIVE
119 }
120
121 #[inline]
122 fn context( &self ) -> &C {
123 panic!();
124 }
125
126 #[inline]
127 fn context_mut( &mut self ) -> &mut C {
128 panic!();
129 }
130}
131
132pub trait Writable< C: Context > {
133 fn write_to< T: ?Sized + Writer< C > >( &self, writer: &mut T ) -> Result< (), C::Error >;
134
135 #[inline]
136 fn write_to_buffer( &self, buffer: &mut [u8] ) -> Result< (), C::Error > where Self: DefaultContext< Context = C >, C: Default {
137 self.write_to_buffer_with_ctx( Default::default(), buffer )
138 }
139
140 fn write_to_vec( &self ) -> Result< Vec< u8 >, C::Error > where Self: DefaultContext< Context = C >, C: Default {
141 self.write_to_vec_with_ctx( Default::default() )
142 }
143
144 #[inline]
145 fn write_to_stream< S: Write >( &self, stream: S ) -> Result< (), C::Error > where Self: DefaultContext< Context = C >, C: Default {
146 self.write_to_stream_with_ctx( Default::default(), stream )
147 }
148
149 #[inline]
150 fn write_to_file( &self, path: impl AsRef< Path > ) -> Result< (), C::Error > where Self: DefaultContext< Context = C >, C: Default {
151 self.write_to_file_with_ctx( Default::default(), path )
152 }
153
154 #[inline]
155 fn write_to_buffer_with_ctx( &self, mut context: C, buffer: &mut [u8] ) -> Result< (), C::Error > {
156 self.write_to_buffer_with_ctx_mut( &mut context, buffer )
157 }
158
159 #[inline]
160 fn write_to_buffer_with_ctx_mut( &self, context: &mut C, buffer: &mut [u8] ) -> Result< (), C::Error > {
161 let bytes_needed = self.bytes_needed()?;
162 let buffer_length = buffer.len();
163 let buffer = buffer.get_mut( 0..bytes_needed ).ok_or_else( || error_output_buffer_is_too_small( buffer_length, bytes_needed ) )?;
164 let mut writer = BufferCollector {
165 context,
166 buffer,
167 position: 0
168 };
169
170 self.write_to( &mut writer )?;
171 Ok(())
172 }
173
174 #[inline]
175 fn write_to_vec_with_ctx( &self, mut context: C ) -> Result< Vec< u8 >, C::Error > {
176 self.write_to_vec_with_ctx_mut( &mut context )
177 }
178
179 #[inline]
180 fn write_to_vec_with_ctx_mut( &self, context: &mut C ) -> Result< Vec< u8 >, C::Error > {
181 let capacity = self.bytes_needed()?;
182 let mut vec = Vec::with_capacity( capacity );
183 unsafe {
184 vec.set_len( capacity );
185 }
186
187 let mut writer = BufferCollector {
188 context,
189 buffer: vec.as_mut_slice(),
190 position: 0
191 };
192
193 self.write_to( &mut writer )?;
194
195 let position = writer.position;
196 unsafe {
197 vec.set_len( position );
198 }
199
200 debug_assert_eq!( position, capacity );
201 Ok( vec )
202 }
203
204 #[inline]
205 fn write_to_stream_with_ctx< S: Write >( &self, context: C, stream: S ) -> Result< (), C::Error > {
206 let mut writer = WritingCollector {
207 context,
208 writer: stream
209 };
210
211 self.write_to( &mut writer )
212 }
213
214 #[inline]
215 fn write_to_file_with_ctx( &self, context: C, path: impl AsRef< Path > ) -> Result< (), C::Error > {
216 let stream = File::create( path ).map_err( |error| {
217 let error = Error::from_io_error( error );
218 <C::Error as From< Error >>::from( error )
219 })?;
220 let stream = io::BufWriter::new( stream );
221 self.write_to_stream_with_ctx( context, stream )
222 }
223
224 #[inline]
225 fn bytes_needed( &self ) -> Result< usize, C::Error > {
226 let mut writer = SizeCalculatorCollector {
227 size: 0
228 };
229
230 self.write_to( &mut writer )?;
231 Ok( writer.size )
232 }
233
234 #[doc(hidden)]
236 #[inline]
237 fn speedy_is_primitive() -> bool {
238 false
239 }
240
241 #[doc(hidden)]
242 #[inline]
243 unsafe fn speedy_slice_as_bytes( _: &[Self] ) -> &[u8] where Self: Sized {
244 panic!();
245 }
246}