use std::{fmt::Display, str::FromStr};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum VariantType {
Deletion,
Duplication,
Indel,
Insertion,
Inversion,
Snv,
}
impl Display for VariantType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
VariantType::Deletion => write!(f, "deletion"),
VariantType::Duplication => write!(f, "duplication"),
VariantType::Indel => write!(f, "indel"),
VariantType::Insertion => write!(f, "insertion"),
VariantType::Inversion => write!(f, "inversion"),
VariantType::Snv => write!(f, "single nucleotide variant"),
}
}
}
impl FromStr for VariantType {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
"copy number loss" | "deletion" => VariantType::Deletion,
"copy number gain" | "duplication" | "tandem duplication" => VariantType::Duplication,
"indel" => VariantType::Indel,
"insertion" => VariantType::Insertion,
"inversion" => VariantType::Inversion,
"single nucleotide variant" => VariantType::Snv,
_ => anyhow::bail!("Unknown variant type: {}", s),
})
}
}
impl Serialize for VariantType {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl<'de> Deserialize<'de> for VariantType {
fn deserialize<D>(d: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let s = String::deserialize(d)?;
Self::from_str(&s).map_err(serde::de::Error::custom)
}
}
impl From<VariantType> for crate::pbs::annonars::clinvar::v1::minimal::VariantType {
fn from(value: VariantType) -> Self {
match value {
VariantType::Deletion => {
crate::pbs::annonars::clinvar::v1::minimal::VariantType::Deletion
}
VariantType::Duplication => {
crate::pbs::annonars::clinvar::v1::minimal::VariantType::Duplication
}
VariantType::Indel => crate::pbs::annonars::clinvar::v1::minimal::VariantType::Indel,
VariantType::Insertion => {
crate::pbs::annonars::clinvar::v1::minimal::VariantType::Insertion
}
VariantType::Inversion => {
crate::pbs::annonars::clinvar::v1::minimal::VariantType::Inversion
}
VariantType::Snv => crate::pbs::annonars::clinvar::v1::minimal::VariantType::Snv,
}
}
}
impl From<i32> for VariantType {
fn from(value: i32) -> Self {
match value {
0 => VariantType::Deletion,
1 => VariantType::Duplication,
2 => VariantType::Indel,
3 => VariantType::Insertion,
4 => VariantType::Inversion,
5 => VariantType::Snv,
_ => unreachable!(),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum ClinicalSignificance {
Pathogenic,
LikelyPathogenic,
UncertainSignificance,
LikelyBenign,
Benign,
}
impl Display for ClinicalSignificance {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ClinicalSignificance::Pathogenic => write!(f, "pathogenic"),
ClinicalSignificance::LikelyPathogenic => write!(f, "likely pathogenic"),
ClinicalSignificance::UncertainSignificance => write!(f, "uncertain significance"),
ClinicalSignificance::LikelyBenign => write!(f, "likely benign"),
ClinicalSignificance::Benign => write!(f, "benign"),
}
}
}
impl FromStr for ClinicalSignificance {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
"pathogenic" => ClinicalSignificance::Pathogenic,
"likely pathogenic" => ClinicalSignificance::LikelyPathogenic,
"uncertain significance" => ClinicalSignificance::UncertainSignificance,
"likely benign" => ClinicalSignificance::LikelyBenign,
"benign" => ClinicalSignificance::Benign,
_ => anyhow::bail!("Unknown pathogenicity: {}", s),
})
}
}
impl Serialize for ClinicalSignificance {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl<'de> Deserialize<'de> for ClinicalSignificance {
fn deserialize<D>(d: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let s = String::deserialize(d)?;
Self::from_str(&s).map_err(serde::de::Error::custom)
}
}
impl From<ClinicalSignificance>
for crate::pbs::annonars::clinvar::v1::minimal::ClinicalSignificance
{
fn from(value: ClinicalSignificance) -> Self {
match value {
ClinicalSignificance::Pathogenic => {
crate::pbs::annonars::clinvar::v1::minimal::ClinicalSignificance::Pathogenic
}
ClinicalSignificance::LikelyPathogenic => {
crate::pbs::annonars::clinvar::v1::minimal::ClinicalSignificance::LikelyPathogenic
}
ClinicalSignificance::UncertainSignificance => {
crate::pbs::annonars::clinvar::v1::minimal::ClinicalSignificance::UncertainSignificance
}
ClinicalSignificance::LikelyBenign => {
crate::pbs::annonars::clinvar::v1::minimal::ClinicalSignificance::LikelyBenign
}
ClinicalSignificance::Benign => {
crate::pbs::annonars::clinvar::v1::minimal::ClinicalSignificance::Benign
}
}
}
}
impl From<i32> for ClinicalSignificance {
fn from(value: i32) -> Self {
match value {
0 => ClinicalSignificance::Pathogenic,
1 => ClinicalSignificance::LikelyPathogenic,
2 => ClinicalSignificance::UncertainSignificance,
3 => ClinicalSignificance::LikelyBenign,
4 => ClinicalSignificance::Benign,
_ => unreachable!(),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum ReviewStatus {
PracticeGuideline,
ReviewedByExpertPanel,
CriteriaProvidedMultipleSubmittersNoConflicts,
CriteriaProvidedSingleSubmitter,
CriteriaProvidedConflictingInterpretations,
NoAssertionCriteriaProvided,
NoAssertionProvided,
}
impl Display for ReviewStatus {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ReviewStatus::CriteriaProvidedConflictingInterpretations => {
write!(f, "criteria provided, conflicting interpretations")
}
ReviewStatus::CriteriaProvidedMultipleSubmittersNoConflicts => {
write!(f, "criteria provided, multiple submitters, no conflicts")
}
ReviewStatus::CriteriaProvidedSingleSubmitter => {
write!(f, "criteria provided, single submitter")
}
ReviewStatus::NoAssertionCriteriaProvided => {
write!(f, "no assertion criteria provided")
}
ReviewStatus::NoAssertionProvided => write!(f, "no assertion provided"),
ReviewStatus::PracticeGuideline => write!(f, "practice guideline"),
ReviewStatus::ReviewedByExpertPanel => write!(f, "reviewed by expert panel"),
}
}
}
impl FromStr for ReviewStatus {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"criteria provided, conflicting interpretations" => {
Ok(ReviewStatus::CriteriaProvidedConflictingInterpretations)
}
"criteria provided, multiple submitters, no conflicts" => {
Ok(ReviewStatus::CriteriaProvidedMultipleSubmittersNoConflicts)
}
"criteria provided, single submitter" => {
Ok(ReviewStatus::CriteriaProvidedSingleSubmitter)
}
"no assertion criteria provided" => Ok(ReviewStatus::NoAssertionCriteriaProvided),
"no assertion provided" => Ok(ReviewStatus::NoAssertionProvided),
"practice guideline" => Ok(ReviewStatus::PracticeGuideline),
"reviewed by expert panel" => Ok(ReviewStatus::ReviewedByExpertPanel),
_ => anyhow::bail!("Unknown review status: {}", s),
}
}
}
impl Serialize for ReviewStatus {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl<'de> Deserialize<'de> for ReviewStatus {
fn deserialize<D>(d: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let s = String::deserialize(d)?;
Self::from_str(&s).map_err(serde::de::Error::custom)
}
}
impl From<ReviewStatus> for crate::pbs::annonars::clinvar::v1::minimal::ReviewStatus {
fn from(value: ReviewStatus) -> Self {
match value {
ReviewStatus::NoAssertionProvided => crate::pbs::annonars::clinvar::v1::minimal::ReviewStatus::NoAssertionProvided,
ReviewStatus::NoAssertionCriteriaProvided => {
crate::pbs::annonars::clinvar::v1::minimal::ReviewStatus::NoAssertionCriteriaProvided
}
ReviewStatus::CriteriaProvidedConflictingInterpretations => {
crate::pbs::annonars::clinvar::v1::minimal::ReviewStatus::CriteriaProvidedConflictingInterpretations
}
ReviewStatus::CriteriaProvidedSingleSubmitter => {
crate::pbs::annonars::clinvar::v1::minimal::ReviewStatus::CriteriaProvidedSingleSubmitter
}
ReviewStatus::CriteriaProvidedMultipleSubmittersNoConflicts => {
crate::pbs::annonars::clinvar::v1::minimal::ReviewStatus::CriteriaProvidedMultipleSubmittersNoConflicts
}
ReviewStatus::ReviewedByExpertPanel => crate::pbs::annonars::clinvar::v1::minimal::ReviewStatus::ReviewedByExpertPanel,
ReviewStatus::PracticeGuideline => crate::pbs::annonars::clinvar::v1::minimal::ReviewStatus::PracticeGuideline,
}
}
}
impl From<i32> for ReviewStatus {
fn from(value: i32) -> Self {
match value {
0 => ReviewStatus::PracticeGuideline,
1 => ReviewStatus::ReviewedByExpertPanel,
2 => ReviewStatus::CriteriaProvidedMultipleSubmittersNoConflicts,
3 => ReviewStatus::CriteriaProvidedSingleSubmitter,
4 => ReviewStatus::CriteriaProvidedConflictingInterpretations,
5 => ReviewStatus::NoAssertionCriteriaProvided,
6 => ReviewStatus::NoAssertionProvided,
_ => unreachable!(),
}
}
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
pub struct Record {
pub rcv: String,
pub vcv: String,
pub title: String,
pub hgnc_ids: Vec<String>,
pub variant_type: VariantType,
pub clinical_significance: ClinicalSignificance,
pub review_status: ReviewStatus,
pub sequence_location: SequenceLocation,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
pub struct SequenceLocation {
pub assembly: String,
pub chr: String,
pub start: Option<u32>,
pub stop: Option<u32>,
pub reference_allele_vcf: Option<String>,
pub alternate_allele_vcf: Option<String>,
pub inner_start: Option<u32>,
pub inner_stop: Option<u32>,
pub outer_start: Option<u32>,
pub outer_stop: Option<u32>,
}