Skip to main content

oxbow/bbi/model/base/
field.rs

1use std::io;
2
3use bigtools::bed::autosql::parse::Field as AutosqlField;
4use bigtools::bed::autosql::parse::FieldType as AutosqlType;
5
6// Re-export shared types from the bed module.
7pub use crate::bed::model::field_def::{
8    bed_standard_fields, FieldBuilder, FieldDef, FieldType, Push,
9};
10
11/// Convert an AutoSql field to a [`FieldDef`].
12impl TryFrom<&AutosqlField> for FieldDef {
13    type Error = io::Error;
14
15    fn try_from(field: &AutosqlField) -> Result<Self, Self::Error> {
16        let ty = FieldType::try_from(field)?;
17        Ok(Self {
18            name: field.name.clone(),
19            ty,
20        })
21    }
22}
23
24/// Convert an AutoSql field type to a [`FieldType`].
25impl TryFrom<&AutosqlField> for FieldType {
26    type Error = io::Error;
27
28    fn try_from(f: &AutosqlField) -> Result<Self, Self::Error> {
29        let ty = match &f.field_type {
30            AutosqlType::Byte => match &f.field_size {
31                None => Self::Byte,
32                Some(size_str) => match size_str.parse::<usize>() {
33                    Ok(size) => Self::ByteFixedSizeList(size),
34                    Err(_) => Self::ByteList,
35                },
36            },
37            AutosqlType::Ubyte => match &f.field_size {
38                None => Self::Ubyte,
39                Some(size_str) => match size_str.parse::<usize>() {
40                    Ok(size) => Self::UbyteFixedSizeList(size),
41                    Err(_) => Self::UbyteList,
42                },
43            },
44            AutosqlType::Short => match &f.field_size {
45                None => Self::Short,
46                Some(size_str) => match size_str.parse::<usize>() {
47                    Ok(size) => Self::ShortFixedSizeList(size),
48                    Err(_) => Self::ShortList,
49                },
50            },
51            AutosqlType::Ushort => match &f.field_size {
52                None => Self::Ushort,
53                Some(size_str) => match size_str.parse::<usize>() {
54                    Ok(size) => Self::UshortFixedSizeList(size),
55                    Err(_) => Self::UshortList,
56                },
57            },
58            AutosqlType::Int => match &f.field_size {
59                None => Self::Int,
60                Some(size_str) => match size_str.parse::<usize>() {
61                    Ok(size) => Self::IntFixedSizeList(size),
62                    Err(_) => Self::IntList,
63                },
64            },
65            AutosqlType::Uint => match &f.field_size {
66                None => Self::Uint,
67                Some(size_str) => match size_str.parse::<usize>() {
68                    Ok(size) => Self::UintFixedSizeList(size),
69                    Err(_) => Self::UintList,
70                },
71            },
72            AutosqlType::Bigint => match &f.field_size {
73                None => Self::Bigint,
74                Some(size_str) => match size_str.parse::<usize>() {
75                    Ok(size) => Self::BigintFixedSizeList(size),
76                    Err(_) => Self::BigintList,
77                },
78            },
79            AutosqlType::Float => match &f.field_size {
80                None => Self::Float,
81                Some(size_str) => match size_str.parse::<usize>() {
82                    Ok(size) => Self::FloatFixedSizeList(size),
83                    Err(_) => Self::FloatList,
84                },
85            },
86            AutosqlType::Double => match &f.field_size {
87                None => Self::Double,
88                Some(size_str) => match size_str.parse::<usize>() {
89                    Ok(size) => Self::DoubleFixedSizeList(size),
90                    Err(_) => Self::DoubleList,
91                },
92            },
93            AutosqlType::Char => Self::Char,
94            AutosqlType::String => Self::String,
95            AutosqlType::Lstring => Self::Lstring,
96            AutosqlType::Enum(items) => Self::Enum(items.clone()),
97            AutosqlType::Set(items) => Self::Set(items.clone()),
98            AutosqlType::Declaration(_, _) => {
99                return Err(io::Error::new(
100                    io::ErrorKind::InvalidInput,
101                    "Unsupported AutoSql type: Declaration.",
102                ));
103            }
104        };
105        Ok(ty)
106    }
107}
108
109/// The 12 standard BED field definitions as AutoSql fields.
110///
111/// This is the bigtools-dependent version, kept for compatibility with BBI code
112/// that receives AutoSql fields from bigtools parsers.
113pub fn bed_standard_autosql_fields() -> [AutosqlField; 12] {
114    [
115        AutosqlField {
116            name: "chrom".to_string(),
117            field_type: AutosqlType::String,
118            field_size: None,
119            index_type: None,
120            auto: false,
121            comment: "Reference sequence chromosome or scaffold.".to_string(),
122        },
123        AutosqlField {
124            name: "start".to_string(),
125            field_type: AutosqlType::Uint,
126            field_size: None,
127            index_type: None,
128            auto: false,
129            comment: "Start position in chromosome.".to_string(),
130        },
131        AutosqlField {
132            name: "end".to_string(),
133            field_type: AutosqlType::Uint,
134            field_size: None,
135            index_type: None,
136            auto: false,
137            comment: "End position in chromosome.".to_string(),
138        },
139        AutosqlField {
140            name: "name".to_string(),
141            field_type: AutosqlType::String,
142            field_size: None,
143            index_type: None,
144            auto: false,
145            comment: "Name or ID of item.".to_string(),
146        },
147        AutosqlField {
148            name: "score".to_string(),
149            field_type: AutosqlType::Ushort,
150            field_size: None,
151            index_type: None,
152            auto: false,
153            comment: "Score (0-1000).".to_string(),
154        },
155        AutosqlField {
156            name: "strand".to_string(),
157            field_type: AutosqlType::Char,
158            field_size: None,
159            index_type: None,
160            auto: false,
161            comment: "+ or - for strand.".to_string(),
162        },
163        AutosqlField {
164            name: "thickStart".to_string(),
165            field_type: AutosqlType::Uint,
166            field_size: None,
167            index_type: None,
168            auto: false,
169            comment: "Start of where display should be thick (start codon).".to_string(),
170        },
171        AutosqlField {
172            name: "thickEnd".to_string(),
173            field_type: AutosqlType::Uint,
174            field_size: None,
175            index_type: None,
176            auto: false,
177            comment: "End of where display should be thick (stop codon).".to_string(),
178        },
179        AutosqlField {
180            name: "itemRgb".to_string(),
181            field_type: AutosqlType::Ubyte,
182            field_size: Some("3".to_string()),
183            index_type: None,
184            auto: false,
185            comment: "RGB value (use R,G,B string in input file).".to_string(),
186        },
187        AutosqlField {
188            name: "blockCount".to_string(),
189            field_type: AutosqlType::Uint,
190            field_size: None,
191            index_type: None,
192            auto: false,
193            comment: "Number of blocks.".to_string(),
194        },
195        AutosqlField {
196            name: "blockSizes".to_string(),
197            field_type: AutosqlType::Uint,
198            field_size: Some("blockCount".to_string()),
199            index_type: None,
200            auto: false,
201            comment: "Comma separated list of block sizes.".to_string(),
202        },
203        AutosqlField {
204            name: "blockStarts".to_string(),
205            field_type: AutosqlType::Uint,
206            field_size: Some("blockCount".to_string()),
207            index_type: None,
208            auto: false,
209            comment: "Start positions relative to chromStart.".to_string(),
210        },
211    ]
212}
213
214#[cfg(test)]
215mod tests {
216    use super::*;
217
218    #[test]
219    fn test_fielddef_try_from_autosql_field() {
220        let autosql_field = AutosqlField {
221            name: "foo".to_string(),
222            field_type: AutosqlType::Int,
223            field_size: None,
224            index_type: None,
225            auto: false,
226            comment: "Just a field".to_string(),
227        };
228        let field_def = FieldDef::try_from(&autosql_field);
229        assert!(field_def.is_ok());
230        let field_def = field_def.unwrap();
231        assert_eq!(field_def.name, "foo");
232        assert_eq!(field_def.ty, FieldType::Int);
233    }
234}