web_search/providers/base.rs
1//! Base provider trait and common types
2
3use async_trait::async_trait;
4use serde::{Deserialize, Serialize};
5
6use crate::error::SearchError;
7use crate::transport::SearchTransport;
8
9/// A single search result
10#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct SearchResult {
12 /// The title of the search result
13 pub title: String,
14 /// The URL of the search result
15 pub url: String,
16 /// The description/snippet of the search result
17 pub snippet: String,
18 /// The search provider that returned this result
19 pub source: String,
20 /// The rank position in the original results (1-based)
21 pub rank: usize,
22 /// Computed score after merging (optional)
23 #[serde(skip_serializing_if = "Option::is_none")]
24 pub score: Option<f64>,
25 /// Sources that returned this result (after deduplication)
26 #[serde(skip_serializing_if = "Option::is_none")]
27 pub sources: Option<Vec<String>>,
28}
29
30/// Options for search queries
31#[derive(Debug, Clone, Default)]
32pub struct SearchOptions {
33 /// Maximum number of results to return
34 pub limit: Option<usize>,
35 /// Language code (e.g., "en", "de")
36 pub language: Option<String>,
37 /// Region code (e.g., "us", "de")
38 pub region: Option<String>,
39 /// Enable safe search filtering
40 pub safe_search: Option<bool>,
41}
42
43/// Trait that all search providers must implement
44#[async_trait]
45pub trait SearchProvider: Send + Sync {
46 /// Get the provider name
47 fn name(&self) -> &str;
48
49 /// Check if the provider is available/enabled
50 fn is_available(&self) -> bool;
51
52 /// Get the provider weight for reranking
53 fn weight(&self) -> f64;
54
55 /// Set the provider weight for reranking
56 fn set_weight(&mut self, weight: f64);
57
58 /// Enable or disable the provider
59 fn set_enabled(&mut self, enabled: bool);
60
61 /// Perform a search with the provider's default transport.
62 async fn search(
63 &self,
64 query: &str,
65 options: &SearchOptions,
66 ) -> Result<Vec<SearchResult>, SearchError>;
67
68 /// Perform a search with a caller-owned transport.
69 ///
70 /// The default preserves compatibility for third-party providers; built-in
71 /// providers override this method so every network request is routed through
72 /// the supplied transport.
73 async fn search_with_transport(
74 &self,
75 query: &str,
76 options: &SearchOptions,
77 transport: &dyn SearchTransport,
78 ) -> Result<Vec<SearchResult>, SearchError> {
79 let _ = transport;
80 self.search(query, options).await
81 }
82}