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}