1use crate::load::{Answer, DirEntry, FileKind, LoadedPlugin, Loading, Question, Rejection};
9use crate::path::PackagePath;
10
11pub trait Source {
13 type Error: std::fmt::Display;
17
18 fn kind(&mut self, path: &PackagePath) -> Result<Option<FileKind>, Self::Error>;
20
21 fn confined(&mut self, path: &PackagePath) -> Result<bool, Self::Error>;
24
25 fn read(&mut self, path: &PackagePath) -> Result<Vec<u8>, Self::Error>;
27
28 fn list(&mut self, path: &PackagePath) -> Result<Vec<DirEntry>, Self::Error>;
30}
31
32pub fn load<S: Source>(source: &mut S) -> Result<LoadedPlugin, Rejection> {
34 let mut loading = Loading::start();
35 while let Some(question) = loading.question() {
36 let answer = match &question {
37 Question::Kind(path) => match source.kind(path) {
38 Ok(kind) => Answer::Kind(kind),
39 Err(e) => Answer::Unavailable { detail: e.to_string() },
40 },
41 Question::Confined(path) => match source.confined(path) {
42 Ok(confined) => Answer::Confined(confined),
43 Err(e) => Answer::Unavailable { detail: e.to_string() },
44 },
45 Question::Read(path) => match source.read(path) {
46 Ok(bytes) => Answer::Bytes(bytes),
47 Err(e) => Answer::Unavailable { detail: e.to_string() },
48 },
49 Question::List(path) => match source.list(path) {
50 Ok(entries) => Answer::Entries(entries),
51 Err(e) => Answer::Unavailable { detail: e.to_string() },
52 },
53 };
54 loading.answer(answer).expect("answer variant matches the question just asked");
55 }
56 loading.finish()
57}