1use std::fmt::Display;
8
9use crate::{parser::ds::*, sequences::aa_to_aa3};
10
11pub struct NoRef<'a, T>(pub &'a T)
13where
14 T: Display;
15
16impl<T> NoRef<'_, T>
17where
18 T: Display,
19{
20 pub fn inner(&self) -> &T {
21 match self {
22 NoRef(value) => value,
23 }
24 }
25}
26
27impl<T> Display for Mu<T>
28where
29 T: Display,
30{
31 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32 match self {
33 Mu::Certain(value) => write!(f, "{value}"),
34 Mu::Uncertain(value) => write!(f, "({value})"),
35 }
36 }
37}
38
39impl<'a, T> Display for NoRef<'a, Mu<T>>
40where
41 T: Display,
42 NoRef<'a, T>: std::fmt::Display,
43{
44 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45 match self {
46 NoRef(Mu::Certain(value)) => write!(f, "{}", NoRef(value)),
47 NoRef(Mu::Uncertain(value)) => write!(f, "({})", NoRef(value)),
48 }
49 }
50}
51
52impl Display for GeneSymbol {
53 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
54 write!(f, "{}", self.value)
55 }
56}
57
58impl Display for NaEdit {
59 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
60 match self {
61 NaEdit::RefAlt {
62 reference,
63 alternative,
64 } => match (reference.len(), alternative.len()) {
65 (0, 0) => write!(f, "="),
66 (1, 1) => {
67 if reference == alternative {
68 write!(f, "=")
69 } else {
70 write!(f, "{reference}>{alternative}")
71 }
72 }
73 (0, _) => write!(f, "delins{alternative}"),
74 (_, 0) => write!(f, "del{reference}ins"),
75 (_, _) => {
76 if reference == alternative {
77 write!(f, "=")
78 } else {
79 write!(f, "del{reference}ins{alternative}")
80 }
81 }
82 },
83 NaEdit::NumAlt { count, alternative } => match (count, alternative.len()) {
84 (0, 0) => write!(f, "="),
85 (0, _) => write!(f, "delins{alternative}"),
86 (_, 0) => write!(f, "del{count}ins"),
87 (_, _) => write!(f, "del{count}ins{alternative}"),
88 },
89 NaEdit::DelRef { reference } => write!(f, "del{reference}"),
90 NaEdit::DelNum { count } => write!(f, "del{count}"),
91 NaEdit::Ins { alternative } => write!(f, "ins{alternative}"),
92 NaEdit::Dup { reference } => write!(f, "dup{reference}"),
93 NaEdit::InvRef { reference } => write!(f, "inv{reference}"),
94 NaEdit::InvNum { count } => write!(f, "inv{count}"),
95 }
96 }
97}
98
99impl Display for NoRef<'_, NaEdit> {
100 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
101 match self {
102 NoRef(NaEdit::RefAlt {
103 reference,
104 alternative,
105 }) => match (reference.len(), alternative.len()) {
106 (0, 0) => write!(f, "="),
107 (1, 1) => {
108 if reference == alternative {
109 write!(f, "=")
110 } else {
111 write!(f, "{reference}>{alternative}")
112 }
113 }
114 (_, 0) => write!(f, "delins"),
115 (_, _) => {
116 if reference == alternative {
117 write!(f, "=")
118 } else {
119 write!(f, "delins{alternative}")
120 }
121 }
122 },
123 NoRef(NaEdit::NumAlt { count, alternative }) => match (count, alternative.len()) {
124 (0, 0) => write!(f, "="),
125 (_, 0) => write!(f, "delins"),
126 (_, _) => write!(f, "delins{alternative}"),
127 },
128 NoRef(NaEdit::DelRef { .. }) | NoRef(NaEdit::DelNum { .. }) => write!(f, "del"),
129 NoRef(NaEdit::Ins { alternative }) => write!(f, "ins{alternative}"),
130 NoRef(NaEdit::Dup { .. }) => write!(f, "dup"),
131 NoRef(NaEdit::InvRef { .. }) | NoRef(NaEdit::InvNum { .. }) => write!(f, "inv"),
132 }
133 }
134}
135
136impl Display for UncertainLengthChange {
137 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
138 match self {
139 UncertainLengthChange::None => write!(f, ""),
140 UncertainLengthChange::Unknown => write!(f, "?"),
141 UncertainLengthChange::Known(count) => write!(f, "{count}"),
142 }
143 }
144}
145
146impl Display for Accession {
147 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
148 write!(f, "{}", self.value)
149 }
150}
151
152impl Display for ProteinEdit {
153 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
154 match self {
155 ProteinEdit::Fs {
156 alternative,
157 terminal,
158 length,
159 } => match (alternative, terminal, length) {
160 (None, None, UncertainLengthChange::None) => write!(f, "fsTer"),
161 (None, None, UncertainLengthChange::Unknown) => write!(f, "fsTer?"),
162 (None, None, UncertainLengthChange::Known(count)) => write!(f, "fsTer{count}"),
163 (Some(alt), None, UncertainLengthChange::None) => write!(f, "{alt}fsTer"),
164 (Some(alt), None, UncertainLengthChange::Unknown) => write!(f, "{alt}fsTer?"),
165 (Some(alt), None, UncertainLengthChange::Known(count)) => {
166 let alt = aa_to_aa3(alt).expect("aa_to_aa3 conversion failed");
167 write!(f, "{alt}fsTer{count}")
168 }
169 (None, Some(ter), UncertainLengthChange::None) => {
170 let mut ter = aa_to_aa3(ter).expect("aa_to_aa3 conversion failed");
171 if ter.is_empty() {
172 ter = "Ter".to_string();
173 }
174 write!(f, "fs{ter}")
175 }
176 (None, Some(ter), UncertainLengthChange::Unknown) => {
177 let mut ter = aa_to_aa3(ter).expect("aa_to_aa3 conversion failed");
178 if ter.is_empty() {
179 ter = "Ter".to_string();
180 }
181 write!(f, "fs{ter}?")
182 }
183 (None, Some(ter), UncertainLengthChange::Known(count)) => {
184 let mut ter = aa_to_aa3(ter).expect("aa_to_aa3 conversion failed");
185 if ter.is_empty() {
186 ter = "Ter".to_string();
187 }
188 write!(f, "fs{ter}{count}")
189 }
190 (Some(alt), Some(ter), UncertainLengthChange::None) => {
191 let alt = aa_to_aa3(alt).expect("aa_to_aa3 conversion failed");
192 let mut ter = aa_to_aa3(ter).expect("aa_to_aa3 conversion failed");
193 if ter.is_empty() {
194 ter = "Ter".to_string();
195 }
196 write!(f, "{alt}fs{ter}")
197 }
198 (Some(alt), Some(ter), UncertainLengthChange::Unknown) => {
199 let alt = aa_to_aa3(alt).expect("aa_to_aa3 conversion failed");
200 let mut ter = aa_to_aa3(ter).expect("aa_to_aa3 conversion failed");
201 if ter.is_empty() {
202 ter = "Ter".to_string();
203 }
204 write!(f, "{alt}fs{ter}?")
205 }
206 (Some(alt), Some(ter), UncertainLengthChange::Known(count)) => {
207 let alt = aa_to_aa3(alt).expect("aa_to_aa3 conversion failed");
208 let mut ter = aa_to_aa3(ter).expect("aa_to_aa3 conversion failed");
209 if ter.is_empty() {
210 ter = "Ter".to_string();
211 }
212 write!(f, "{alt}fs{ter}{count}")
213 }
214 },
215 ProteinEdit::Ext {
216 aa_ext,
217 ext_aa,
218 change,
219 } => match (aa_ext, ext_aa, change) {
220 (None, None, UncertainLengthChange::None) => write!(f, "ext"),
221 (None, None, UncertainLengthChange::Unknown) => write!(f, "ext?"),
222 (None, None, UncertainLengthChange::Known(count)) => write!(f, "ext{count}"),
223 (Some(alt), None, UncertainLengthChange::None) => {
224 let alt = aa_to_aa3(alt).expect("aa_to_aa3 conversion failed");
225 write!(f, "{alt}ext")
226 }
227 (Some(alt), None, UncertainLengthChange::Unknown) => {
228 let alt = aa_to_aa3(alt).expect("aa_to_aa3 conversion failed");
229 write!(f, "{alt}ext?")
230 }
231 (Some(alt), None, UncertainLengthChange::Known(count)) => {
232 let alt = aa_to_aa3(alt).expect("aa_to_aa3 conversion failed");
233 write!(f, "{alt}ext{count}")
234 }
235 (None, Some(ter), UncertainLengthChange::None) => write!(f, "ext{ter}"),
236 (None, Some(ter), UncertainLengthChange::Unknown) => write!(f, "ext{ter}?"),
237 (None, Some(ter), UncertainLengthChange::Known(count)) => {
238 let ter = aa_to_aa3(ter).expect("aa_to_aa3 conversion failed");
239 write!(f, "ext{ter}{count}")
240 }
241 (Some(alt), Some(ter), UncertainLengthChange::None) => {
242 let alt = aa_to_aa3(alt).expect("aa_to_aa3 conversion failed");
243 let ter = aa_to_aa3(ter).expect("aa_to_aa3 conversion failed");
244 write!(f, "{alt}ext{ter}")
245 }
246 (Some(alt), Some(ter), UncertainLengthChange::Unknown) => {
247 let alt = aa_to_aa3(alt).expect("aa_to_aa3 conversion failed");
248 let ter = aa_to_aa3(ter).expect("aa_to_aa3 conversion failed");
249 write!(f, "{alt}ext{ter}?")
250 }
251 (Some(alt), Some(ter), UncertainLengthChange::Known(count)) => {
252 let alt = aa_to_aa3(alt).expect("aa_to_aa3 conversion failed");
253 let ter = aa_to_aa3(ter).expect("aa_to_aa3 conversion failed");
254 write!(f, "{alt}ext{ter}{count}")
255 }
256 },
257 ProteinEdit::Subst { alternative } => {
258 let alternative = aa_to_aa3(alternative).expect("aa_to_aa3 conversion failed");
259 if alternative.is_empty() {
260 write!(f, "=")
261 } else {
262 write!(f, "{alternative}")
263 }
264 }
265 ProteinEdit::DelIns { alternative } => {
266 let alternative = aa_to_aa3(alternative).expect("aa_to_aa3 conversion failed");
267 write!(f, "delins{alternative}")
268 }
269 ProteinEdit::Ins { alternative } => {
270 let alternative = aa_to_aa3(alternative).expect("aa_to_aa3 conversion failed");
271 write!(f, "ins{alternative}")
272 }
273 ProteinEdit::Del => write!(f, "del"),
274 ProteinEdit::Dup => write!(f, "dup"),
275 ProteinEdit::Ident => write!(f, "="),
276 }
277 }
278}
279
280impl Display for ProtPos {
281 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
282 let aa = aa_to_aa3(&self.aa).expect("aa_to_aa3 conversion failed");
283 write!(f, "{aa}{}", self.number)
284 }
285}
286
287impl Display for ProtInterval {
288 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
289 write!(f, "{}", self.start)?;
290 if self.start != self.end {
291 write!(f, "_{}", self.end)?;
292 }
293 Ok(())
294 }
295}
296
297impl Display for ProtLocEdit {
298 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
299 match self {
301 ProtLocEdit::Ordinary { loc, edit } => write!(f, "{loc}{edit}"),
302 ProtLocEdit::NoChange => write!(f, "="),
303 ProtLocEdit::NoChangeUncertain => write!(f, "(=)"),
304 ProtLocEdit::NoProtein => write!(f, "0"),
305 ProtLocEdit::NoProteinUncertain => write!(f, "0?"),
306 ProtLocEdit::Unknown => write!(f, "?"),
307 ProtLocEdit::InitiationUncertain => write!(f, "Met1?"),
308 }
309 }
310}
311
312impl Display for NoRef<'_, ProtLocEdit> {
313 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
314 self.inner().fmt(f)
315 }
316}
317
318impl Display for CdsLocEdit {
319 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
320 write!(f, "{}{}", self.loc, self.edit)
321 }
322}
323
324impl Display for NoRef<'_, CdsLocEdit> {
325 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
326 write!(f, "{}{}", self.inner().loc, NoRef(&self.inner().edit))
327 }
328}
329
330impl Display for CdsInterval {
331 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
332 write!(f, "{}", self.start)?;
333 if self.start != self.end {
334 write!(f, "_{}", self.end)?;
335 }
336 Ok(())
337 }
338}
339
340impl Display for CdsPos {
341 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
342 if self.cds_from == CdsFrom::End {
343 write!(f, "*")?;
344 }
345
346 write!(f, "{}", self.base)?;
347
348 if let Some(offset) = self.offset {
349 if offset > 0 {
350 write!(f, "+")?;
351 }
352 write!(f, "{offset}")?;
353 }
354
355 Ok(())
356 }
357}
358
359impl Display for TxLocEdit {
360 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
361 write!(f, "{}{}", self.loc, self.edit)
362 }
363}
364
365impl Display for NoRef<'_, TxLocEdit> {
366 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
367 write!(f, "{}{}", self.inner().loc, NoRef(&self.inner().edit))
368 }
369}
370
371impl Display for TxInterval {
372 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
373 write!(f, "{}", self.start)?;
374 if self.start != self.end {
375 write!(f, "_{}", self.end)?;
376 }
377 Ok(())
378 }
379}
380
381impl Display for TxPos {
382 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
383 write!(f, "{}", self.base)?;
384
385 if let Some(offset) = self.offset {
386 if offset > 0 {
387 write!(f, "+")?;
388 }
389 write!(f, "{offset}")?;
390 }
391
392 Ok(())
393 }
394}
395
396impl Display for RnaLocEdit {
397 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
398 write!(f, "{}{}", self.loc, self.edit)
399 }
400}
401
402impl Display for NoRef<'_, RnaLocEdit> {
403 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
404 write!(f, "{}{}", self.inner().loc, NoRef(&self.inner().edit))
405 }
406}
407
408impl Display for RnaInterval {
409 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
410 write!(f, "{}", self.start)?;
411 if self.start != self.end {
412 write!(f, "_{}", self.end)?;
413 }
414 Ok(())
415 }
416}
417
418impl Display for RnaPos {
419 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
420 write!(f, "{}", self.base)?;
421
422 if let Some(offset) = self.offset {
423 if offset > 0 {
424 write!(f, "+")?;
425 }
426 write!(f, "{offset}")?;
427 }
428
429 Ok(())
430 }
431}
432
433impl Display for GenomeLocEdit {
434 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
435 write!(f, "{}{}", self.loc, self.edit)
436 }
437}
438
439impl Display for NoRef<'_, GenomeLocEdit> {
440 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
441 write!(f, "{}{}", self.inner().loc, NoRef(&self.inner().edit))
442 }
443}
444
445impl Display for GenomeInterval {
446 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
447 match self.start {
448 Some(begin) => write!(f, "{begin}")?,
449 None => write!(f, "?")?,
450 }
451 if self.start != self.end {
452 match self.end {
453 Some(end) => write!(f, "_{end}")?,
454 None => write!(f, "_?")?,
455 }
456 }
457 Ok(())
458 }
459}
460
461impl Display for MtLocEdit {
462 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
463 write!(f, "{}{}", self.loc, self.edit)
464 }
465}
466
467impl Display for NoRef<'_, MtLocEdit> {
468 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
469 write!(f, "{}{}", self.inner().loc, NoRef(&self.inner().edit))
470 }
471}
472
473impl Display for MtInterval {
474 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
475 match self.start {
476 Some(begin) => write!(f, "{begin}")?,
477 None => write!(f, "?")?,
478 }
479 if self.start != self.end {
480 match self.end {
481 Some(end) => write!(f, "_{end}")?,
482 None => write!(f, "_?")?,
483 }
484 }
485 Ok(())
486 }
487}
488
489impl Display for HgvsVariant {
490 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
491 match self {
492 HgvsVariant::CdsVariant {
493 accession,
494 gene_symbol,
495 loc_edit,
496 } => {
497 write!(f, "{accession}")?;
498 if let Some(gene_symbol) = gene_symbol {
499 write!(f, "({gene_symbol})")?;
500 }
501 write!(f, ":c.{loc_edit}")
502 }
503 HgvsVariant::GenomeVariant {
504 accession,
505 gene_symbol,
506 loc_edit,
507 } => {
508 write!(f, "{accession}")?;
509 if let Some(gene_symbol) = gene_symbol {
510 write!(f, "({gene_symbol})")?;
511 }
512 write!(f, ":g.{loc_edit}")
513 }
514 HgvsVariant::MtVariant {
515 accession,
516 gene_symbol,
517 loc_edit,
518 } => {
519 write!(f, "{accession}")?;
520 if let Some(gene_symbol) = gene_symbol {
521 write!(f, "({gene_symbol})")?;
522 }
523 write!(f, ":m.{loc_edit}")
524 }
525 HgvsVariant::TxVariant {
526 accession,
527 gene_symbol,
528 loc_edit,
529 } => {
530 write!(f, "{accession}")?;
531 if let Some(gene_symbol) = gene_symbol {
532 write!(f, "({gene_symbol})")?;
533 }
534 write!(f, ":n.{loc_edit}")
535 }
536 HgvsVariant::ProtVariant {
537 accession,
538 gene_symbol,
539 loc_edit,
540 } => {
541 write!(f, "{accession}")?;
542 if let Some(gene_symbol) = gene_symbol {
543 write!(f, "({gene_symbol})")?;
544 }
545 write!(f, ":p.{loc_edit}")
546 }
547 HgvsVariant::RnaVariant {
548 accession,
549 gene_symbol,
550 loc_edit,
551 } => {
552 write!(f, "{accession}")?;
553 if let Some(gene_symbol) = gene_symbol {
554 write!(f, "({gene_symbol})")?;
555 }
556 write!(f, ":r.{loc_edit}")
557 }
558 }
559 }
560}
561
562impl Display for NoRef<'_, HgvsVariant> {
563 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
564 match self {
565 NoRef(HgvsVariant::CdsVariant {
566 accession,
567 gene_symbol,
568 loc_edit,
569 }) => {
570 write!(f, "{accession}")?;
571 if let Some(gene_symbol) = gene_symbol {
572 write!(f, "({gene_symbol})")?;
573 }
574 write!(f, ":c.{}", NoRef(loc_edit))
575 }
576 NoRef(HgvsVariant::GenomeVariant {
577 accession,
578 gene_symbol,
579 loc_edit,
580 }) => {
581 write!(f, "{accession}")?;
582 if let Some(gene_symbol) = gene_symbol {
583 write!(f, "({gene_symbol})")?;
584 }
585 write!(f, ":g.{}", NoRef(loc_edit))
586 }
587 NoRef(HgvsVariant::MtVariant {
588 accession,
589 gene_symbol,
590 loc_edit,
591 }) => {
592 write!(f, "{accession}")?;
593 if let Some(gene_symbol) = gene_symbol {
594 write!(f, "({gene_symbol})")?;
595 }
596 write!(f, ":m.{}", NoRef(loc_edit))
597 }
598 NoRef(HgvsVariant::TxVariant {
599 accession,
600 gene_symbol,
601 loc_edit,
602 }) => {
603 write!(f, "{accession}")?;
604 if let Some(gene_symbol) = gene_symbol {
605 write!(f, "({gene_symbol})")?;
606 }
607 write!(f, ":n.{}", NoRef(loc_edit))
608 }
609 NoRef(HgvsVariant::ProtVariant {
610 accession,
611 gene_symbol,
612 loc_edit,
613 }) => {
614 write!(f, "{accession}")?;
615 if let Some(gene_symbol) = gene_symbol {
616 write!(f, "({gene_symbol})")?;
617 }
618 write!(f, ":p.{}", NoRef(loc_edit))
619 }
620 NoRef(HgvsVariant::RnaVariant {
621 accession,
622 gene_symbol,
623 loc_edit,
624 }) => {
625 write!(f, "{accession}")?;
626 if let Some(gene_symbol) = gene_symbol {
627 write!(f, "({gene_symbol})")?;
628 }
629 write!(f, ":r.{}", NoRef(loc_edit))
630 }
631 }
632 }
633}
634
635#[cfg(test)]
636mod test {
637 use anyhow::Error;
638 use std::{
639 fs::File,
640 io::{BufRead, BufReader},
641 str::FromStr,
642 };
643
644 use pretty_assertions::assert_eq;
645
646 use crate::parser::{
647 Accession, CdsFrom, CdsInterval, CdsLocEdit, CdsPos, GeneSymbol, GenomeInterval,
648 GenomeLocEdit, HgvsVariant, MtInterval, MtLocEdit, Mu, NaEdit, ProtInterval, ProtLocEdit,
649 ProtPos, ProteinEdit, RnaInterval, RnaLocEdit, RnaPos, TxInterval, TxLocEdit, TxPos,
650 UncertainLengthChange,
651 };
652
653 #[test]
654 fn mu() {
655 assert_eq!(format!("{}", Mu::Certain(42)), "42".to_string());
656 assert_eq!(format!("{}", Mu::Uncertain(42)), "(42)".to_string());
657 }
658
659 #[test]
660 fn gene_symbol() {
661 assert_eq!(
662 format!(
663 "{}",
664 GeneSymbol {
665 value: "TTN".to_string()
666 }
667 ),
668 "TTN".to_string()
669 );
670 }
671
672 #[test]
673 fn na_edit_ref_alt() {
674 assert_eq!(
675 format!(
676 "{}",
677 NaEdit::RefAlt {
678 reference: "".to_string(),
679 alternative: "".to_string()
680 }
681 ),
682 "=".to_string()
683 );
684
685 assert_eq!(
686 format!(
687 "{}",
688 NaEdit::RefAlt {
689 reference: "C".to_string(),
690 alternative: "T".to_string()
691 }
692 ),
693 "C>T".to_string()
694 );
695
696 assert_eq!(
697 format!(
698 "{}",
699 NaEdit::RefAlt {
700 reference: "CC".to_string(),
701 alternative: "T".to_string()
702 }
703 ),
704 "delCCinsT".to_string()
705 );
706
707 assert_eq!(
708 format!(
709 "{}",
710 NaEdit::RefAlt {
711 reference: "C".to_string(),
712 alternative: "".to_string()
713 }
714 ),
715 "delCins".to_string()
716 );
717
718 assert_eq!(
719 format!(
720 "{}",
721 NaEdit::RefAlt {
722 reference: "".to_string(),
723 alternative: "C".to_string()
724 }
725 ),
726 "delinsC".to_string()
727 );
728 }
729
730 #[test]
731 fn na_edit_num_alt() {
732 assert_eq!(
733 format!(
734 "{}",
735 NaEdit::NumAlt {
736 count: 0,
737 alternative: "".to_string()
738 }
739 ),
740 "=".to_string()
741 );
742
743 assert_eq!(
744 format!(
745 "{}",
746 NaEdit::NumAlt {
747 count: 0,
748 alternative: "T".to_string()
749 }
750 ),
751 "delinsT".to_string()
752 );
753 assert_eq!(
754 format!(
755 "{}",
756 NaEdit::NumAlt {
757 count: 3,
758 alternative: "".to_string()
759 }
760 ),
761 "del3ins".to_string()
762 );
763
764 assert_eq!(
765 format!(
766 "{}",
767 NaEdit::NumAlt {
768 count: 3,
769 alternative: "T".to_string()
770 }
771 ),
772 "del3insT".to_string()
773 );
774 }
775
776 #[test]
777 fn na_edit_del_ref() {
778 assert_eq!(
779 format!(
780 "{}",
781 NaEdit::DelRef {
782 reference: "T".to_string()
783 }
784 ),
785 "delT".to_string()
786 );
787 }
788
789 #[test]
790 fn na_edit_del_num() {
791 assert_eq!(
792 format!("{}", NaEdit::DelNum { count: 3 }),
793 "del3".to_string()
794 );
795 }
796
797 #[test]
798 fn na_edit_ins() {
799 assert_eq!(
800 format!(
801 "{}",
802 NaEdit::Ins {
803 alternative: "T".to_string()
804 }
805 ),
806 "insT".to_string()
807 );
808 }
809
810 #[test]
811 fn na_edit_dup() {
812 assert_eq!(
813 format!(
814 "{}",
815 NaEdit::Dup {
816 reference: "T".to_string()
817 }
818 ),
819 "dupT".to_string()
820 );
821 }
822
823 #[test]
824 fn na_edit_inv_ref() {
825 assert_eq!(
826 format!(
827 "{}",
828 NaEdit::InvRef {
829 reference: "T".to_string()
830 }
831 ),
832 "invT".to_string()
833 );
834 }
835
836 #[test]
837 fn na_edit_inv_num() {
838 assert_eq!(
839 format!("{}", NaEdit::InvNum { count: 3 }),
840 "inv3".to_string()
841 );
842 }
843
844 #[test]
845 fn uncertain_length_change() {
846 assert_eq!(format!("{}", UncertainLengthChange::None), "".to_string(),);
847 assert_eq!(
848 format!("{}", UncertainLengthChange::Unknown),
849 "?".to_string(),
850 );
851 assert_eq!(
852 format!("{}", UncertainLengthChange::Known(42)),
853 "42".to_string(),
854 );
855 }
856
857 #[test]
858 fn accession() {
859 assert_eq!(
860 format!(
861 "{}",
862 Accession {
863 value: "TTN".to_string()
864 }
865 ),
866 "TTN".to_string()
867 )
868 }
869
870 #[test]
871 fn protein_edit_fs() {
872 assert_eq!(
873 format!(
874 "{}",
875 ProteinEdit::Fs {
876 alternative: None,
877 terminal: None,
878 length: UncertainLengthChange::None,
879 }
880 ),
881 "fsTer".to_string(),
882 );
883 assert_eq!(
884 format!(
885 "{}",
886 ProteinEdit::Fs {
887 alternative: None,
888 terminal: None,
889 length: UncertainLengthChange::Unknown,
890 }
891 ),
892 "fsTer?".to_string(),
893 );
894 assert_eq!(
895 format!(
896 "{}",
897 ProteinEdit::Fs {
898 alternative: None,
899 terminal: None,
900 length: UncertainLengthChange::Known(42),
901 }
902 ),
903 "fsTer42".to_string(),
904 );
905
906 assert_eq!(
907 format!(
908 "{}",
909 ProteinEdit::Fs {
910 alternative: Some("Leu".to_string()),
911 terminal: None,
912 length: UncertainLengthChange::None,
913 }
914 ),
915 "LeufsTer".to_string(),
916 );
917 assert_eq!(
918 format!(
919 "{}",
920 ProteinEdit::Fs {
921 alternative: Some("Leu".to_string()),
922 terminal: None,
923 length: UncertainLengthChange::Unknown,
924 }
925 ),
926 "LeufsTer?".to_string(),
927 );
928 assert_eq!(
929 format!(
930 "{}",
931 ProteinEdit::Fs {
932 alternative: Some("Leu".to_string()),
933 terminal: None,
934 length: UncertainLengthChange::Known(42),
935 }
936 ),
937 "LeufsTer42".to_string(),
938 );
939
940 assert_eq!(
941 format!(
942 "{}",
943 ProteinEdit::Fs {
944 alternative: None,
945 terminal: Some("Ter".to_string()),
946 length: UncertainLengthChange::None,
947 }
948 ),
949 "fsTer".to_string(),
950 );
951 assert_eq!(
952 format!(
953 "{}",
954 ProteinEdit::Fs {
955 alternative: None,
956 terminal: Some("Ter".to_string()),
957 length: UncertainLengthChange::Unknown,
958 }
959 ),
960 "fsTer?".to_string(),
961 );
962 assert_eq!(
963 format!(
964 "{}",
965 ProteinEdit::Fs {
966 alternative: None,
967 terminal: Some("Ter".to_string()),
968 length: UncertainLengthChange::Known(42),
969 }
970 ),
971 "fsTer42".to_string(),
972 );
973
974 assert_eq!(
975 format!(
976 "{}",
977 ProteinEdit::Fs {
978 alternative: Some("Leu".to_string()),
979 terminal: Some("Ter".to_string()),
980 length: UncertainLengthChange::None,
981 }
982 ),
983 "LeufsTer".to_string(),
984 );
985 assert_eq!(
986 format!(
987 "{}",
988 ProteinEdit::Fs {
989 alternative: Some("Leu".to_string()),
990 terminal: Some("Ter".to_string()),
991 length: UncertainLengthChange::Unknown,
992 }
993 ),
994 "LeufsTer?".to_string(),
995 );
996 assert_eq!(
997 format!(
998 "{}",
999 ProteinEdit::Fs {
1000 alternative: Some("Leu".to_string()),
1001 terminal: Some("Ter".to_string()),
1002 length: UncertainLengthChange::Known(42),
1003 }
1004 ),
1005 "LeufsTer42".to_string(),
1006 );
1007 }
1008
1009 #[test]
1010 fn protein_edit_ext() {
1011 assert_eq!(
1012 format!(
1013 "{}",
1014 ProteinEdit::Ext {
1015 aa_ext: None,
1016 ext_aa: None,
1017 change: UncertainLengthChange::None,
1018 }
1019 ),
1020 "ext".to_string(),
1021 );
1022 assert_eq!(
1023 format!(
1024 "{}",
1025 ProteinEdit::Ext {
1026 aa_ext: None,
1027 ext_aa: None,
1028 change: UncertainLengthChange::Unknown,
1029 }
1030 ),
1031 "ext?".to_string(),
1032 );
1033 assert_eq!(
1034 format!(
1035 "{}",
1036 ProteinEdit::Ext {
1037 aa_ext: None,
1038 ext_aa: None,
1039 change: UncertainLengthChange::Known(42),
1040 }
1041 ),
1042 "ext42".to_string(),
1043 );
1044
1045 assert_eq!(
1046 format!(
1047 "{}",
1048 ProteinEdit::Ext {
1049 aa_ext: Some("Leu".to_string()),
1050 ext_aa: None,
1051 change: UncertainLengthChange::None,
1052 }
1053 ),
1054 "Leuext".to_string(),
1055 );
1056 assert_eq!(
1057 format!(
1058 "{}",
1059 ProteinEdit::Ext {
1060 aa_ext: Some("Leu".to_string()),
1061 ext_aa: None,
1062 change: UncertainLengthChange::Unknown,
1063 }
1064 ),
1065 "Leuext?".to_string(),
1066 );
1067 assert_eq!(
1068 format!(
1069 "{}",
1070 ProteinEdit::Ext {
1071 aa_ext: Some("Leu".to_string()),
1072 ext_aa: None,
1073 change: UncertainLengthChange::Known(42),
1074 }
1075 ),
1076 "Leuext42".to_string(),
1077 );
1078
1079 assert_eq!(
1080 format!(
1081 "{}",
1082 ProteinEdit::Ext {
1083 aa_ext: None,
1084 ext_aa: Some("Thr".to_string()),
1085 change: UncertainLengthChange::None,
1086 }
1087 ),
1088 "extThr".to_string(),
1089 );
1090 assert_eq!(
1091 format!(
1092 "{}",
1093 ProteinEdit::Ext {
1094 aa_ext: None,
1095 ext_aa: Some("Thr".to_string()),
1096 change: UncertainLengthChange::Unknown,
1097 }
1098 ),
1099 "extThr?".to_string(),
1100 );
1101 assert_eq!(
1102 format!(
1103 "{}",
1104 ProteinEdit::Ext {
1105 aa_ext: None,
1106 ext_aa: Some("Thr".to_string()),
1107 change: UncertainLengthChange::Known(42),
1108 }
1109 ),
1110 "extThr42".to_string(),
1111 );
1112
1113 assert_eq!(
1114 format!(
1115 "{}",
1116 ProteinEdit::Ext {
1117 aa_ext: Some("Leu".to_string()),
1118 ext_aa: Some("Thr".to_string()),
1119 change: UncertainLengthChange::None,
1120 }
1121 ),
1122 "LeuextThr".to_string(),
1123 );
1124 assert_eq!(
1125 format!(
1126 "{}",
1127 ProteinEdit::Ext {
1128 aa_ext: Some("Leu".to_string()),
1129 ext_aa: Some("Thr".to_string()),
1130 change: UncertainLengthChange::Unknown,
1131 }
1132 ),
1133 "LeuextThr?".to_string(),
1134 );
1135 assert_eq!(
1136 format!(
1137 "{}",
1138 ProteinEdit::Ext {
1139 aa_ext: Some("Leu".to_string()),
1140 ext_aa: Some("Thr".to_string()),
1141 change: UncertainLengthChange::Known(42),
1142 }
1143 ),
1144 "LeuextThr42".to_string(),
1145 );
1146 }
1147
1148 #[test]
1149 fn protein_edit_subst() {
1150 assert_eq!(
1151 format!(
1152 "{}",
1153 ProteinEdit::Subst {
1154 alternative: "Leu".to_string()
1155 }
1156 ),
1157 "Leu".to_string(),
1158 );
1159 }
1160
1161 #[test]
1162 fn protein_edit_del_ins() {
1163 assert_eq!(
1164 format!(
1165 "{}",
1166 ProteinEdit::DelIns {
1167 alternative: "Leu".to_string()
1168 }
1169 ),
1170 "delinsLeu".to_string(),
1171 );
1172 }
1173
1174 #[test]
1175 fn protein_edit_ins() {
1176 assert_eq!(
1177 format!(
1178 "{}",
1179 ProteinEdit::Ins {
1180 alternative: "Leu".to_string()
1181 }
1182 ),
1183 "insLeu".to_string(),
1184 );
1185 }
1186
1187 #[test]
1188 fn protein_edit_del() {
1189 assert_eq!(format!("{}", ProteinEdit::Del), "del".to_string(),);
1190 }
1191
1192 #[test]
1193 fn protein_edit_dup() {
1194 assert_eq!(format!("{}", ProteinEdit::Dup), "dup".to_string(),);
1195 }
1196
1197 #[test]
1198 fn protein_edit_ident() {
1199 assert_eq!(format!("{}", ProteinEdit::Ident), "=".to_string(),);
1200 }
1201
1202 #[test]
1203 fn cds_pos() {
1204 assert_eq!(
1205 format!(
1206 "{}",
1207 CdsPos {
1208 base: 42,
1209 offset: None,
1210 cds_from: CdsFrom::Start,
1211 }
1212 ),
1213 "42".to_string(),
1214 );
1215
1216 assert_eq!(
1217 format!(
1218 "{}",
1219 CdsPos {
1220 base: 42,
1221 offset: None,
1222 cds_from: CdsFrom::End,
1223 }
1224 ),
1225 "*42".to_string(),
1226 );
1227
1228 assert_eq!(
1229 format!(
1230 "{}",
1231 CdsPos {
1232 base: 42,
1233 offset: Some(10),
1234 cds_from: CdsFrom::Start,
1235 }
1236 ),
1237 "42+10".to_string(),
1238 );
1239
1240 assert_eq!(
1241 format!(
1242 "{}",
1243 CdsPos {
1244 base: 42,
1245 offset: Some(10),
1246 cds_from: CdsFrom::End,
1247 }
1248 ),
1249 "*42+10".to_string(),
1250 );
1251
1252 assert_eq!(
1253 format!(
1254 "{}",
1255 CdsPos {
1256 base: 42,
1257 offset: Some(-10),
1258 cds_from: CdsFrom::Start,
1259 }
1260 ),
1261 "42-10".to_string(),
1262 );
1263
1264 assert_eq!(
1265 format!(
1266 "{}",
1267 CdsPos {
1268 base: 42,
1269 offset: Some(-10),
1270 cds_from: CdsFrom::End,
1271 }
1272 ),
1273 "*42-10".to_string(),
1274 );
1275 }
1276
1277 #[test]
1278 fn cds_interval() {
1279 assert_eq!(
1280 format!(
1281 "{}",
1282 CdsInterval {
1283 start: CdsPos {
1284 base: 42,
1285 offset: Some(-10),
1286 cds_from: CdsFrom::Start,
1287 },
1288 end: CdsPos {
1289 base: 42,
1290 offset: Some(10),
1291 cds_from: CdsFrom::Start,
1292 }
1293 }
1294 ),
1295 "42-10_42+10".to_string(),
1296 );
1297
1298 assert_eq!(
1299 format!(
1300 "{}",
1301 CdsInterval {
1302 start: CdsPos {
1303 base: 42,
1304 offset: Some(10),
1305 cds_from: CdsFrom::Start,
1306 },
1307 end: CdsPos {
1308 base: 42,
1309 offset: Some(10),
1310 cds_from: CdsFrom::Start,
1311 }
1312 }
1313 ),
1314 "42+10".to_string(),
1315 );
1316 }
1317
1318 #[test]
1319 fn cds_loc_edit() {
1320 assert_eq!(
1321 format!(
1322 "{}",
1323 CdsLocEdit {
1324 loc: Mu::Certain(CdsInterval {
1325 start: CdsPos {
1326 base: 42,
1327 offset: Some(-10),
1328 cds_from: CdsFrom::Start,
1329 },
1330 end: CdsPos {
1331 base: 42,
1332 offset: Some(10),
1333 cds_from: CdsFrom::Start,
1334 }
1335 }),
1336 edit: Mu::Certain(NaEdit::RefAlt {
1337 reference: "".to_string(),
1338 alternative: "".to_string()
1339 })
1340 }
1341 ),
1342 "42-10_42+10=".to_string(),
1343 );
1344 }
1345
1346 #[test]
1347 fn tx_pos() {
1348 assert_eq!(
1349 format!(
1350 "{}",
1351 TxPos {
1352 base: 42,
1353 offset: None,
1354 }
1355 ),
1356 "42".to_string(),
1357 );
1358
1359 assert_eq!(
1360 format!(
1361 "{}",
1362 TxPos {
1363 base: 42,
1364 offset: Some(10),
1365 }
1366 ),
1367 "42+10".to_string(),
1368 );
1369
1370 assert_eq!(
1371 format!(
1372 "{}",
1373 TxPos {
1374 base: 42,
1375 offset: Some(-10),
1376 }
1377 ),
1378 "42-10".to_string(),
1379 );
1380 }
1381
1382 #[test]
1383 fn tx_interval() {
1384 assert_eq!(
1385 format!(
1386 "{}",
1387 TxInterval {
1388 start: TxPos {
1389 base: 42,
1390 offset: Some(-10),
1391 },
1392 end: TxPos {
1393 base: 42,
1394 offset: Some(10),
1395 }
1396 }
1397 ),
1398 "42-10_42+10".to_string(),
1399 );
1400
1401 assert_eq!(
1402 format!(
1403 "{}",
1404 TxInterval {
1405 start: TxPos {
1406 base: 42,
1407 offset: Some(10),
1408 },
1409 end: TxPos {
1410 base: 42,
1411 offset: Some(10),
1412 }
1413 }
1414 ),
1415 "42+10".to_string(),
1416 );
1417 }
1418
1419 #[test]
1420 fn tx_loc_edit() {
1421 assert_eq!(
1422 format!(
1423 "{}",
1424 TxLocEdit {
1425 loc: Mu::Certain(TxInterval {
1426 start: TxPos {
1427 base: 42,
1428 offset: Some(-10),
1429 },
1430 end: TxPos {
1431 base: 42,
1432 offset: Some(10),
1433 }
1434 }),
1435 edit: Mu::Certain(NaEdit::RefAlt {
1436 reference: "".to_string(),
1437 alternative: "".to_string()
1438 })
1439 }
1440 ),
1441 "42-10_42+10=".to_string(),
1442 );
1443 }
1444 #[test]
1445 fn rna_pos() {
1446 assert_eq!(
1447 format!(
1448 "{}",
1449 RnaPos {
1450 base: 42,
1451 offset: None,
1452 }
1453 ),
1454 "42".to_string(),
1455 );
1456
1457 assert_eq!(
1458 format!(
1459 "{}",
1460 RnaPos {
1461 base: 42,
1462 offset: Some(10),
1463 }
1464 ),
1465 "42+10".to_string(),
1466 );
1467
1468 assert_eq!(
1469 format!(
1470 "{}",
1471 RnaPos {
1472 base: 42,
1473 offset: Some(-10),
1474 }
1475 ),
1476 "42-10".to_string(),
1477 );
1478 }
1479
1480 #[test]
1481 fn rna_interval() {
1482 assert_eq!(
1483 format!(
1484 "{}",
1485 RnaInterval {
1486 start: RnaPos {
1487 base: 42,
1488 offset: Some(-10),
1489 },
1490 end: RnaPos {
1491 base: 42,
1492 offset: Some(10),
1493 }
1494 }
1495 ),
1496 "42-10_42+10".to_string(),
1497 );
1498
1499 assert_eq!(
1500 format!(
1501 "{}",
1502 RnaInterval {
1503 start: RnaPos {
1504 base: 42,
1505 offset: Some(10),
1506 },
1507 end: RnaPos {
1508 base: 42,
1509 offset: Some(10),
1510 }
1511 }
1512 ),
1513 "42+10".to_string(),
1514 );
1515 }
1516
1517 #[test]
1518 fn rna_loc_edit() {
1519 assert_eq!(
1520 format!(
1521 "{}",
1522 RnaLocEdit {
1523 loc: Mu::Certain(RnaInterval {
1524 start: RnaPos {
1525 base: 42,
1526 offset: Some(-10),
1527 },
1528 end: RnaPos {
1529 base: 42,
1530 offset: Some(10),
1531 }
1532 }),
1533 edit: Mu::Certain(NaEdit::RefAlt {
1534 reference: "".to_string(),
1535 alternative: "".to_string()
1536 })
1537 }
1538 ),
1539 "42-10_42+10=".to_string(),
1540 );
1541 }
1542
1543 #[test]
1544 fn genome_interval() {
1545 assert_eq!(
1546 format!(
1547 "{}",
1548 GenomeInterval {
1549 start: None,
1550 end: None
1551 }
1552 ),
1553 "?".to_string(),
1554 );
1555
1556 assert_eq!(
1557 format!(
1558 "{}",
1559 GenomeInterval {
1560 start: Some(10),
1561 end: None
1562 }
1563 ),
1564 "10_?".to_string(),
1565 );
1566
1567 assert_eq!(
1568 format!(
1569 "{}",
1570 GenomeInterval {
1571 start: None,
1572 end: Some(10)
1573 }
1574 ),
1575 "?_10".to_string(),
1576 );
1577
1578 assert_eq!(
1579 format!(
1580 "{}",
1581 GenomeInterval {
1582 start: Some(10),
1583 end: Some(20)
1584 }
1585 ),
1586 "10_20".to_string(),
1587 );
1588
1589 assert_eq!(
1590 format!(
1591 "{}",
1592 GenomeInterval {
1593 start: Some(10),
1594 end: Some(10)
1595 }
1596 ),
1597 "10".to_string(),
1598 );
1599 }
1600
1601 #[test]
1602 fn genome_loc_edit() {
1603 assert_eq!(
1604 format!(
1605 "{}",
1606 GenomeLocEdit {
1607 loc: Mu::Certain(GenomeInterval {
1608 start: Some(10),
1609 end: Some(20)
1610 }),
1611 edit: Mu::Certain(NaEdit::RefAlt {
1612 reference: "C".to_string(),
1613 alternative: "T".to_string()
1614 })
1615 }
1616 ),
1617 "10_20C>T".to_string(),
1618 );
1619 }
1620
1621 #[test]
1622 fn mt_interval() {
1623 assert_eq!(
1624 format!(
1625 "{}",
1626 MtInterval {
1627 start: None,
1628 end: None
1629 }
1630 ),
1631 "?".to_string(),
1632 );
1633
1634 assert_eq!(
1635 format!(
1636 "{}",
1637 MtInterval {
1638 start: Some(10),
1639 end: None
1640 }
1641 ),
1642 "10_?".to_string(),
1643 );
1644
1645 assert_eq!(
1646 format!(
1647 "{}",
1648 MtInterval {
1649 start: None,
1650 end: Some(10)
1651 }
1652 ),
1653 "?_10".to_string(),
1654 );
1655
1656 assert_eq!(
1657 format!(
1658 "{}",
1659 MtInterval {
1660 start: Some(10),
1661 end: Some(20)
1662 }
1663 ),
1664 "10_20".to_string(),
1665 );
1666
1667 assert_eq!(
1668 format!(
1669 "{}",
1670 MtInterval {
1671 start: Some(10),
1672 end: Some(10)
1673 }
1674 ),
1675 "10".to_string(),
1676 );
1677 }
1678
1679 #[test]
1680 fn mt_loc_edit() {
1681 assert_eq!(
1682 format!(
1683 "{}",
1684 MtLocEdit {
1685 loc: Mu::Certain(MtInterval {
1686 start: Some(10),
1687 end: Some(20)
1688 }),
1689 edit: Mu::Certain(NaEdit::RefAlt {
1690 reference: "C".to_string(),
1691 alternative: "T".to_string()
1692 })
1693 }
1694 ),
1695 "10_20C>T".to_string(),
1696 );
1697 }
1698
1699 #[test]
1700 fn prot_pos() {
1701 assert_eq!(
1702 format!(
1703 "{}",
1704 ProtPos {
1705 aa: "Leu".to_string(),
1706 number: 42
1707 }
1708 ),
1709 "Leu42".to_string()
1710 );
1711 }
1712
1713 #[test]
1714 fn prot_interval() {
1715 assert_eq!(
1716 format!(
1717 "{}",
1718 ProtInterval {
1719 start: ProtPos {
1720 aa: "Leu".to_string(),
1721 number: 42
1722 },
1723 end: ProtPos {
1724 aa: "Thr".to_string(),
1725 number: 43
1726 },
1727 }
1728 ),
1729 "Leu42_Thr43".to_string()
1730 );
1731
1732 assert_eq!(
1733 format!(
1734 "{}",
1735 ProtInterval {
1736 start: ProtPos {
1737 aa: "Leu".to_string(),
1738 number: 42
1739 },
1740 end: ProtPos {
1741 aa: "Leu".to_string(),
1742 number: 42
1743 },
1744 }
1745 ),
1746 "Leu42".to_string()
1747 );
1748 }
1749
1750 #[test]
1751 fn prot_loc_edit() {
1752 assert_eq!(
1753 format!(
1754 "{}",
1755 ProtLocEdit::Ordinary {
1756 loc: Mu::Certain(ProtInterval {
1757 start: ProtPos {
1758 aa: "Leu".to_string(),
1759 number: 42
1760 },
1761 end: ProtPos {
1762 aa: "Thr".to_string(),
1763 number: 43
1764 },
1765 },),
1766 edit: Mu::Certain(ProteinEdit::Ident),
1767 }
1768 ),
1769 "Leu42_Thr43=".to_string()
1770 );
1771
1772 assert_eq!(format!("{}", ProtLocEdit::NoChange,), "=".to_string());
1773
1774 assert_eq!(
1775 format!("{}", ProtLocEdit::NoChangeUncertain,),
1776 "(=)".to_string()
1777 );
1778
1779 assert_eq!(format!("{}", ProtLocEdit::NoProtein,), "0".to_string());
1780
1781 assert_eq!(
1782 format!("{}", ProtLocEdit::NoProteinUncertain,),
1783 "0?".to_string()
1784 );
1785 }
1786
1787 #[test]
1788 fn hgvs_variant_cds() {
1789 assert_eq!(
1790 format!(
1791 "{}",
1792 HgvsVariant::CdsVariant {
1793 accession: Accession {
1794 value: "NA12345.1".to_string()
1795 },
1796 gene_symbol: Some(GeneSymbol {
1797 value: "TTN".to_string()
1798 }),
1799 loc_edit: CdsLocEdit {
1800 loc: Mu::Certain(CdsInterval {
1801 start: CdsPos {
1802 base: 100,
1803 offset: None,
1804 cds_from: CdsFrom::Start,
1805 },
1806 end: CdsPos {
1807 base: 100,
1808 offset: None,
1809 cds_from: CdsFrom::Start,
1810 }
1811 }),
1812 edit: Mu::Certain(NaEdit::RefAlt {
1813 reference: "C".to_string(),
1814 alternative: "T".to_string()
1815 })
1816 }
1817 }
1818 ),
1819 "NA12345.1(TTN):c.100C>T".to_string(),
1820 );
1821
1822 assert_eq!(
1823 format!(
1824 "{}",
1825 HgvsVariant::CdsVariant {
1826 accession: Accession {
1827 value: "NA12345.1".to_string()
1828 },
1829 gene_symbol: None,
1830 loc_edit: CdsLocEdit {
1831 loc: Mu::Certain(CdsInterval {
1832 start: CdsPos {
1833 base: 100,
1834 offset: None,
1835 cds_from: CdsFrom::Start,
1836 },
1837 end: CdsPos {
1838 base: 100,
1839 offset: None,
1840 cds_from: CdsFrom::Start,
1841 }
1842 }),
1843 edit: Mu::Certain(NaEdit::RefAlt {
1844 reference: "C".to_string(),
1845 alternative: "T".to_string()
1846 })
1847 }
1848 }
1849 ),
1850 "NA12345.1:c.100C>T".to_string(),
1851 );
1852 }
1853
1854 #[test]
1855 fn hgvs_variant_genome() {
1856 assert_eq!(
1857 format!(
1858 "{}",
1859 HgvsVariant::GenomeVariant {
1860 accession: Accession {
1861 value: "NA12345.1".to_string()
1862 },
1863 gene_symbol: Some(GeneSymbol {
1864 value: "TTN".to_string()
1865 }),
1866 loc_edit: GenomeLocEdit {
1867 loc: Mu::Certain(GenomeInterval {
1868 start: Some(100),
1869 end: Some(100)
1870 }),
1871 edit: Mu::Certain(NaEdit::RefAlt {
1872 reference: "C".to_string(),
1873 alternative: "T".to_string()
1874 })
1875 }
1876 }
1877 ),
1878 "NA12345.1(TTN):g.100C>T".to_string(),
1879 );
1880
1881 assert_eq!(
1882 format!(
1883 "{}",
1884 HgvsVariant::GenomeVariant {
1885 accession: Accession {
1886 value: "NA12345.1".to_string()
1887 },
1888 gene_symbol: None,
1889 loc_edit: GenomeLocEdit {
1890 loc: Mu::Certain(GenomeInterval {
1891 start: Some(100),
1892 end: Some(100)
1893 }),
1894 edit: Mu::Certain(NaEdit::RefAlt {
1895 reference: "C".to_string(),
1896 alternative: "T".to_string()
1897 })
1898 }
1899 }
1900 ),
1901 "NA12345.1:g.100C>T".to_string(),
1902 );
1903 }
1904
1905 #[test]
1906 fn hgvs_variant_mt() {
1907 assert_eq!(
1908 format!(
1909 "{}",
1910 HgvsVariant::MtVariant {
1911 accession: Accession {
1912 value: "NA12345.1".to_string()
1913 },
1914 gene_symbol: Some(GeneSymbol {
1915 value: "TTN".to_string()
1916 }),
1917 loc_edit: MtLocEdit {
1918 loc: Mu::Certain(MtInterval {
1919 start: Some(100),
1920 end: Some(100)
1921 }),
1922 edit: Mu::Certain(NaEdit::RefAlt {
1923 reference: "C".to_string(),
1924 alternative: "T".to_string()
1925 })
1926 }
1927 }
1928 ),
1929 "NA12345.1(TTN):m.100C>T".to_string(),
1930 );
1931
1932 assert_eq!(
1933 format!(
1934 "{}",
1935 HgvsVariant::MtVariant {
1936 accession: Accession {
1937 value: "NA12345.1".to_string()
1938 },
1939 gene_symbol: None,
1940 loc_edit: MtLocEdit {
1941 loc: Mu::Certain(MtInterval {
1942 start: Some(100),
1943 end: Some(100)
1944 }),
1945 edit: Mu::Certain(NaEdit::RefAlt {
1946 reference: "C".to_string(),
1947 alternative: "T".to_string()
1948 })
1949 }
1950 }
1951 ),
1952 "NA12345.1:m.100C>T".to_string(),
1953 );
1954 }
1955
1956 #[test]
1957 fn hgvs_variant_tx() {
1958 assert_eq!(
1959 format!(
1960 "{}",
1961 HgvsVariant::TxVariant {
1962 accession: Accession {
1963 value: "NA12345.1".to_string()
1964 },
1965 gene_symbol: Some(GeneSymbol {
1966 value: "TTN".to_string()
1967 }),
1968 loc_edit: TxLocEdit {
1969 loc: Mu::Certain(TxInterval {
1970 start: TxPos {
1971 base: 100,
1972 offset: None
1973 },
1974 end: TxPos {
1975 base: 100,
1976 offset: None
1977 },
1978 }),
1979 edit: Mu::Certain(NaEdit::RefAlt {
1980 reference: "C".to_string(),
1981 alternative: "T".to_string()
1982 })
1983 }
1984 }
1985 ),
1986 "NA12345.1(TTN):n.100C>T".to_string(),
1987 );
1988
1989 assert_eq!(
1990 format!(
1991 "{}",
1992 HgvsVariant::TxVariant {
1993 accession: Accession {
1994 value: "NA12345.1".to_string()
1995 },
1996 gene_symbol: None,
1997 loc_edit: TxLocEdit {
1998 loc: Mu::Certain(TxInterval {
1999 start: TxPos {
2000 base: 100,
2001 offset: None
2002 },
2003 end: TxPos {
2004 base: 100,
2005 offset: None
2006 },
2007 }),
2008 edit: Mu::Certain(NaEdit::RefAlt {
2009 reference: "C".to_string(),
2010 alternative: "T".to_string()
2011 })
2012 }
2013 }
2014 ),
2015 "NA12345.1:n.100C>T".to_string(),
2016 );
2017 }
2018
2019 #[test]
2020 fn hgvs_variant_rna() {
2021 assert_eq!(
2022 format!(
2023 "{}",
2024 HgvsVariant::RnaVariant {
2025 accession: Accession {
2026 value: "NA12345.1".to_string()
2027 },
2028 gene_symbol: Some(GeneSymbol {
2029 value: "TTN".to_string()
2030 }),
2031 loc_edit: RnaLocEdit {
2032 loc: Mu::Certain(RnaInterval {
2033 start: RnaPos {
2034 base: 100,
2035 offset: None
2036 },
2037 end: RnaPos {
2038 base: 100,
2039 offset: None
2040 },
2041 }),
2042 edit: Mu::Certain(NaEdit::RefAlt {
2043 reference: "C".to_string(),
2044 alternative: "T".to_string()
2045 })
2046 }
2047 }
2048 ),
2049 "NA12345.1(TTN):r.100C>T".to_string(),
2050 );
2051
2052 assert_eq!(
2053 format!(
2054 "{}",
2055 HgvsVariant::RnaVariant {
2056 accession: Accession {
2057 value: "NA12345.1".to_string()
2058 },
2059 gene_symbol: None,
2060 loc_edit: RnaLocEdit {
2061 loc: Mu::Certain(RnaInterval {
2062 start: RnaPos {
2063 base: 100,
2064 offset: None
2065 },
2066 end: RnaPos {
2067 base: 100,
2068 offset: None
2069 },
2070 }),
2071 edit: Mu::Certain(NaEdit::RefAlt {
2072 reference: "C".to_string(),
2073 alternative: "T".to_string()
2074 })
2075 }
2076 }
2077 ),
2078 "NA12345.1:r.100C>T".to_string(),
2079 );
2080 }
2081
2082 #[test]
2083 fn hgvs_variant_prot() {
2084 assert_eq!(
2085 format!(
2086 "{}",
2087 HgvsVariant::ProtVariant {
2088 accession: Accession {
2089 value: "NA12345.1".to_string()
2090 },
2091 gene_symbol: Some(GeneSymbol {
2092 value: "TTN".to_string()
2093 }),
2094 loc_edit: ProtLocEdit::NoChange
2095 }
2096 ),
2097 "NA12345.1(TTN):p.=".to_string(),
2098 );
2099 }
2100
2101 #[test]
2103 fn roundtrip_hgvs_gauntlet() -> Result<(), Error> {
2104 let reader = BufReader::new(File::open("tests/data/parser/gauntlet")?);
2105
2106 for line in reader.lines() {
2107 let line = line?;
2108 let line = line.trim();
2109 if !line.starts_with('#') && !line.is_empty() {
2110 let hgvs_variant = HgvsVariant::from_str(line)?;
2111 let hgvs_str = format!("{}", &hgvs_variant);
2112 assert_eq!(
2113 hgvs_str, line,
2114 "round-trip failed for variant {:?}; line= {}",
2115 &hgvs_variant, line
2116 );
2117 }
2118 }
2119
2120 Ok(())
2121 }
2122}
2123
2124