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}