rust_releases_io/client/
fs_client.rs1use crate::client::errors::IoError;
2use crate::{
3 Document, IsStaleError, ResourceFile, RetrievalLocation, RetrievedDocument, RustReleasesClient,
4};
5use std::path::Path;
6use std::{fs, io};
7
8const DEFAULT_MEMORY_SIZE: usize = 4096;
9
10#[derive(Debug, Default)]
15pub struct FsClient;
16
17impl RustReleasesClient for FsClient {
18 type Error = FsClientError;
19
20 fn fetch(&self, resource: ResourceFile) -> Result<RetrievedDocument, Self::Error> {
21 let path = Path::new(resource.url);
24
25 let file =
26 fs::File::open(path).map_err(|e| IoError::inaccessible(e, path.to_path_buf()))?;
27 let mut reader = io::BufReader::new(file);
28
29 let document = read_document(&mut reader)?;
30
31 Ok(RetrievedDocument::new(
32 document,
33 RetrievalLocation::Path(path.to_path_buf()),
34 ))
35 }
36}
37
38fn read_document(reader: &mut impl io::BufRead) -> Result<Document, FsClientError> {
39 let mut buffer = Vec::with_capacity(DEFAULT_MEMORY_SIZE);
40
41 let bytes_read = reader
42 .read_to_end(&mut buffer)
43 .map_err(IoError::auxiliary)?;
44
45 if bytes_read == 0 {
46 return Err(FsClientError::EmptyFile);
47 }
48
49 Ok(Document::new(buffer))
50}
51
52#[derive(Debug, thiserror::Error)]
54#[non_exhaustive]
55pub enum FsClientError {
56 #[error("Received empty file")]
58 EmptyFile,
59
60 #[error(transparent)]
62 Io(#[from] IoError),
63
64 #[error(transparent)]
67 IsStale(#[from] IsStaleError),
68}