1use crate::io::{BufRead, Read, Write};
26use core::{mem, ptr, slice};
27
28use crate::message;
29use crate::serialize;
30use crate::{Error, ErrorKind, Result};
31
32struct PackedRead<R>
38where
39 R: BufRead,
40{
41 inner: R,
42}
43
44impl<R> PackedRead<R>
45where
46 R: BufRead,
47{
48 fn get_read_buffer(&mut self) -> Result<(*const u8, *const u8)> {
49 let buf = self.inner.fill_buf()?;
50 Ok((buf.as_ptr(), buf.as_ptr().wrapping_add(buf.len())))
51 }
52}
53
54#[inline]
55fn ptr_sub<T>(p1: *const T, p2: *const T) -> usize {
56 (p1 as usize - p2 as usize) / mem::size_of::<T>()
57}
58
59macro_rules! refresh_buffer(
60 ($this:expr, $size:ident, $in_ptr:ident, $in_end:ident, $out:ident,
61 $outBuf:ident, $buffer_begin:ident) => (
62 {
63 $this.inner.consume($size);
64 let (b, e) = $this.get_read_buffer()?;
65 $in_ptr = b;
66 $in_end = e;
67 $size = ptr_sub($in_end, $in_ptr);
68 $buffer_begin = b;
69 if $size == 0 {
70 return Err(Error::from_kind(ErrorKind::PrematureEndOfPackedInput));
71 }
72 }
73 );
74 );
75
76impl<R> Read for PackedRead<R>
77where
78 R: BufRead,
79{
80 fn read(&mut self, out_buf: &mut [u8]) -> Result<usize> {
81 let len = out_buf.len();
82 if len == 0 {
83 return Ok(0);
84 }
85
86 assert!(len % 8 == 0, "PackedRead reads must be word-aligned.");
87
88 unsafe {
89 let out_buf_start = out_buf.as_mut_ptr();
90 let mut out = out_buf_start;
91 let out_end: *mut u8 = out.wrapping_add(len);
92
93 let (mut in_ptr, mut in_end) = self.get_read_buffer()?;
94 let mut buffer_begin = in_ptr;
95 let mut size = ptr_sub(in_end, in_ptr);
96 if size == 0 {
97 return Ok(0);
98 }
99
100 loop {
101 let tag: u8;
102
103 assert_eq!(
104 ptr_sub(out, out_buf_start) % 8,
105 0,
106 "Output pointer should always be aligned here."
107 );
108
109 if ptr_sub(in_end, in_ptr) < 10 {
110 if ptr_sub(in_end, in_ptr) == 0 {
111 refresh_buffer!(self, size, in_ptr, in_end, out, out_buf, buffer_begin);
112 continue;
113 }
114
115 tag = *in_ptr;
119 in_ptr = in_ptr.add(1);
120
121 for i in 0..8 {
122 if (tag & (1u8 << i)) != 0 {
123 if ptr_sub(in_end, in_ptr) == 0 {
124 refresh_buffer!(
125 self,
126 size,
127 in_ptr,
128 in_end,
129 out,
130 out_buf,
131 buffer_begin
132 );
133 }
134 *out = *in_ptr;
135 out = out.add(1);
136 in_ptr = in_ptr.add(1);
137 } else {
138 *out = 0;
139 out = out.add(1);
140 }
141 }
142
143 if ptr_sub(in_end, in_ptr) == 0 && (tag == 0 || tag == 0xff) {
144 refresh_buffer!(self, size, in_ptr, in_end, out, out_buf, buffer_begin);
145 }
146 } else {
147 tag = *in_ptr;
148 in_ptr = in_ptr.add(1);
149
150 for n in 0..8 {
151 let is_nonzero = (tag & (1u8 << n)) != 0;
152 *out = (*in_ptr) & ((-i8::from(is_nonzero)) as u8);
153 out = out.add(1);
154 in_ptr = in_ptr.add(is_nonzero as usize);
155 }
156 }
157 if tag == 0 {
158 assert!(
159 ptr_sub(in_end, in_ptr) > 0,
160 "Should always have non-empty buffer here."
161 );
162
163 let run_length: usize = (*in_ptr) as usize * 8;
164 in_ptr = in_ptr.add(1);
165
166 if run_length > ptr_sub(out_end, out) {
167 return Err(Error::from_kind(
168 ErrorKind::PackedInputDidNotEndCleanlyOnASegmentBoundary,
169 ));
170 }
171
172 ptr::write_bytes(out, 0, run_length);
173 out = out.add(run_length);
174 } else if tag == 0xff {
175 assert!(
176 ptr_sub(in_end, in_ptr) > 0,
177 "Should always have non-empty buffer here"
178 );
179
180 let mut run_length: usize = (*in_ptr) as usize * 8;
181 in_ptr = in_ptr.add(1);
182
183 if run_length > ptr_sub(out_end, out) {
184 return Err(Error::from_kind(
185 ErrorKind::PackedInputDidNotEndCleanlyOnASegmentBoundary,
186 ));
187 }
188
189 let in_remaining = ptr_sub(in_end, in_ptr);
190 if in_remaining >= run_length {
191 ptr::copy_nonoverlapping(in_ptr, out, run_length);
193 out = out.add(run_length);
194 in_ptr = in_ptr.add(run_length);
195 } else {
196 ptr::copy_nonoverlapping(in_ptr, out, in_remaining);
198 out = out.add(in_remaining);
199 run_length -= in_remaining;
200
201 self.inner.consume(size);
202 {
203 let buf = slice::from_raw_parts_mut::<u8>(out, run_length);
204 self.inner.read_exact(buf)?;
205 }
206
207 out = out.add(run_length);
208
209 if out == out_end {
210 return Ok(len);
211 } else {
212 let (b, e) = self.get_read_buffer()?;
213 in_ptr = b;
214 in_end = e;
215 size = ptr_sub(e, b);
216 buffer_begin = in_ptr;
217 continue;
218 }
219 }
220 }
221
222 if out == out_end {
223 self.inner.consume(ptr_sub(in_ptr, buffer_begin));
224 return Ok(len);
225 }
226 }
227 }
228 }
229}
230
231#[cfg(feature = "alloc")]
233pub fn read_message<R>(
234 read: R,
235 options: message::ReaderOptions,
236) -> Result<crate::message::Reader<serialize::OwnedSegments>>
237where
238 R: BufRead,
239{
240 let packed_read = PackedRead { inner: read };
241 serialize::read_message(packed_read, options)
242}
243
244#[cfg(feature = "alloc")]
246pub fn try_read_message<R>(
247 read: R,
248 options: message::ReaderOptions,
249) -> Result<Option<crate::message::Reader<serialize::OwnedSegments>>>
250where
251 R: BufRead,
252{
253 let packed_read = PackedRead { inner: read };
254 serialize::try_read_message(packed_read, options)
255}
256
257pub fn read_message_no_alloc<R>(
264 read: R,
265 buffer: &mut [u8],
266 options: message::ReaderOptions,
267) -> Result<crate::message::Reader<serialize::NoAllocBufferSegments<&[u8]>>>
268where
269 R: BufRead,
270{
271 let packed_read = PackedRead { inner: read };
272 serialize::read_message_no_alloc(packed_read, buffer, options)
273}
274
275pub fn try_read_message_no_alloc<R>(
282 read: R,
283 buffer: &mut [u8],
284 options: message::ReaderOptions,
285) -> Result<Option<crate::message::Reader<serialize::NoAllocBufferSegments<&[u8]>>>>
286where
287 R: BufRead,
288{
289 let packed_read = PackedRead { inner: read };
290 serialize::try_read_message_no_alloc(packed_read, buffer, options)
291}
292
293struct PackedWrite<W>
294where
295 W: Write,
296{
297 inner: W,
298}
299
300impl<W> Write for PackedWrite<W>
301where
302 W: Write,
303{
304 fn write_all(&mut self, in_buf: &[u8]) -> Result<()> {
305 unsafe {
306 let mut buf_idx: usize = 0;
307 let mut buf: [u8; 64] = [0; 64];
308
309 let mut in_ptr: *const u8 = in_buf.as_ptr();
310 let in_end: *const u8 = in_buf.as_ptr().wrapping_add(in_buf.len());
311
312 while in_ptr < in_end {
313 if buf_idx + 10 > buf.len() {
314 self.inner.write_all(&buf[..buf_idx])?;
318 buf_idx = 0;
319 }
320
321 let tag_pos = buf_idx;
322 buf_idx += 1;
323
324 let bit0 = u8::from(*in_ptr != 0);
325 *buf.get_unchecked_mut(buf_idx) = *in_ptr;
326 buf_idx += bit0 as usize;
327 in_ptr = in_ptr.add(1);
328
329 let bit1 = u8::from(*in_ptr != 0);
330 *buf.get_unchecked_mut(buf_idx) = *in_ptr;
331 buf_idx += bit1 as usize;
332 in_ptr = in_ptr.add(1);
333
334 let bit2 = u8::from(*in_ptr != 0);
335 *buf.get_unchecked_mut(buf_idx) = *in_ptr;
336 buf_idx += bit2 as usize;
337 in_ptr = in_ptr.add(1);
338
339 let bit3 = u8::from(*in_ptr != 0);
340 *buf.get_unchecked_mut(buf_idx) = *in_ptr;
341 buf_idx += bit3 as usize;
342 in_ptr = in_ptr.add(1);
343
344 let bit4 = u8::from(*in_ptr != 0);
345 *buf.get_unchecked_mut(buf_idx) = *in_ptr;
346 buf_idx += bit4 as usize;
347 in_ptr = in_ptr.add(1);
348
349 let bit5 = u8::from(*in_ptr != 0);
350 *buf.get_unchecked_mut(buf_idx) = *in_ptr;
351 buf_idx += bit5 as usize;
352 in_ptr = in_ptr.add(1);
353
354 let bit6 = u8::from(*in_ptr != 0);
355 *buf.get_unchecked_mut(buf_idx) = *in_ptr;
356 buf_idx += bit6 as usize;
357 in_ptr = in_ptr.add(1);
358
359 let bit7 = u8::from(*in_ptr != 0);
360 *buf.get_unchecked_mut(buf_idx) = *in_ptr;
361 buf_idx += bit7 as usize;
362 in_ptr = in_ptr.add(1);
363
364 let tag: u8 = bit0
365 | (bit1 << 1)
366 | (bit2 << 2)
367 | (bit3 << 3)
368 | (bit4 << 4)
369 | (bit5 << 5)
370 | (bit6 << 6)
371 | (bit7 << 7);
372
373 *buf.get_unchecked_mut(tag_pos) = tag;
374
375 if tag == 0 {
376 let mut in_word: *const [u8; 8] = in_ptr as *const [u8; 8];
381 let mut limit: *const [u8; 8] = in_end as *const [u8; 8];
382 if ptr_sub(limit, in_word) > 255 {
383 limit = in_word.add(255);
384 }
385 while in_word < limit && *in_word == [0; 8] {
386 in_word = in_word.add(1);
387 }
388
389 *buf.get_unchecked_mut(buf_idx) = ptr_sub(in_word, in_ptr as *const [u8; 8])
390 .try_into()
391 .unwrap();
392 buf_idx += 1;
393 in_ptr = in_word as *const u8;
394 } else if tag == 0xff {
395 let run_start = in_ptr;
404 let mut limit = in_end;
405 if ptr_sub(limit, in_ptr) > 255 * 8 {
406 limit = in_ptr.add(255 * 8);
407 }
408
409 while in_ptr < limit {
410 let mut c = 0;
411
412 for _ in 0..8 {
413 c += u8::from(*in_ptr == 0);
414 in_ptr = in_ptr.add(1);
415 }
416
417 if c >= 2 {
418 in_ptr = in_ptr.sub(8);
421 break;
422 }
423 }
424
425 let count: usize = ptr_sub(in_ptr, run_start);
426 *buf.get_unchecked_mut(buf_idx) = (count / 8).try_into().unwrap();
427 buf_idx += 1;
428
429 self.inner.write_all(&buf[..buf_idx])?;
430 buf_idx = 0;
431 self.inner
432 .write_all(slice::from_raw_parts::<u8>(run_start, count))?;
433 }
434 }
435
436 self.inner.write_all(&buf[..buf_idx])?;
437 Ok(())
438 }
439 }
440}
441
442pub fn write_message<W, A>(write: W, message: &crate::message::Builder<A>) -> Result<()>
447where
448 W: Write,
449 A: crate::message::Allocator,
450{
451 let packed_write = PackedWrite { inner: write };
452 serialize::write_message(packed_write, message)
453}
454
455#[cfg(feature = "alloc")]
456#[cfg(test)]
457mod tests {
458 use crate::io::{Read, Write};
459
460 use quickcheck::{quickcheck, TestResult};
461
462 use super::read_message;
463 use crate::message::ReaderOptions;
464 use crate::serialize::test::write_message_segments;
465 use crate::serialize_packed::{PackedRead, PackedWrite};
466 use crate::ErrorKind;
467
468 #[test]
469 pub(crate) fn premature_eof() {
470 let input_bytes: &[u8] = &[];
471 let mut packed_read = PackedRead { inner: input_bytes };
472
473 let mut output_bytes: alloc::vec::Vec<u8> = vec![0; 8];
474 assert!(packed_read.read_exact(&mut output_bytes[..]).is_err());
475 }
476
477 pub(crate) fn check_unpacks_to(packed: &[u8], unpacked: &[u8]) {
478 let mut packed_read = PackedRead { inner: packed };
479
480 let mut bytes: alloc::vec::Vec<u8> = vec![0; unpacked.len()];
481 packed_read.read_exact(&mut bytes[..]).unwrap();
482
483 assert!(packed_read.inner.is_empty()); assert_eq!(bytes, unpacked);
485 }
486
487 pub(crate) fn check_packing(unpacked: &[u8], packed: &[u8]) {
488 let mut bytes: alloc::vec::Vec<u8> = vec![0; packed.len()];
492 {
493 let mut packed_write = PackedWrite {
494 inner: &mut bytes[..],
495 };
496 packed_write.write_all(unpacked).unwrap();
497 }
498
499 assert_eq!(bytes, packed);
500
501 check_unpacks_to(packed, unpacked);
504 }
505
506 #[test]
507 pub(crate) fn simple_packing() {
508 check_packing(&[], &[]);
509 check_packing(&[0; 8], &[0, 0]);
510 check_packing(&[0, 0, 12, 0, 0, 34, 0, 0], &[0x24, 12, 34]);
511 check_packing(
512 &[1, 3, 2, 4, 5, 7, 6, 8],
513 &[0xff, 1, 3, 2, 4, 5, 7, 6, 8, 0],
514 );
515 check_packing(
516 &[0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 2, 4, 5, 7, 6, 8],
517 &[0, 0, 0xff, 1, 3, 2, 4, 5, 7, 6, 8, 0],
518 );
519 check_packing(
520 &[0, 0, 12, 0, 0, 34, 0, 0, 1, 3, 2, 4, 5, 7, 6, 8],
521 &[0x24, 12, 34, 0xff, 1, 3, 2, 4, 5, 7, 6, 8, 0],
522 );
523 check_packing(
524 &[1, 3, 2, 4, 5, 7, 6, 8, 8, 6, 7, 4, 5, 2, 3, 1],
525 &[0xff, 1, 3, 2, 4, 5, 7, 6, 8, 1, 8, 6, 7, 4, 5, 2, 3, 1],
526 );
527
528 check_packing(
529 &[
530 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4,
531 5, 6, 7, 8, 0, 2, 4, 0, 9, 0, 5, 1,
532 ],
533 &[
534 0xff, 1, 2, 3, 4, 5, 6, 7, 8, 3, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1,
535 2, 3, 4, 5, 6, 7, 8, 0xd6, 2, 4, 9, 5, 1,
536 ],
537 );
538 check_packing(
539 &[
540 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 6, 2, 4, 3, 9, 0, 5, 1, 1, 2, 3, 4,
541 5, 6, 7, 8, 0, 2, 4, 0, 9, 0, 5, 1,
542 ],
543 &[
544 0xff, 1, 2, 3, 4, 5, 6, 7, 8, 3, 1, 2, 3, 4, 5, 6, 7, 8, 6, 2, 4, 3, 9, 0, 5, 1, 1,
545 2, 3, 4, 5, 6, 7, 8, 0xd6, 2, 4, 9, 5, 1,
546 ],
547 );
548
549 check_packing(
550 &[
551 8, 0, 100, 6, 0, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
552 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 3, 1,
553 ],
554 &[0xed, 8, 100, 6, 1, 1, 2, 0, 2, 0xd4, 1, 2, 3, 1],
555 );
556
557 check_packing(&[0; 8], &[0, 0]);
558 check_packing(&[0; 16], &[0, 1]);
559 check_packing(
560 &[
561 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
562 ],
563 &[0, 2],
564 );
565 check_packing(&[0; 258 * 8], &[0, 255, 0, 1]);
566 }
567
568 quickcheck! {
569 #[cfg_attr(miri, ignore)] fn test_round_trip(segments: alloc::vec::Vec<alloc::vec::Vec<crate::Word>>) -> TestResult {
571 use crate::message::ReaderSegments;
572 if segments.is_empty() { return TestResult::discard(); }
573 let mut buf: alloc::vec::Vec<u8> = alloc::vec::Vec::new();
574
575 write_message_segments(&mut PackedWrite { inner: &mut buf }, &segments);
576 let message = read_message(&mut &buf[..], ReaderOptions::new()).unwrap();
577 let result_segments = message.into_segments();
578
579 TestResult::from_bool(segments.iter().enumerate().all(|(i, segment)| {
580 crate::Word::words_to_bytes(&segment[..]) == result_segments.get_segment(i as u32).unwrap()
581 }))
582 }
583
584 #[cfg_attr(miri, ignore)] fn test_unpack(packed: alloc::vec::Vec<u8>) -> TestResult {
586 let len = packed.len();
587 let mut packed_read = PackedRead { inner: &packed[..] };
588
589 let mut out_buffer: alloc::vec::Vec<u8> = vec![0; len * 8];
590
591 let _ = packed_read.read_exact(&mut out_buffer);
592 TestResult::from_bool(true)
593 }
594 }
595
596 #[test]
597 fn did_not_end_cleanly_on_a_segment_boundary() {
598 let packed = &[0xff, 1, 2, 3, 4, 5, 6, 7, 8, 37, 1, 2];
599 let mut packed_read = PackedRead { inner: &packed[..] };
600
601 let mut bytes: alloc::vec::Vec<u8> = vec![0; 200];
602 match packed_read.read_exact(&mut bytes[..]) {
603 Ok(_) => panic!("should have been an error"),
604 Err(e) => {
605 assert_eq!(
606 e.kind,
607 ErrorKind::PackedInputDidNotEndCleanlyOnASegmentBoundary,
608 );
609 }
610 }
611 }
612
613 #[test]
614 fn premature_end_of_packed_input() {
615 fn helper(packed: &[u8]) {
616 let mut packed_read = PackedRead { inner: packed };
617
618 let mut bytes: alloc::vec::Vec<u8> = vec![0; 200];
619 match packed_read.read_exact(&mut bytes[..]) {
620 Ok(_) => panic!("should have been an error"),
621 Err(e) => {
622 assert_eq!(e.kind, ErrorKind::PrematureEndOfPackedInput);
623 }
624 }
625 }
626
627 helper(&[0xf0, 1, 2]);
628 helper(&[0]);
629 helper(&[0xff, 1, 2, 3, 4, 5, 6, 7, 8]);
630
631 helper(&[1, 1]);
634 }
635
636 #[test]
637 fn packed_segment_table() {
638 let packed_buf = &[0x11, 4, 1, 0, 1, 0, 0];
639
640 check_unpacks_to(
641 packed_buf,
642 &[
643 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
644 0, 0, 0, 0,
645 ],
646 );
647
648 read_message(&mut &packed_buf[..], Default::default()).unwrap();
651 }
652}