Skip to main content

htsget_http/
service_info.rs

1use htsget_config::config;
2use htsget_config::types::Format;
3use htsget_search::HtsGet;
4use serde::{Deserialize, Serialize};
5use serde_json::Value;
6use std::collections::HashMap;
7use tracing::debug;
8use tracing::instrument;
9
10use crate::Endpoint;
11
12const READS_FORMATS: [&str; 2] = ["BAM", "CRAM"];
13const VARIANTS_FORMATS: [&str; 2] = ["VCF", "BCF"];
14
15const HTSGET_GROUP: &str = "org.ga4gh";
16const HTSGET_ARTIFACT: &str = "htsget";
17const HTSGET_VERSION: &str = "1.3.0";
18
19/// A struct representing the information that should be present in a service-info response.
20#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
21#[serde(rename_all = "camelCase")]
22pub struct ServiceInfo {
23  #[serde(flatten)]
24  pub fields: HashMap<String, Value>,
25  #[serde(rename = "type")]
26  pub service_type: Type,
27  pub htsget: Htsget,
28}
29
30#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
31#[serde(rename_all = "camelCase")]
32pub struct Type {
33  pub group: String,
34  pub artifact: String,
35  pub version: String,
36}
37
38impl Default for Type {
39  fn default() -> Self {
40    Self {
41      group: HTSGET_GROUP.to_string(),
42      artifact: HTSGET_ARTIFACT.to_string(),
43      version: HTSGET_VERSION.to_string(),
44    }
45  }
46}
47
48#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
49#[serde(rename_all = "camelCase")]
50pub struct Htsget {
51  pub datatype: String,
52  pub formats: Vec<String>,
53  pub fields_parameters_effective: bool,
54  pub tags_parameters_effective: bool,
55}
56
57impl ServiceInfo {
58  pub fn new(
59    endpoint: Endpoint,
60    supported_formats: &[Format],
61    fields_effective: bool,
62    tags_effective: bool,
63    fields: HashMap<String, Value>,
64  ) -> Self {
65    let htsget_info = Htsget {
66      datatype: match endpoint {
67        Endpoint::Reads => "reads",
68        Endpoint::Variants => "variants",
69      }
70      .to_string(),
71      formats: supported_formats
72        .iter()
73        .map(|format| format.to_string())
74        .filter(|format| match endpoint {
75          Endpoint::Reads => READS_FORMATS.contains(&format.as_str()),
76          Endpoint::Variants => VARIANTS_FORMATS.contains(&format.as_str()),
77        })
78        .collect(),
79      fields_parameters_effective: fields_effective,
80      tags_parameters_effective: tags_effective,
81    };
82
83    Self {
84      fields,
85      service_type: Default::default(),
86      htsget: htsget_info,
87    }
88  }
89}
90
91#[instrument(level = "debug", skip_all)]
92pub fn get_service_info_json(
93  endpoint: Endpoint,
94  searcher: impl HtsGet + Send + Sync + 'static,
95  config: config::service_info::ServiceInfo,
96) -> ServiceInfo {
97  debug!(endpoint = ?endpoint,"getting service-info response for endpoint");
98  ServiceInfo::new(
99    endpoint,
100    &searcher.get_supported_formats(),
101    searcher.are_field_parameters_effective(),
102    searcher.are_tag_parameters_effective(),
103    config.into_inner(),
104  )
105}