stuffr_core/source/
borrowed.rs1use std::io::Read;
4
5use super::{DecodeSideSource, SeekRead, Source, SourceCaps};
6use crate::archive::{Codec, DecodeOpts};
7use crate::error::{Error, Result};
8
9pub struct BorrowedSource<'a> {
17 inner: Box<dyn Read + 'a>,
18}
19
20impl<'a> BorrowedSource<'a> {
21 pub fn new<R: Read + 'a>(r: R) -> Self {
22 Self { inner: Box::new(r) }
23 }
24}
25
26impl Read for BorrowedSource<'_> {
27 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
28 self.inner.read(buf)
29 }
30}
31
32impl Source for BorrowedSource<'_> {
33 fn caps(&self) -> SourceCaps {
34 SourceCaps {
35 seekable: false,
36 len: None,
37 }
38 }
39
40 fn as_seek(&mut self) -> Option<&mut dyn SeekRead> {
41 None
42 }
43}
44
45pub fn decode_reader<'a, R: Read + 'a>(
59 codec: &dyn Codec,
60 r: R,
61 o: &DecodeOpts,
62) -> Result<Box<dyn Source + 'a>> {
63 if !codec.caps().decode {
64 return Err(Error::CapabilityUnavailable {
65 format: codec.id(),
66 available: "written",
67 requested: "read",
68 });
69 }
70 let decoded = codec
71 .decoder(Box::new(BorrowedSource::new(r)), o)
72 .map_err(|e| match e {
73 Error::Io(io_err) => Error::from_decode_io(io_err),
74 other => other,
75 })?;
76 Ok(DecodeSideSource::wrap(decoded))
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82 use crate::testing::MockCodec;
83
84 #[test]
85 fn a_borrowed_source_reads_a_local_borrow_and_never_claims_seek() {
86 let bytes = b"hello".to_vec();
87 let mut cursor = std::io::Cursor::new(&bytes[..]);
88 let mut s = BorrowedSource::new(&mut cursor);
89 assert!(
90 !s.caps().seekable,
91 "a Cursor can seek; the source must not say so"
92 );
93 assert_eq!(s.caps().len, None);
94 assert!(s.as_seek().is_none());
95 let mut out = Vec::new();
96 s.read_to_end(&mut out).unwrap();
97 assert_eq!(out, b"hello");
98 }
99
100 #[test]
101 fn decode_reader_decodes_through_a_non_send_borrow() {
102 struct NotSend<'b>(std::marker::PhantomData<std::rc::Rc<()>>, &'b [u8]);
104 impl Read for NotSend<'_> {
105 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
106 self.1.read(buf)
107 }
108 }
109 let encoded: Vec<u8> = b"abc".iter().map(|b| b ^ 0xFF).collect();
110 let mut out = Vec::new();
111 decode_reader(
112 &MockCodec,
113 NotSend(std::marker::PhantomData, &encoded),
114 &DecodeOpts::default(),
115 )
116 .unwrap()
117 .read_to_end(&mut out)
118 .unwrap();
119 assert_eq!(out, b"abc");
120 }
121}