walker_common/retrieve/
mod.rs

1//! Retrieving remote content
2
3mod error;
4pub use error::*;
5
6use crate::utils::{hex::Hex, url::Urlify};
7use digest::{Digest, Output};
8use std::{
9    fmt::{Debug, Formatter},
10    ops::{Deref, DerefMut},
11};
12use time::OffsetDateTime;
13
14pub trait RetrievedDocument: Urlify + Debug {
15    type Discovered: Urlify + Debug;
16}
17
18/// The retrieved digest
19#[derive(Clone, PartialEq, Eq)]
20pub struct RetrievedDigest<D: Digest> {
21    /// The expected digest, as read from the remote source
22    pub expected: String,
23    /// The actual digest, as calculated from reading the content
24    pub actual: Output<D>,
25}
26
27impl<D: Digest> RetrievedDigest<D> {
28    pub fn validate(&self) -> Result<(), (&str, String)> {
29        let actual = Hex(&self.actual).to_lower();
30        if self.expected == actual {
31            Ok(())
32        } else {
33            Err((&self.expected, actual))
34        }
35    }
36}
37
38impl<D: Digest> Debug for RetrievedDigest<D> {
39    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
40        f.debug_struct("RetrievedDigest")
41            .field("expected", &self.expected)
42            .field("actual", &Hex(&self.actual))
43            .finish()
44    }
45}
46
47/// Building a digest while retrieving.
48#[derive(Clone)]
49pub struct RetrievingDigest<D: Digest> {
50    pub expected: String,
51    pub current: D,
52}
53
54impl<D> Deref for RetrievingDigest<D>
55where
56    D: Digest,
57{
58    type Target = D;
59
60    fn deref(&self) -> &Self::Target {
61        &self.current
62    }
63}
64
65impl<D> DerefMut for RetrievingDigest<D>
66where
67    D: Digest,
68{
69    fn deref_mut(&mut self) -> &mut Self::Target {
70        &mut self.current
71    }
72}
73
74impl<D> From<RetrievingDigest<D>> for RetrievedDigest<D>
75where
76    D: Digest,
77{
78    fn from(value: RetrievingDigest<D>) -> Self {
79        Self {
80            expected: value.expected,
81            actual: value.current.finalize(),
82        }
83    }
84}
85
86/// Metadata of the retrieval process.
87#[derive(Clone, Debug, Default)]
88pub struct RetrievalMetadata {
89    /// Last known modification time
90    pub last_modification: Option<OffsetDateTime>,
91    /// ETag
92    pub etag: Option<String>,
93}