Skip to main content

sbom_walker/
discover.rs

1//! Discovering
2
3use crate::{model::metadata, model::metadata::SourceMetadata};
4use std::{fmt::Debug, future::Future, ops::Deref, time::SystemTime};
5use url::Url;
6use walker_common::utils::url::Urlify;
7
8/// Discovery configuration
9pub struct DiscoverConfig {
10    /// The URL to locate the SBOM metadata.
11    pub source: String,
12
13    /// Only report documents which have changed since the provided date. If a document has no
14    /// change information, or this field is [`None`], it wil always be reported.
15    pub since: Option<SystemTime>,
16
17    /// Keys which can be used for validation
18    pub keys: Vec<metadata::Key>,
19}
20
21impl DiscoverConfig {
22    pub fn with_since(mut self, since: impl Into<Option<SystemTime>>) -> Self {
23        self.since = since.into();
24        self
25    }
26}
27
28#[derive(Clone, Debug, PartialEq, Eq)]
29pub struct DiscoveredSbom {
30    /// The URL of the SBOM
31    pub url: Url,
32    /// The "last changed" date from the change information
33    pub modified: SystemTime,
34}
35
36impl Urlify for DiscoveredSbom {
37    fn url(&self) -> &Url {
38        &self.url
39    }
40}
41
42#[derive(Debug)]
43pub struct DiscoveredContext<'c> {
44    pub metadata: &'c SourceMetadata,
45}
46
47impl Deref for DiscoveredContext<'_> {
48    type Target = SourceMetadata;
49
50    fn deref(&self) -> &Self::Target {
51        self.metadata
52    }
53}
54
55/// Visiting discovered SBOMs
56pub trait DiscoveredVisitor {
57    type Error: std::fmt::Display + Debug;
58    type Context;
59
60    fn visit_context(
61        &self,
62        context: &DiscoveredContext,
63    ) -> impl Future<Output = Result<Self::Context, Self::Error>>;
64
65    fn visit_sbom(
66        &self,
67        context: &Self::Context,
68        sbom: DiscoveredSbom,
69    ) -> impl Future<Output = Result<(), Self::Error>>;
70}
71
72impl<F, E, Fut> DiscoveredVisitor for F
73where
74    F: Fn(DiscoveredSbom) -> Fut,
75    Fut: Future<Output = Result<(), E>>,
76    E: std::fmt::Display + Debug,
77{
78    type Error = E;
79    type Context = ();
80
81    async fn visit_context(
82        &self,
83        _context: &DiscoveredContext<'_>,
84    ) -> Result<Self::Context, Self::Error> {
85        Ok(())
86    }
87
88    async fn visit_sbom(
89        &self,
90        _context: &Self::Context,
91        sbom: DiscoveredSbom,
92    ) -> Result<(), Self::Error> {
93        self(sbom).await
94    }
95}