@@ -12,6 +12,61 @@ use std::cmp::Ordering;
1212use std:: collections:: BTreeMap ;
1313use std:: ops:: { Deref , DerefMut } ;
1414
15+ /// Dataset metadata attributes with recognized keys and extensibility
16+ #[ derive( Clone , Debug , Default , Eq , PartialEq , Serialize , Deserialize , JsonSchema ) ]
17+ pub struct DatasetAttributes {
18+ /// Human-readable dataset name
19+ #[ serde( default , skip_serializing_if = "Option::is_none" ) ]
20+ pub name : Option < String > ,
21+
22+ /// Name of the reference sequence
23+ #[ serde( rename = "reference name" , default , skip_serializing_if = "Option::is_none" ) ]
24+ pub reference_name : Option < String > ,
25+
26+ /// Accession number of the reference sequence
27+ #[ serde( rename = "reference accession" , default , skip_serializing_if = "Option::is_none" ) ]
28+ pub reference_accession : Option < String > ,
29+
30+ /// If true, dataset is deprecated and excluded from listings by default.
31+ /// Authors mark a dataset as deprecated to indicate it will no longer be updated or supported.
32+ /// Use `--include-deprecated` CLI flag to show deprecated datasets.
33+ #[ serde( default , skip_serializing_if = "Option::is_none" ) ]
34+ pub deprecated : Option < bool > ,
35+
36+ /// If true, dataset is experimental and excluded with `--no-experimental` CLI flag.
37+ /// Authors mark a dataset as experimental when development is still in progress,
38+ /// or if the dataset is incomplete or of lower quality than usual. Use at own risk.
39+ #[ serde( default , skip_serializing_if = "Option::is_none" ) ]
40+ pub experimental : Option < bool > ,
41+
42+ /// Additional custom attributes
43+ #[ serde( flatten) ]
44+ pub other : BTreeMap < String , AnyType > ,
45+ }
46+
47+ impl DatasetAttributes {
48+ pub fn is_default ( & self ) -> bool {
49+ self == & Self :: default ( )
50+ }
51+
52+ /// Iterate over all attributes as (key, value) pairs for display
53+ pub fn iter ( & self ) -> impl Iterator < Item = ( & str , String ) > {
54+ let typed = [
55+ self . name . as_ref ( ) . map ( |v| ( "name" , v. clone ( ) ) ) ,
56+ self . reference_name . as_ref ( ) . map ( |v| ( "reference name" , v. clone ( ) ) ) ,
57+ self . reference_accession . as_ref ( ) . map ( |v| ( "reference accession" , v. clone ( ) ) ) ,
58+ self . deprecated . map ( |v| ( "deprecated" , v. to_string ( ) ) ) ,
59+ self . experimental . map ( |v| ( "experimental" , v. to_string ( ) ) ) ,
60+ ]
61+ . into_iter ( )
62+ . flatten ( ) ;
63+
64+ let other = self . other . iter ( ) . map ( |( k, v) | ( k. as_str ( ) , v. to_string ( ) ) ) ;
65+
66+ chain ! ( typed, other)
67+ }
68+ }
69+
1570const INDEX_JSON_SCHEMA_VERSION_FROM : & str = "3.0.0" ;
1671const INDEX_JSON_SCHEMA_VERSION_TO : & str = "3.0.0" ;
1772
@@ -114,8 +169,8 @@ pub struct Dataset {
114169 #[ serde( default , skip_serializing_if = "Vec::is_empty" ) ]
115170 pub shortcuts : Vec < String > ,
116171
117- #[ serde( default , skip_serializing_if = "BTreeMap::is_empty " ) ]
118- pub attributes : BTreeMap < String , AnyType > ,
172+ #[ serde( default , skip_serializing_if = "DatasetAttributes::is_default " ) ]
173+ pub attributes : DatasetAttributes ,
119174
120175 #[ serde( default , skip_serializing_if = "DatasetMeta::is_default" ) ]
121176 pub meta : DatasetMeta ,
@@ -148,7 +203,7 @@ impl Dataset {
148203 }
149204
150205 pub fn name ( & self ) -> Option < & str > {
151- self . attributes . get ( " name" ) . and_then ( AnyType :: as_str_maybe )
206+ self . attributes . name . as_deref ( )
152207 }
153208
154209 pub fn shortcuts ( & self ) -> impl Iterator < Item = & str > {
@@ -175,30 +230,19 @@ impl Dataset {
175230 }
176231
177232 pub fn ref_name ( & self ) -> Option < & str > {
178- self . attributes . get ( "reference name" ) . and_then ( AnyType :: as_str_maybe )
233+ self . attributes . reference_name . as_deref ( )
179234 }
180235
181236 pub fn ref_accession ( & self ) -> Option < & str > {
182- self
183- . attributes
184- . get ( "reference accession" )
185- . and_then ( AnyType :: as_str_maybe)
237+ self . attributes . reference_accession . as_deref ( )
186238 }
187239
188240 pub fn deprecated ( & self ) -> bool {
189- self
190- . attributes
191- . get ( "deprecated" )
192- . and_then ( AnyType :: as_bool_maybe)
193- . unwrap_or ( false )
241+ self . attributes . deprecated . unwrap_or ( false )
194242 }
195243
196244 pub fn experimental ( & self ) -> bool {
197- self
198- . attributes
199- . get ( "experimental" )
200- . and_then ( AnyType :: as_bool_maybe)
201- . unwrap_or ( false )
245+ self . attributes . experimental . unwrap_or ( false )
202246 }
203247
204248 pub fn is_community ( & self ) -> bool {
0 commit comments