1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
//! Variant record samples.

pub mod keys;
mod sample;
pub mod series;

use std::io;

pub use self::{sample::Sample, series::Series};
use crate::Header;

#[allow(clippy::tabs_in_doc_comments)]
/// Variant record samples.
///
/// Variant record samples are described similarly to a data frame: rows and columns are samples
/// and series, respectively.
///
/// Take, for example, the following samples in a VCF record.
///
/// ```text
/// FORMAT	sample1	sample2	sample3
/// GT:GQ:DP	0|0:21:1	1|0:34:2	1/1:55:5
/// ```
///
/// This trait provides an interface over this data as a table.
///
/// ```text
///           GT     GQ    DP
///         +-----+-----+-----+
/// sample1 | 0|0 |  21 |   1 |
/// sample2 | 1|0 |  34 |   2 |
/// sample3 | 1/1 |  55 |   5 |
///         +-----+-----+-----+
/// ```
///
/// A sample contains the values of a row (e.g., sample1 = ["0|0", 21, 1]); and a column, the
/// values of a series (e.g., GT = ["0|0", "1|0", "1/1"]).
pub trait Samples {
    /// Returns whether there are any samples.
    fn is_empty(&self) -> bool;

    /// Returns the number of samples.
    fn len(&self) -> usize;

    /// Returns the column names.
    fn column_names<'a, 'h: 'a>(
        &'a self,
        header: &'h Header,
    ) -> Box<dyn Iterator<Item = io::Result<&'a str>> + 'a>;

    /// Returns the series with the given column name.
    fn select<'a, 'h: 'a>(
        &'a self,
        header: &'h Header,
        column_name: &str,
    ) -> Option<io::Result<Box<dyn Series + 'a>>>;

    /// Returns an iterator over series.
    fn series(&self) -> Box<dyn Iterator<Item = io::Result<Box<dyn Series + '_>>> + '_>;

    /// Returns an iterator over samples.
    fn iter(&self) -> Box<dyn Iterator<Item = Box<dyn Sample + '_>> + '_>;
}

impl Samples for Box<dyn Samples + '_> {
    fn is_empty(&self) -> bool {
        (**self).is_empty()
    }

    fn len(&self) -> usize {
        (**self).len()
    }

    fn column_names<'a, 'h: 'a>(
        &'a self,
        header: &'h Header,
    ) -> Box<dyn Iterator<Item = io::Result<&'a str>> + 'a> {
        (**self).column_names(header)
    }

    fn select<'a, 'h: 'a>(
        &'a self,
        header: &'h Header,
        column_name: &str,
    ) -> Option<io::Result<Box<dyn Series + 'a>>> {
        (**self).select(header, column_name)
    }

    fn series(&self) -> Box<dyn Iterator<Item = io::Result<Box<dyn Series + '_>>> + '_> {
        (**self).series()
    }

    fn iter(&self) -> Box<dyn Iterator<Item = Box<dyn Sample + '_>> + '_> {
        (**self).iter()
    }
}