use super::types::OrbitClass;
#[derive(Debug, Clone, Default)]
pub struct SbdbQueryParams {
pub fields: Vec<String>,
pub sort: Option<Vec<String>>,
pub limit: Option<u32>,
pub limit_from: Option<u32>,
pub full_prec: bool,
pub sb_kind: Option<String>,
pub sb_group: Option<String>,
pub sb_class: Option<Vec<String>>,
pub sb_ns: Option<String>,
}
impl SbdbQueryParams {
pub fn new() -> Self {
Self::default()
}
pub fn fields(mut self, fields: &[&str]) -> Self {
self.fields = fields.iter().map(|s| s.to_string()).collect();
self
}
pub fn neo_only(mut self) -> Self {
self.sb_group = Some("neo".into());
self
}
pub fn pha_only(mut self) -> Self {
self.sb_group = Some("pha".into());
self
}
pub fn nea_only(mut self) -> Self {
self.sb_group = Some("nea".into());
self
}
pub fn asteroids_only(mut self) -> Self {
self.sb_kind = Some("a".into());
self
}
pub fn comets_only(mut self) -> Self {
self.sb_kind = Some("c".into());
self
}
pub fn orbit_class(mut self, class: OrbitClass) -> Self {
self.sb_class = Some(vec![class.as_code().to_string()]);
self
}
pub fn numbered_only(mut self) -> Self {
self.sb_ns = Some("n".into());
self
}
pub fn limit(mut self, n: u32) -> Self {
self.limit = Some(n);
self
}
pub fn sort(mut self, fields: &[&str]) -> Self {
self.sort = Some(fields.iter().map(|s| s.to_string()).collect());
self
}
pub fn offset(mut self, n: u32) -> Self {
self.limit_from = Some(n);
self
}
pub fn to_query_params(&self) -> Vec<(String, String)> {
let mut params = Vec::new();
if !self.fields.is_empty() {
params.push(("fields".into(), self.fields.join(",")));
}
if let Some(ref sort) = self.sort {
params.push(("sort".into(), sort.join(",")));
}
if let Some(limit) = self.limit {
params.push(("limit".into(), limit.to_string()));
}
if let Some(offset) = self.limit_from {
params.push(("limit-from".into(), offset.to_string()));
}
if self.full_prec {
params.push(("full-prec".into(), "true".into()));
}
if let Some(ref kind) = self.sb_kind {
params.push(("sb-kind".into(), kind.clone()));
}
if let Some(ref group) = self.sb_group {
params.push(("sb-group".into(), group.clone()));
}
if let Some(ref classes) = self.sb_class {
params.push(("sb-class".into(), classes.join(",")));
}
if let Some(ref ns) = self.sb_ns {
params.push(("sb-ns".into(), ns.clone()));
}
params
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashMap;
#[test]
fn test_empty_params() {
let params = SbdbQueryParams::new();
assert!(params.to_query_params().is_empty());
}
#[test]
fn test_fields_and_limit() {
let params = SbdbQueryParams::new()
.fields(&["spkid", "full_name", "e", "a"])
.limit(10);
let query = params.to_query_params();
let map: HashMap<String, String> = query.into_iter().collect();
assert_eq!(map.get("fields").unwrap(), "spkid,full_name,e,a");
assert_eq!(map.get("limit").unwrap(), "10");
}
#[test]
fn test_pha_filter() {
let params = SbdbQueryParams::new().pha_only();
let query = params.to_query_params();
let map: HashMap<String, String> = query.into_iter().collect();
assert_eq!(map.get("sb-group").unwrap(), "pha");
}
#[test]
fn test_orbit_class_filter() {
let params = SbdbQueryParams::new().orbit_class(OrbitClass::Apollo);
let query = params.to_query_params();
let map: HashMap<String, String> = query.into_iter().collect();
assert_eq!(map.get("sb-class").unwrap(), "APO");
}
#[test]
fn test_comets_numbered() {
let params = SbdbQueryParams::new().comets_only().numbered_only();
let query = params.to_query_params();
let map: HashMap<String, String> = query.into_iter().collect();
assert_eq!(map.get("sb-kind").unwrap(), "c");
assert_eq!(map.get("sb-ns").unwrap(), "n");
}
#[test]
fn test_sort_and_offset() {
let params = SbdbQueryParams::new()
.sort(&["H", "-a"])
.offset(100)
.limit(50);
let query = params.to_query_params();
let map: HashMap<String, String> = query.into_iter().collect();
assert_eq!(map.get("sort").unwrap(), "H,-a");
assert_eq!(map.get("limit-from").unwrap(), "100");
assert_eq!(map.get("limit").unwrap(), "50");
}
}