corro_speedy/
lib.rs

1#![cfg_attr(feature = "external_doc", doc = include_str!("../README.md"))]
2#![forbid(unsafe_op_in_unsafe_fn)]
3
4mod error;
5#[macro_use]
6mod utils;
7mod readable;
8mod readable_impl;
9mod readable_unsized_impl;
10mod reader;
11mod writable;
12mod writable_impl;
13mod writer;
14mod context;
15mod endianness;
16mod varint;
17mod circular_buffer;
18
19#[cfg(feature = "chrono")]
20mod ext_chrono;
21
22#[cfg(feature = "glam")]
23mod ext_glam;
24
25#[cfg(feature = "smallvec")]
26mod ext_smallvec;
27
28#[cfg(feature = "regex")]
29mod ext_regex;
30
31#[cfg(feature = "indexmap")]
32mod ext_indexmap;
33
34#[cfg(feature = "uuid")]
35mod ext_uuid;
36
37#[doc(hidden)]
38pub mod private;
39
40#[cfg(feature = "speedy-derive")]
41pub use speedy_derive::{Readable, Writable};
42
43pub use crate::readable::Readable;
44pub use crate::reader::Reader;
45
46pub use crate::writable::Writable;
47pub use crate::writer::Writer;
48
49pub use crate::endianness::Endianness;
50pub use crate::context::{BigEndian, Context, LittleEndian};
51
52pub use crate::error::{Error, IsEof};
53
54#[cfg(test)]
55mod tests {
56    use std::io;
57    use std::borrow::Cow;
58
59    use super::{
60        Reader,
61        Readable,
62        Writer,
63        Writable,
64        Context,
65        Endianness
66    };
67
68    #[derive(PartialEq, Debug)]
69    struct SimpleStruct {
70        a: u8,
71        b: u8,
72        c: u8
73    }
74
75    impl< C: Context > Writable< C > for SimpleStruct {
76        fn write_to< T: ?Sized + Writer< C > >( &self, writer: &mut T ) -> Result< (), C::Error > {
77            writer.write_value( &self.a )?;
78            writer.write_value( &self.b )?;
79            writer.write_value( &self.c )?;
80
81            Ok(())
82        }
83    }
84
85    impl< 'a, C: Context > Readable< 'a, C > for SimpleStruct {
86        fn read_from< R: Reader< 'a, C > >( reader: &mut R ) -> Result< Self, C::Error > {
87            let a = reader.read_u8()?;
88            let b = reader.read_u8()?;
89            let c = reader.read_u8()?;
90            Ok( SimpleStruct { a, b, c } )
91        }
92    }
93
94    #[test]
95    fn simple_write_to_vec() {
96        let value = SimpleStruct { a: 1, b: 2, c: 3 };
97        let data = value.write_to_vec_with_ctx( Endianness::NATIVE ).unwrap();
98        assert_eq!( data, vec![ 1, 2, 3 ] );
99    }
100
101    #[test]
102    fn simple_read_from_stream_unbuffered() {
103        let data = vec![ 1, 2, 3 ];
104        let cursor = io::Cursor::new( data );
105        let value = SimpleStruct::read_from_stream_unbuffered_with_ctx( Endianness::NATIVE, cursor ).unwrap();
106        assert_eq!( value, SimpleStruct { a: 1, b: 2, c: 3 } );
107    }
108
109    #[test]
110    fn simple_read_from_stream_buffered() {
111        let data = vec![ 1, 2, 3 ];
112        let cursor = io::Cursor::new( data );
113        let value = SimpleStruct::read_from_stream_buffered_with_ctx( Endianness::NATIVE, cursor ).unwrap();
114        assert_eq!( value, SimpleStruct { a: 1, b: 2, c: 3 } );
115    }
116
117    #[test]
118    fn simple_read_from_buffer() {
119        let data = vec![ 1, 2, 3 ];
120        let value = SimpleStruct::read_from_buffer_with_ctx( Endianness::NATIVE, &data ).unwrap();
121        assert_eq!( value, SimpleStruct { a: 1, b: 2, c: 3 } );
122    }
123
124    #[test]
125    fn simple_read_bytes_from_buffer_owned() {
126        let data = vec![ 2, 0, 0, 0, 12, 34 ];
127        let value: Cow< [u8] > = Readable::read_from_buffer_copying_data_with_ctx( Endianness::LittleEndian, &data ).unwrap();
128        assert_eq!( &*value, &[12, 34] );
129        assert_ne!( value.as_ptr(), data[ 4.. ].as_ptr() );
130    }
131
132    #[test]
133    fn simple_read_bytes_from_buffer_borrowed() {
134        let data = vec![ 2, 0, 0, 0, 12, 34 ];
135        let value: Cow< [u8] > = Readable::read_from_buffer_with_ctx( Endianness::LittleEndian, &data ).unwrap();
136        assert_eq!( &*value, &[12, 34] );
137        assert_eq!( value.as_ptr(), data[ 4.. ].as_ptr() );
138    }
139
140    #[test]
141    fn read_from_buffer_copying_data_with_default_ctx() {
142        let data = vec![ 2, 0 ];
143        let value = u16::read_from_buffer_copying_data( &data ).unwrap();
144        assert_eq!( value, 2 );
145    }
146
147    #[test]
148    fn read_from_buffer_borrowed_with_default_ctx() {
149        let data = vec![ 2, 0 ];
150        let value = u16::read_from_buffer( &data ).unwrap();
151        assert_eq!( value, 2 );
152    }
153
154    #[test]
155    fn read_from_stream_unbuffered_with_default_ctx() {
156        let data = vec![ 2, 0 ];
157        let value = u16::read_from_stream_unbuffered( io::Cursor::new( data ) ).unwrap();
158        assert_eq!( value, 2 );
159    }
160
161    #[test]
162    fn read_from_stream_buffered_with_default_ctx() {
163        let data = vec![ 2, 0 ];
164        let value = u16::read_from_stream_buffered( io::Cursor::new( data ) ).unwrap();
165        assert_eq!( value, 2 );
166    }
167
168    #[test]
169    fn write_to_buffer_with_default_ctx() {
170        let mut buffer = [0, 0];
171        2_u16.write_to_buffer( &mut buffer ).unwrap();
172        assert_eq!( buffer, [2, 0] );
173    }
174
175    #[test]
176    fn write_to_vec_with_default_ctx() {
177        let buffer = 2_u16.write_to_vec().unwrap();
178        assert_eq!( buffer, [2, 0] );
179    }
180
181    #[test]
182    fn write_to_stream_with_default_ctx() {
183        let mut buffer = [0, 0];
184        2_u16.write_to_stream( io::Cursor::new( &mut buffer[..] ) ).unwrap();
185        assert_eq!( buffer, [2, 0] );
186    }
187
188    #[test]
189    fn read_write_u8_vec() {
190        let original: Vec< u8 > = vec![ 1, 2, 3 ];
191        let serialized = original.write_to_vec_with_ctx( Endianness::NATIVE ).unwrap();
192        let deserialized: Vec< u8 > = Vec::< u8 >::read_from_buffer_with_ctx( Endianness::NATIVE, &serialized ).unwrap();
193        assert_eq!( original, deserialized );
194    }
195
196    #[test]
197    fn read_write_u64_vec() {
198        let original: Vec< u64 > = vec![ 1, 2, 3 ];
199        let serialized = original.write_to_vec_with_ctx( Endianness::NATIVE ).unwrap();
200        let deserialized: Vec< u64 > = Vec::< u64 >::read_from_buffer_with_ctx( Endianness::NATIVE, &serialized ).unwrap();
201        assert_eq!( original, deserialized );
202    }
203
204    #[test]
205    fn read_write_string() {
206        let original: String = "Hello world!".to_owned();
207        let serialized = original.write_to_vec_with_ctx( Endianness::NATIVE ).unwrap();
208        let deserialized: String = String::read_from_buffer_with_ctx( Endianness::NATIVE, &serialized ).unwrap();
209        assert_eq!( original, deserialized );
210    }
211
212    #[cfg(not(miri))]
213    #[test]
214    fn read_big_vector_of_vectors_from_stream_buffered() {
215        const fn hash32( x: u32 ) -> u32 {
216            let mut x = x.wrapping_mul( 0xa4d94a4f );
217            let a = x >> 16;
218            let b = x >> 30;
219            x ^= a >> b;
220            x.wrapping_mul( 0xa4d94a4f )
221        }
222
223        struct TestStream {
224            buffer: Vec< u8 >,
225            position: usize
226        }
227
228        impl io::Read for TestStream {
229            fn read( &mut self, output: &mut [u8] ) -> Result< usize, io::Error > {
230                if self.position >= self.buffer.len() || output.len() == 0 {
231                    return Ok(0);
232                }
233
234                let random = hash32( self.position as u32 + output.len() as u32 ) as usize;
235                let length = std::cmp::min( random % output.len() + 1, self.buffer.len() - self.position );
236                output[ ..length ].copy_from_slice( &self.buffer[ self.position..self.position + length ] );
237                self.position += length;
238
239                Ok( length )
240            }
241        }
242
243        let mut original: Vec< Vec< u8 > > = Vec::new();
244        for nth in 0..10000 {
245            let mut buffer = Vec::new();
246            let random = hash32( nth as u32 );
247            for byte in 0..(random % 128) as u8 {
248                buffer.push( byte );
249            }
250
251            original.push( buffer );
252        }
253        let serialized = original.write_to_vec().unwrap();
254        let stream = TestStream { buffer: serialized, position: 0 };
255        let deserialized: Vec< Vec< u8 > > = Readable::read_from_stream_buffered( stream ).unwrap();
256        assert_eq!( original, deserialized );
257    }
258}