1use crate::model::metadata::ProviderMetadata;
4use std::fmt::Debug;
5use std::future::Future;
6use std::sync::Arc;
7use std::time::SystemTime;
8use url::Url;
9use walker_common::utils::url::Urlify;
10
11pub struct DiscoverConfig {
13 pub source: String,
18
19 pub since: Option<SystemTime>,
22}
23
24impl DiscoverConfig {
25 pub fn with_since(mut self, since: impl Into<Option<SystemTime>>) -> Self {
26 self.since = since.into();
27 self
28 }
29}
30
31impl From<&str> for DiscoverConfig {
32 fn from(value: &str) -> Self {
33 Self {
34 since: None,
35 source: value.to_string(),
36 }
37 }
38}
39
40#[derive(Clone, Debug, PartialEq, Eq)]
41pub enum DistributionContext {
42 Directory(Url),
43 Feed(Url),
44}
45
46impl DistributionContext {
47 pub fn url(&self) -> &Url {
49 match self {
50 Self::Directory(url) => url,
51 Self::Feed(url) => url,
52 }
53 }
54}
55
56#[derive(Clone, Debug, PartialEq, Eq)]
57pub struct DiscoveredAdvisory {
58 pub context: Arc<DistributionContext>,
60 pub url: Url,
62 pub digest: Option<Url>,
64 pub signature: Option<Url>,
66 pub modified: SystemTime,
68}
69
70pub trait AsDiscovered: Debug {
72 fn as_discovered(&self) -> &DiscoveredAdvisory;
73}
74
75impl AsDiscovered for DiscoveredAdvisory {
76 fn as_discovered(&self) -> &DiscoveredAdvisory {
77 self
78 }
79}
80
81impl Urlify for DiscoveredAdvisory {
82 fn url(&self) -> &Url {
83 &self.url
84 }
85
86 fn relative_base_and_url(&self) -> Option<(&Url, String)> {
87 self.context
88 .url()
89 .make_relative(&self.url)
90 .map(|relative| (self.context.url(), relative))
91 }
92}
93
94#[derive(Debug)]
95pub struct DiscoveredContext<'c> {
96 pub metadata: &'c ProviderMetadata,
97}
98
99pub trait DiscoveredVisitor {
101 type Error: std::fmt::Display + Debug;
102 type Context;
103
104 fn visit_context(
105 &self,
106 context: &DiscoveredContext,
107 ) -> impl Future<Output = Result<Self::Context, Self::Error>>;
108
109 fn visit_advisory(
110 &self,
111 context: &Self::Context,
112 advisory: DiscoveredAdvisory,
113 ) -> impl Future<Output = Result<(), Self::Error>>;
114}
115
116impl<F, E, Fut> DiscoveredVisitor for F
117where
118 F: Fn(DiscoveredAdvisory) -> Fut,
119 Fut: Future<Output = Result<(), E>>,
120 E: std::fmt::Display + Debug,
121{
122 type Error = E;
123 type Context = ();
124
125 async fn visit_context(
126 &self,
127 _context: &DiscoveredContext<'_>,
128 ) -> Result<Self::Context, Self::Error> {
129 Ok(())
130 }
131
132 async fn visit_advisory(
133 &self,
134 _ctx: &Self::Context,
135 advisory: DiscoveredAdvisory,
136 ) -> Result<(), Self::Error> {
137 self(advisory).await
138 }
139}