speedy/
writable.rs

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    // Since specialization is not stable yet we do it this way.
235    #[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}