noodles_sam/record/data/field/
value.rs1mod array;
4pub mod base_modifications;
5mod integer;
6
7pub use self::base_modifications::BaseModifications;
8
9use std::io;
10
11use bstr::{BStr, ByteSlice};
12
13use self::{array::parse_array, integer::parse_integer_value};
14use super::Type;
15use crate::alignment::record::data::field::Value;
16
17pub(super) fn parse_value<'a>(src: &mut &'a [u8], ty: Type) -> io::Result<Value<'a>> {
18 match ty {
19 Type::Character => parse_character_value(src),
20 Type::Integer => parse_integer_value(src),
21 Type::Float => parse_float_value(src),
22 Type::String => Ok(parse_string_value(src)),
23 Type::Hex => Ok(parse_hex_value(src)),
24 Type::Array => parse_array(src).map(Value::Array),
25 }
26}
27
28fn parse_character_value<'a>(src: &mut &'a [u8]) -> io::Result<Value<'a>> {
29 if let Some((b, rest)) = src.split_first() {
30 *src = rest;
31 Ok(Value::Character(*b))
32 } else {
33 Err(io::Error::from(io::ErrorKind::UnexpectedEof))
34 }
35}
36
37fn parse_float_value<'a>(src: &mut &'a [u8]) -> io::Result<Value<'a>> {
38 let (n, i) = lexical_core::parse_partial(src)
39 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
40
41 *src = &src[i..];
42
43 Ok(Value::Float(n))
44}
45
46fn parse_string<'a>(src: &mut &'a [u8]) -> &'a BStr {
47 const DELIMITER: u8 = b'\t';
48
49 let i = src.as_bstr().find_byte(DELIMITER).unwrap_or(src.len());
50 let (buf, rest) = src.split_at(i);
51 *src = rest;
52 buf.as_bstr()
53}
54
55fn parse_string_value<'a>(src: &mut &'a [u8]) -> Value<'a> {
56 Value::String(parse_string(src))
57}
58
59fn parse_hex_value<'a>(src: &mut &'a [u8]) -> Value<'a> {
60 Value::Hex(parse_string(src))
61}
62
63#[cfg(test)]
64mod tests {
65 use super::*;
66
67 #[test]
68 fn test_parse_value() -> io::Result<()> {
69 let mut src = &b"n"[..];
70 assert!(matches!(
71 parse_value(&mut src, Type::Character)?,
72 Value::Character(b'n')
73 ));
74
75 let mut src = &b"0"[..];
76 assert!(matches!(
77 parse_value(&mut src, Type::Integer)?,
78 Value::Int32(0)
79 ));
80
81 let mut src = &b"0.0"[..];
82 assert!(matches!(
83 parse_value(&mut src, Type::Float)?,
84 Value::Float(n) if n == 0.0
85 ));
86
87 let mut src = &b"ndls"[..];
88 assert!(matches!(
89 parse_value(&mut src, Type::String)?,
90 Value::String(s) if s == "ndls"
91 ));
92
93 let mut src = &b"CAFE"[..];
94 assert!(matches!(
95 parse_value(&mut src, Type::Hex)?,
96 Value::Hex(s) if s == "CAFE"
97 ));
98
99 let mut src = &b"C,0"[..];
100 assert!(matches!(
101 parse_value(&mut src, Type::Array)?,
102 Value::Array(_)
103 ));
104
105 Ok(())
106 }
107}