fuchsia_archive/
utf8_reader.rs
1use crate::error::Error;
6
7#[derive(Debug)]
10pub struct Utf8Reader<T>
11where
12 T: std::io::Read + std::io::Seek,
13{
14 reader: crate::read::Reader<T>,
15}
16
17impl<T> Utf8Reader<T>
18where
19 T: std::io::Read + std::io::Seek,
20{
21 pub fn new(source: T) -> Result<Self, Error> {
23 let ret = Self { reader: crate::read::Reader::new(source)? };
24 let () = ret.try_list().try_for_each(|r| r.map(|_| ()))?;
25 Ok(ret)
26 }
27
28 fn try_list(&self) -> impl ExactSizeIterator<Item = Result<crate::Utf8Entry<'_>, Error>> {
30 self.reader.list().map(|e| {
31 Ok(crate::Utf8Entry {
32 path: std::str::from_utf8(e.path).map_err(|err| Error::PathDataInvalidUtf8 {
33 source: err,
34 path: e.path.into(),
35 })?,
36 offset: e.offset,
37 length: e.length,
38 })
39 })
40 }
41
42 pub fn list(&self) -> impl ExactSizeIterator<Item = crate::Utf8Entry<'_>> {
44 self.try_list().map(|r| {
45 r.expect("Utf8Reader::new only succeeds if try_list succeeds for every element")
46 })
47 }
48
49 pub fn read_file(&mut self, path: &str) -> Result<Vec<u8>, Error> {
52 self.reader.read_file(path.as_bytes())
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59 use assert_matches::assert_matches;
60 use fuchsia_async as fasync;
61 use std::io::Cursor;
62
63 #[fasync::run_singlethreaded(test)]
64 async fn new_rejects_non_utf8_path() {
65 let mut far_bytes = vec![];
66 let () = crate::write::write(
67 &mut far_bytes,
68 std::collections::BTreeMap::from_iter([(
69 b"\xff",
70 (0, Box::new("".as_bytes()) as Box<dyn std::io::Read>),
71 )]),
72 )
73 .unwrap();
74
75 assert_matches!(
76 Utf8Reader::new(Cursor::new(far_bytes)),
77 Err(crate::Error::PathDataInvalidUtf8{source: _, path}) if path == b"\xff".to_vec()
78 );
79 }
80
81 #[fasync::run_singlethreaded(test)]
82 async fn list_does_not_panic() {
83 let mut far_bytes = vec![];
84 let () = crate::write::write(
85 &mut far_bytes,
86 std::collections::BTreeMap::from_iter([(
87 "valid-utf8",
88 (0, Box::new("".as_bytes()) as Box<dyn std::io::Read>),
89 )]),
90 )
91 .unwrap();
92
93 itertools::assert_equal(
94 Utf8Reader::new(Cursor::new(far_bytes)).unwrap().list(),
95 [crate::Utf8Entry { path: "valid-utf8", offset: 4096, length: 0 }],
96 );
97 }
98
99 #[fasync::run_singlethreaded(test)]
100 async fn read_file() {
101 let mut far_bytes = vec![];
102 let () = crate::write::write(
103 &mut far_bytes,
104 std::collections::BTreeMap::from_iter([(
105 "valid-utf8",
106 (12, Box::new("test-content".as_bytes()) as Box<dyn std::io::Read>),
107 )]),
108 )
109 .unwrap();
110
111 assert_eq!(
112 Utf8Reader::new(Cursor::new(far_bytes)).unwrap().read_file("valid-utf8").unwrap(),
113 b"test-content".to_vec()
114 );
115 }
116}