Engines
9 built-in search engines and the Engine trait for custom implementations
Engines
A3S Search ships with 9 built-in engines and an Engine trait for adding custom search sources.
Engine Trait
Every search engine implements this trait:
#[async_trait]
pub trait Engine: Send + Sync {
fn config(&self) -> &EngineConfig;
async fn search(&self, query: &SearchQuery) -> Result<Vec<SearchResult>>;
// Default implementations derived from config:
fn name(&self) -> &str { &self.config().name }
fn shortcut(&self) -> &str { &self.config().shortcut }
fn weight(&self) -> f64 { self.config().weight }
fn is_enabled(&self) -> bool { self.config().enabled }
}EngineConfig
Prop
Type
Built-in Engines
DuckDuckGo
Privacy-focused search via HTML scraping. No API key required.
use a3s_search::engines::DuckDuckGo;
search.add_engine(DuckDuckGo::new());Prop
Type
Brave Search
Independent search index. HTML scraping, no API key required.
use a3s_search::engines::Brave;
search.add_engine(Brave::new());Prop
Type
Bing
Bing International via HTML scraping with query parameter extraction.
use a3s_search::engines::Bing;
search.add_engine(Bing::new());Prop
Type
Wikipedia
MediaWiki JSON API. Higher weight due to authoritative content. Supports multi-language.
use a3s_search::engines::Wikipedia;
// Default (English)
search.add_engine(Wikipedia::new());
// Chinese Wikipedia
search.add_engine(Wikipedia::with_language("zh"));Prop
Type
Sogou
Chinese search engine (搜狗搜索).
use a3s_search::engines::Sogou;
search.add_engine(Sogou::new());Prop
Type
360 Search
Chinese search engine (360搜索).
use a3s_search::engines::So360;
search.add_engine(So360::new());Prop
Type
Google (headless)
Google Search via headless Chrome. Higher weight (1.5) due to result quality.
#[cfg(feature = "headless")]
use a3s_search::engines::Google;
search.add_engine(Google::new(fetcher));Prop
Type
Baidu (headless)
Chinese search engine (百度搜索) via headless Chrome.
#[cfg(feature = "headless")]
use a3s_search::engines::Baidu;
search.add_engine(Baidu::new(fetcher));Prop
Type
Bing China (headless)
Chinese Bing (必应中国) via headless Chrome.
#[cfg(feature = "headless")]
use a3s_search::engines::BingChina;
search.add_engine(BingChina::new(fetcher));Prop
Type
Engine Shortcuts
Prop
Type
Custom Engine
Implement the Engine trait to add any search source:
use a3s_search::*;
use async_trait::async_trait;
struct MyApiEngine {
config: EngineConfig,
api_key: String,
}
impl MyApiEngine {
fn new(api_key: String) -> Self {
Self {
config: EngineConfig {
name: "My API".into(),
shortcut: "myapi".into(),
categories: vec![EngineCategory::General],
weight: 1.0,
timeout: 5,
enabled: true,
paging: true,
safesearch: false,
},
api_key,
}
}
}
#[async_trait]
impl Engine for MyApiEngine {
fn config(&self) -> &EngineConfig { &self.config }
async fn search(&self, query: &SearchQuery) -> Result<Vec<SearchResult>> {
let client = reqwest::Client::new();
let resp: serde_json::Value = client
.get("https://api.example.com/search")
.query(&[("q", &query.query), ("key", &self.api_key)])
.send().await.map_err(SearchError::Http)?
.json().await.map_err(SearchError::Http)?;
let mut results = vec![];
if let Some(items) = resp["items"].as_array() {
for (i, item) in items.iter().enumerate() {
results.push(
SearchResult::new(
item["url"].as_str().unwrap_or_default(),
item["title"].as_str().unwrap_or_default(),
item["snippet"].as_str().unwrap_or_default(),
)
.with_engine("myapi", (i + 1) as u32)
);
}
}
Ok(results)
}
}Custom Engine Weight
Override the default weight for any built-in engine:
use a3s_search::{EngineConfig, engines::Wikipedia};
let wiki = Wikipedia::new().with_config(EngineConfig {
name: "Wikipedia".to_string(),
shortcut: "wiki".to_string(),
weight: 1.5,
..Default::default()
});
search.add_engine(wiki);