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