noodles_vcf/variant/record_buf.rs
1//! Variant record buffer.
2
3mod alternate_bases;
4pub mod builder;
5mod convert;
6mod filters;
7pub mod ids;
8pub mod info;
9pub mod samples;
10
11use std::io;
12
13use noodles_core::Position;
14
15pub use self::{
16 alternate_bases::AlternateBases, builder::Builder, filters::Filters, ids::Ids, info::Info,
17 samples::Samples,
18};
19use crate::Header;
20
21/// A variant record buffer.
22#[derive(Clone, Debug, PartialEq)]
23pub struct RecordBuf {
24 reference_sequence_name: String,
25 variant_start: Option<Position>,
26 ids: Ids,
27 reference_bases: String,
28 alternate_bases: AlternateBases,
29 quality_score: Option<f32>,
30 filters: Filters,
31 info: Info,
32 samples: Samples,
33}
34
35impl RecordBuf {
36 /// Returns a builder to create a record from each of its fields.
37 ///
38 /// # Examples
39 ///
40 /// ```
41 /// use noodles_vcf as vcf;
42 /// let builder = vcf::variant::RecordBuf::builder();
43 /// ```
44 pub fn builder() -> Builder {
45 Builder::default()
46 }
47
48 /// Returns the reference sequence name.
49 ///
50 /// # Examples
51 ///
52 /// ```
53 /// use noodles_vcf as vcf;
54 ///
55 /// let record = vcf::variant::RecordBuf::builder()
56 /// .set_reference_sequence_name("sq0")
57 /// .build();
58 ///
59 /// assert_eq!(record.reference_sequence_name(), "sq0");
60 /// ```
61 pub fn reference_sequence_name(&self) -> &str {
62 &self.reference_sequence_name
63 }
64
65 /// Returns a mutable reference to the reference sequence name.
66 ///
67 /// # Examples
68 ///
69 /// ```
70 /// use noodles_vcf as vcf;
71 ///
72 /// let mut record = vcf::variant::RecordBuf::builder()
73 /// .set_reference_sequence_name("sq0")
74 /// .build();
75 ///
76 /// *record.reference_sequence_name_mut() = String::from("sq1");
77 ///
78 /// assert_eq!(record.reference_sequence_name(), "sq1");
79 /// ```
80 pub fn reference_sequence_name_mut(&mut self) -> &mut String {
81 &mut self.reference_sequence_name
82 }
83
84 /// Returns the variant start position.
85 ///
86 /// This position is 1-based, inclusive. If the record represents the start of a telomeric
87 /// breakend, this returns `None`.
88 ///
89 /// # Examples
90 ///
91 /// ```
92 /// use noodles_core::Position;
93 /// use noodles_vcf as vcf;
94 ///
95 /// let record = vcf::variant::RecordBuf::builder()
96 /// .set_variant_start(Position::MIN)
97 /// .build();
98 ///
99 /// assert_eq!(record.variant_start(), Some(Position::MIN));
100 /// ```
101 pub fn variant_start(&self) -> Option<Position> {
102 self.variant_start
103 }
104
105 /// Returns a mutable reference to the variant start position.
106 ///
107 /// This position is 1-based, inclusive. If the record represents the start of a telomeric
108 /// breakend, this returns `None`.
109 ///
110 /// # Examples
111 ///
112 /// ```
113 /// use noodles_core::Position;
114 /// use noodles_vcf as vcf;
115 ///
116 /// let mut record = vcf::variant::RecordBuf::default();
117 /// *record.variant_start_mut() = Some(Position::MIN);
118 /// assert_eq!(record.variant_start(), Some(Position::MIN));
119 /// ```
120 pub fn variant_start_mut(&mut self) -> &mut Option<Position> {
121 &mut self.variant_start
122 }
123
124 /// Returns a list of IDs of the record.
125 ///
126 /// # Examples
127 ///
128 /// ```
129 /// use noodles_vcf::{self as vcf, variant::record_buf::Ids};
130 ///
131 /// let ids: Ids = [String::from("nd0")].into_iter().collect();
132 ///
133 /// let record = vcf::variant::RecordBuf::builder()
134 /// .set_ids(ids.clone())
135 /// .build();
136 ///
137 /// assert_eq!(record.ids(), &ids);
138 /// ```
139 pub fn ids(&self) -> &Ids {
140 &self.ids
141 }
142
143 /// Returns a mutable reference to the IDs.
144 ///
145 /// # Examples
146 ///
147 /// ```
148 /// use noodles_vcf::{self as vcf, variant::record_buf::Ids};
149 ///
150 /// let mut record = vcf::variant::RecordBuf::default();
151 ///
152 /// let ids: Ids = [String::from("nd0")].into_iter().collect();
153 /// *record.ids_mut() = ids.clone();
154 ///
155 /// assert_eq!(record.ids(), &ids);
156 /// ```
157 pub fn ids_mut(&mut self) -> &mut Ids {
158 &mut self.ids
159 }
160
161 /// Returns the reference bases of the record.
162 ///
163 /// # Examples
164 ///
165 /// ```
166 /// use noodles_vcf as vcf;
167 ///
168 /// let record = vcf::variant::RecordBuf::builder()
169 /// .set_reference_bases("A")
170 /// .build();
171 ///
172 /// assert_eq!(record.reference_bases(), "A");
173 /// ```
174 pub fn reference_bases(&self) -> &str {
175 &self.reference_bases
176 }
177
178 /// Returns a mutable reference to the reference bases of the record.
179 ///
180 /// # Examples
181 ///
182 /// ```
183 /// use noodles_vcf as vcf;
184 ///
185 /// let mut record = vcf::variant::RecordBuf::builder()
186 /// .set_reference_bases("A")
187 /// .build();
188 ///
189 /// *record.reference_bases_mut() = String::from("T");
190 ///
191 /// assert_eq!(record.reference_bases(), "T");
192 /// ```
193 pub fn reference_bases_mut(&mut self) -> &mut String {
194 &mut self.reference_bases
195 }
196
197 /// Returns the alternate bases of the record.
198 ///
199 /// # Examples
200 ///
201 /// ```
202 /// use noodles_vcf::{self as vcf, variant::record_buf::AlternateBases};
203 ///
204 /// let alternate_bases = AlternateBases::from(vec![String::from("C")]);
205 ///
206 /// let record = vcf::variant::RecordBuf::builder()
207 /// .set_alternate_bases(alternate_bases.clone())
208 /// .build();
209 ///
210 /// assert_eq!(record.alternate_bases(), &alternate_bases);
211 /// ```
212 pub fn alternate_bases(&self) -> &AlternateBases {
213 &self.alternate_bases
214 }
215
216 /// Returns a mutable reference to the alternate bases of the record.
217 ///
218 /// # Examples
219 ///
220 /// ```
221 /// use noodles_vcf::{self as vcf, variant::record_buf::AlternateBases};
222 ///
223 /// let mut record = vcf::variant::RecordBuf::builder()
224 /// .set_reference_bases("A")
225 /// .build();
226 ///
227 /// let alternate_bases = AlternateBases::from(vec![String::from("C")]);
228 /// *record.alternate_bases_mut() = alternate_bases.clone();
229 ///
230 /// assert_eq!(record.alternate_bases(), &alternate_bases);
231 /// ```
232 pub fn alternate_bases_mut(&mut self) -> &mut AlternateBases {
233 &mut self.alternate_bases
234 }
235
236 /// Returns the quality score of the record.
237 ///
238 /// # Examples
239 ///
240 /// ```
241 /// use noodles_vcf as vcf;
242 ///
243 /// let record = vcf::variant::RecordBuf::builder()
244 /// .set_quality_score(13.0)
245 /// .build();
246 ///
247 /// assert_eq!(record.quality_score(), Some(13.0));
248 /// ```
249 pub fn quality_score(&self) -> Option<f32> {
250 self.quality_score
251 }
252
253 /// Returns a mutable reference to the quality score.
254 ///
255 /// # Examples
256 ///
257 /// ```
258 /// use noodles_vcf as vcf;
259 ///
260 /// let mut record = vcf::variant::RecordBuf::default();
261 /// *record.quality_score_mut() = Some(13.0);
262 /// assert_eq!(record.quality_score(), Some(13.0));
263 /// ```
264 pub fn quality_score_mut(&mut self) -> &mut Option<f32> {
265 &mut self.quality_score
266 }
267
268 /// Returns the filters of the record.
269 ///
270 /// The filters can either be pass (`PASS`), a list of filter names that caused the record to
271 /// fail, (e.g., `q10`), or missing (`.`).
272 ///
273 /// # Examples
274 ///
275 /// ```
276 /// use noodles_vcf::{self as vcf, variant::record_buf::Filters};
277 ///
278 /// let record = vcf::variant::RecordBuf::builder()
279 /// .set_filters(Filters::pass())
280 /// .build();
281 ///
282 /// assert!(record.filters().is_pass());
283 /// ```
284 pub fn filters(&self) -> &Filters {
285 &self.filters
286 }
287
288 /// Returns a mutable reference to the filters.
289 ///
290 /// # Examples
291 ///
292 /// ```
293 /// use noodles_vcf::{self as vcf, variant::record_buf::Filters};
294 ///
295 /// let mut record = vcf::variant::RecordBuf::default();
296 /// *record.filters_mut() = Filters::pass();
297 /// assert!(record.filters().is_pass());
298 /// ```
299 pub fn filters_mut(&mut self) -> &mut Filters {
300 &mut self.filters
301 }
302
303 /// Returns the addition information of the record.
304 ///
305 /// # Examples
306 ///
307 /// ```
308 /// use noodles_vcf::{
309 /// self as vcf,
310 /// variant::{
311 /// record::info::field::key,
312 /// record_buf::{info::field::Value, Info},
313 /// },
314 /// };
315 ///
316 /// let info: Info = [
317 /// (String::from(key::SAMPLES_WITH_DATA_COUNT), Some(Value::from(3))),
318 /// (String::from(key::ALLELE_FREQUENCIES), Some(Value::from(vec![Some(0.5)]))),
319 /// ]
320 /// .into_iter()
321 /// .collect();
322 ///
323 /// let record = vcf::variant::RecordBuf::builder()
324 /// .set_info(info.clone())
325 /// .build();
326 ///
327 /// assert_eq!(record.info(), &info);
328 /// ```
329 pub fn info(&self) -> &Info {
330 &self.info
331 }
332
333 /// Returns a mutable reference to the additional info fields.
334 ///
335 /// # Examples
336 ///
337 /// ```
338 /// use noodles_vcf::{
339 /// self as vcf,
340 /// variant::{
341 /// record::info::field::key,
342 /// record_buf::{info::field::Value, Info},
343 /// }
344 /// };
345 ///
346 /// let info: Info = [
347 /// (String::from(key::SAMPLES_WITH_DATA_COUNT), Some(Value::from(3))),
348 /// (String::from(key::ALLELE_FREQUENCIES), Some(Value::from(vec![Some(0.5)]))),
349 /// ]
350 /// .into_iter()
351 /// .collect();
352 ///
353 /// let mut record = vcf::variant::RecordBuf::builder()
354 /// .set_info(info)
355 /// .build();
356 ///
357 /// record.info_mut().insert(String::from(key::TOTAL_DEPTH), Some(Value::Integer(13)));
358 ///
359 /// let expected = [
360 /// (String::from(key::SAMPLES_WITH_DATA_COUNT), Some(Value::Integer(3))),
361 /// (String::from(key::ALLELE_FREQUENCIES), Some(Value::from(vec![Some(0.5)]))),
362 /// (String::from(key::TOTAL_DEPTH), Some(Value::Integer(13))),
363 /// ]
364 /// .into_iter()
365 /// .collect();
366 ///
367 /// assert_eq!(record.info(), &expected);
368 /// ```
369 pub fn info_mut(&mut self) -> &mut Info {
370 &mut self.info
371 }
372
373 /// Returns the format of the genotypes of the record.
374 ///
375 /// # Examples
376 ///
377 /// ```
378 /// use noodles_vcf::{
379 /// self as vcf,
380 /// variant::{
381 /// record::samples::keys::key,
382 /// record_buf::{samples::{sample::Value, Keys}, Samples},
383 /// },
384 /// };
385 ///
386 /// let keys: Keys = [
387 /// String::from(key::GENOTYPE),
388 /// String::from(key::CONDITIONAL_GENOTYPE_QUALITY),
389 /// ].into_iter().collect();
390 /// let samples = Samples::new(
391 /// keys.clone(),
392 /// vec![vec![Some(Value::from("0|0")), Some(Value::from(13))]],
393 /// );
394 ///
395 /// let record = vcf::variant::RecordBuf::builder()
396 /// .set_samples(samples)
397 /// .build();
398 ///
399 /// assert_eq!(record.format(), &keys);
400 /// ```
401 pub fn format(&self) -> &samples::Keys {
402 self.samples.keys()
403 }
404
405 /// Returns the genotypes of the record.
406 ///
407 /// # Examples
408 ///
409 /// ```
410 /// use noodles_vcf::{
411 /// self as vcf,
412 /// variant::{
413 /// record::samples::keys::key,
414 /// record_buf::{samples::sample::Value, Samples},
415 /// },
416 /// };
417 ///
418 /// let keys = [
419 /// String::from(key::GENOTYPE),
420 /// String::from(key::CONDITIONAL_GENOTYPE_QUALITY),
421 /// ].into_iter().collect();
422 /// let samples = Samples::new(
423 /// keys,
424 /// vec![vec![Some(Value::from("0|0")), Some(Value::from(13))]],
425 /// );
426 ///
427 /// let record = vcf::variant::RecordBuf::builder()
428 /// .set_samples(samples.clone())
429 /// .build();
430 ///
431 /// assert_eq!(record.samples(), &samples);
432 /// ```
433 pub fn samples(&self) -> &Samples {
434 &self.samples
435 }
436
437 /// Returns a mutable reference to the genotypes of the record.
438 ///
439 /// # Examples
440 ///
441 /// ```
442 /// use noodles_vcf::{
443 /// self as vcf,
444 /// variant::{
445 /// record::samples::keys::key,
446 /// record_buf::{samples::sample::Value, Samples},
447 /// },
448 /// };
449 ///
450 /// let mut record = vcf::variant::RecordBuf::default();
451 ///
452 /// let keys = [
453 /// String::from(key::GENOTYPE),
454 /// String::from(key::CONDITIONAL_GENOTYPE_QUALITY),
455 /// ].into_iter().collect();
456 /// let samples = Samples::new(
457 /// keys,
458 /// vec![vec![Some(Value::from("0|0")), Some(Value::from(13))]],
459 /// );
460 ///
461 /// *record.samples_mut() = samples.clone();
462 ///
463 /// assert_eq!(record.samples(), &samples);
464 /// ```
465 pub fn samples_mut(&mut self) -> &mut Samples {
466 &mut self.samples
467 }
468}
469
470impl Default for RecordBuf {
471 fn default() -> Self {
472 Self {
473 reference_sequence_name: String::from("."),
474 variant_start: Some(Position::MIN),
475 ids: Ids::default(),
476 reference_bases: String::from("N"),
477 alternate_bases: AlternateBases::default(),
478 quality_score: None,
479 filters: Filters::default(),
480 info: Info::default(),
481 samples: Samples::default(),
482 }
483 }
484}
485
486impl super::Record for RecordBuf {
487 fn reference_sequence_name<'a, 'h: 'a>(&'a self, _: &'h Header) -> io::Result<&'a str> {
488 Ok(self.reference_sequence_name())
489 }
490
491 fn variant_start(&self) -> Option<std::io::Result<Position>> {
492 self.variant_start().map(Ok)
493 }
494
495 fn ids(&self) -> Box<dyn super::record::Ids + '_> {
496 Box::new(self.ids())
497 }
498
499 fn reference_bases(&self) -> Box<dyn super::record::ReferenceBases + '_> {
500 Box::new(self.reference_bases())
501 }
502
503 fn alternate_bases(&self) -> Box<dyn super::record::AlternateBases + '_> {
504 Box::new(self.alternate_bases())
505 }
506
507 fn quality_score(&self) -> Option<std::io::Result<f32>> {
508 self.quality_score().map(Ok)
509 }
510
511 fn filters(&self) -> Box<dyn super::record::Filters + '_> {
512 Box::new(self.filters())
513 }
514
515 fn info(&self) -> Box<dyn super::record::Info + '_> {
516 Box::new(self.info())
517 }
518
519 fn samples(&self) -> io::Result<Box<dyn super::record::Samples + '_>> {
520 Ok(Box::new(self.samples()))
521 }
522}
523
524#[cfg(test)]
525mod tests {
526 use super::*;
527
528 #[test]
529 fn test_default() -> Result<(), Box<dyn std::error::Error>> {
530 let actual = RecordBuf::default();
531
532 let expected = RecordBuf::builder()
533 .set_reference_sequence_name(".")
534 .set_variant_start(Position::MIN)
535 .set_reference_bases("N")
536 .build();
537
538 assert_eq!(actual, expected);
539
540 Ok(())
541 }
542}