noodles_sam/alignment/record_buf/data/field/
value.rs1mod array;
4
5use bstr::BString;
6
7pub use self::array::Array;
8use crate::alignment::record::data::field::Type;
9
10#[derive(Clone, Debug, PartialEq)]
12pub enum Value {
13 Character(u8),
15 Int8(i8),
17 UInt8(u8),
19 Int16(i16),
21 UInt16(u16),
23 Int32(i32),
25 UInt32(u32),
27 Float(f32),
29 String(BString),
31 Hex(BString),
33 Array(Array),
35}
36
37impl Value {
38 pub fn ty(&self) -> Type {
47 match self {
48 Self::Character(_) => Type::Character,
49 Self::Int8(_) => Type::Int8,
50 Self::UInt8(_) => Type::UInt8,
51 Self::Int16(_) => Type::Int16,
52 Self::UInt16(_) => Type::UInt16,
53 Self::Int32(_) => Type::Int32,
54 Self::UInt32(_) => Type::UInt32,
55 Self::Float(_) => Type::Float,
56 Self::String(_) => Type::String,
57 Self::Hex(_) => Type::Hex,
58 Self::Array(_) => Type::Array,
59 }
60 }
61
62 pub fn as_int(&self) -> Option<i64> {
75 match self {
76 Self::Int8(n) => Some(i64::from(*n)),
77 Self::UInt8(n) => Some(i64::from(*n)),
78 Self::Int16(n) => Some(i64::from(*n)),
79 Self::UInt16(n) => Some(i64::from(*n)),
80 Self::Int32(n) => Some(i64::from(*n)),
81 Self::UInt32(n) => Some(i64::from(*n)),
82 _ => None,
83 }
84 }
85
86 pub fn is_int(&self) -> bool {
96 matches!(
97 self,
98 Self::Int8(_)
99 | Self::UInt8(_)
100 | Self::Int16(_)
101 | Self::UInt16(_)
102 | Self::Int32(_)
103 | Self::UInt32(_)
104 )
105 }
106}
107
108impl From<i8> for Value {
109 fn from(n: i8) -> Self {
110 if n >= 0 {
111 Self::from(n as u8)
112 } else {
113 Self::Int8(n)
114 }
115 }
116}
117
118impl From<u8> for Value {
119 fn from(n: u8) -> Self {
120 Self::UInt8(n)
121 }
122}
123
124impl From<i16> for Value {
125 fn from(n: i16) -> Self {
126 if n >= 0 {
127 Self::from(n as u16)
128 } else if n >= i16::from(i8::MIN) {
129 Self::Int8(n as i8)
130 } else {
131 Self::Int16(n)
132 }
133 }
134}
135
136impl From<u16> for Value {
137 fn from(n: u16) -> Self {
138 if n <= u16::from(u8::MAX) {
139 Self::UInt8(n as u8)
140 } else {
141 Self::UInt16(n)
142 }
143 }
144}
145
146impl From<i32> for Value {
147 fn from(n: i32) -> Self {
148 if n >= 0 {
149 Self::from(n as u32)
150 } else if n >= i32::from(i8::MIN) {
151 Self::Int8(n as i8)
152 } else if n >= i32::from(i16::MIN) {
153 Self::Int16(n as i16)
154 } else {
155 Self::Int32(n)
156 }
157 }
158}
159
160impl From<u32> for Value {
161 fn from(n: u32) -> Self {
162 if n <= u32::from(u8::MAX) {
163 Self::UInt8(n as u8)
164 } else if n <= u32::from(u16::MAX) {
165 Self::UInt16(n as u16)
166 } else {
167 Self::UInt32(n)
168 }
169 }
170}
171
172impl From<f32> for Value {
173 fn from(n: f32) -> Self {
174 Value::Float(n)
175 }
176}
177
178impl From<&str> for Value {
179 fn from(s: &str) -> Self {
180 Self::String(s.into())
181 }
182}
183
184impl From<String> for Value {
185 fn from(s: String) -> Self {
186 Self::String(s.into())
187 }
188}
189
190impl From<Vec<i8>> for Value {
191 fn from(values: Vec<i8>) -> Self {
192 Value::Array(Array::Int8(values))
193 }
194}
195
196impl From<Vec<u8>> for Value {
197 fn from(values: Vec<u8>) -> Self {
198 Value::Array(Array::UInt8(values))
199 }
200}
201
202impl From<Vec<i16>> for Value {
203 fn from(values: Vec<i16>) -> Self {
204 Value::Array(Array::Int16(values))
205 }
206}
207
208impl From<Vec<u16>> for Value {
209 fn from(values: Vec<u16>) -> Self {
210 Value::Array(Array::UInt16(values))
211 }
212}
213
214impl From<Vec<i32>> for Value {
215 fn from(values: Vec<i32>) -> Self {
216 Value::Array(Array::Int32(values))
217 }
218}
219
220impl From<Vec<u32>> for Value {
221 fn from(values: Vec<u32>) -> Self {
222 Value::Array(Array::UInt32(values))
223 }
224}
225
226impl From<Vec<f32>> for Value {
227 fn from(values: Vec<f32>) -> Self {
228 Value::Array(Array::Float(values))
229 }
230}
231
232impl TryFrom<i64> for Value {
233 type Error = crate::io::reader::record_buf::data::field::value::ParseError;
234
235 fn try_from(n: i64) -> Result<Self, Self::Error> {
236 const MIN: i64 = i32::MIN as i64;
237 const MAX: i64 = u32::MAX as i64;
238
239 if n > MAX {
240 Err(Self::Error::InvalidIntegerValue)
241 } else if n >= 0 {
242 Ok(Self::from(n as u32))
243 } else if n >= i64::from(i8::MIN) {
244 Ok(Self::Int8(n as i8))
245 } else if n >= i64::from(i16::MIN) {
246 Ok(Self::Int16(n as i16))
247 } else if n >= MIN {
248 Ok(Self::Int32(n as i32))
249 } else {
250 Err(Self::Error::InvalidIntegerValue)
251 }
252 }
253}
254
255impl<'a> From<&'a Value> for crate::alignment::record::data::field::Value<'a> {
256 fn from(value_buf: &'a Value) -> Self {
257 match value_buf {
258 Value::Character(c) => Self::Character(*c),
259 Value::Int8(n) => Self::Int8(*n),
260 Value::UInt8(n) => Self::UInt8(*n),
261 Value::Int16(n) => Self::Int16(*n),
262 Value::UInt16(n) => Self::UInt16(*n),
263 Value::Int32(n) => Self::Int32(*n),
264 Value::UInt32(n) => Self::UInt32(*n),
265 Value::Float(n) => Self::Float(*n),
266 Value::String(s) => Self::String(s.as_ref()),
267 Value::Hex(s) => Self::Hex(s.as_ref()),
268 Value::Array(array) => Self::Array(array.into()),
269 }
270 }
271}
272
273#[cfg(test)]
274mod tests {
275 use super::*;
276
277 #[test]
278 fn test_ty() {
279 assert_eq!(Value::Character(b'n').ty(), Type::Character);
280 assert_eq!(Value::Int32(0).ty(), Type::Int32);
281 assert_eq!(Value::Float(0.0).ty(), Type::Float);
282 assert_eq!(Value::from("noodles").ty(), Type::String);
283 assert_eq!(Value::Hex(b"CAFE".into()).ty(), Type::Hex);
284 assert_eq!(Value::Array(Array::UInt8(vec![0])).ty(), Type::Array);
285 }
286
287 #[test]
288 fn test_from_i8_for_value() {
289 assert_eq!(Value::from(i8::MIN), Value::Int8(i8::MIN));
290 assert_eq!(Value::from(-1i8), Value::Int8(-1));
291
292 assert_eq!(Value::from(0i8), Value::UInt8(0));
293 assert_eq!(Value::from(1i8), Value::UInt8(1));
294 assert_eq!(Value::from(i8::MAX), Value::UInt8(i8::MAX as u8));
295 }
296
297 #[test]
298 fn test_from_u8_for_value() {
299 assert_eq!(Value::from(u8::MIN), Value::UInt8(u8::MIN));
300 assert_eq!(Value::from(u8::MAX), Value::UInt8(u8::MAX));
301 }
302
303 #[test]
304 fn test_from_i16_for_value() {
305 assert_eq!(Value::from(i16::MIN), Value::Int16(i16::MIN));
306 assert_eq!(Value::from(-129i16), Value::Int16(-129)); assert_eq!(Value::from(-128i16), Value::Int8(-128)); assert_eq!(Value::from(-1i16), Value::Int8(-1));
310
311 assert_eq!(Value::from(0i16), Value::UInt8(0));
312 assert_eq!(Value::from(1i16), Value::UInt8(1));
313 assert_eq!(Value::from(255i16), Value::UInt8(255)); assert_eq!(Value::from(256i16), Value::UInt16(256)); assert_eq!(Value::from(i16::MAX), Value::UInt16(i16::MAX as u16));
317 }
318
319 #[test]
320 fn test_from_u16_for_value() {
321 assert_eq!(Value::from(u16::MIN), Value::UInt8(0));
322 assert_eq!(Value::from(255u16), Value::UInt8(255));
323
324 assert_eq!(Value::from(256u16), Value::UInt16(256));
325 assert_eq!(Value::from(u16::MAX), Value::UInt16(u16::MAX));
326 }
327
328 #[test]
329 fn test_from_i32_for_value() {
330 assert_eq!(Value::from(i32::MIN), Value::Int32(i32::MIN));
331 assert_eq!(Value::from(-32769i32), Value::Int32(-32769)); assert_eq!(Value::from(-32768i32), Value::Int16(-32768)); assert_eq!(Value::from(-129i32), Value::Int16(-129)); assert_eq!(Value::from(-128i32), Value::Int8(-128)); assert_eq!(Value::from(-1i32), Value::Int8(-1));
338
339 assert_eq!(Value::from(0i32), Value::UInt8(0));
340 assert_eq!(Value::from(1i32), Value::UInt8(1));
341 assert_eq!(Value::from(255i32), Value::UInt8(255)); assert_eq!(Value::from(256i32), Value::UInt16(256)); assert_eq!(Value::from(65535i32), Value::UInt16(65535)); assert_eq!(Value::from(65536i32), Value::UInt32(65536)); assert_eq!(Value::from(i32::MAX), Value::UInt32(i32::MAX as u32));
348 }
349
350 #[test]
351 fn test_from_u32_for_value() {
352 assert_eq!(Value::from(u32::MIN), Value::UInt8(0));
353 assert_eq!(Value::from(255u32), Value::UInt8(255)); assert_eq!(Value::from(256u32), Value::UInt16(256)); assert_eq!(Value::from(65535u32), Value::UInt16(65535)); assert_eq!(Value::from(65536u32), Value::UInt32(65536)); assert_eq!(Value::from(u32::MAX), Value::UInt32(u32::MAX));
360 }
361
362 #[test]
363 fn test_from_f32_for_value() {
364 assert_eq!(Value::from(0.0f32), Value::Float(0.0));
365 }
366
367 #[test]
368 fn test_from_vec_i8_for_value() {
369 assert_eq!(Value::from(vec![0i8]), Value::Array(Array::Int8(vec![0])));
370 }
371
372 #[test]
373 fn test_from_vec_u8_for_value() {
374 assert_eq!(Value::from(vec![0u8]), Value::Array(Array::UInt8(vec![0])));
375 }
376
377 #[test]
378 fn test_from_vec_i16_for_value() {
379 assert_eq!(Value::from(vec![0i16]), Value::Array(Array::Int16(vec![0])));
380 }
381
382 #[test]
383 fn test_from_vec_u16_for_value() {
384 assert_eq!(
385 Value::from(vec![0u16]),
386 Value::Array(Array::UInt16(vec![0]))
387 );
388 }
389
390 #[test]
391 fn test_from_vec_i32_for_value() {
392 assert_eq!(Value::from(vec![0i32]), Value::Array(Array::Int32(vec![0])));
393 }
394
395 #[test]
396 fn test_from_vec_u32_for_value() {
397 assert_eq!(
398 Value::from(vec![0u32]),
399 Value::Array(Array::UInt32(vec![0]))
400 );
401 }
402
403 #[test]
404 fn test_from_vec_f32_for_value() {
405 assert_eq!(
406 Value::from(vec![0.0f32]),
407 Value::Array(Array::Float(vec![0.0]))
408 );
409 }
410
411 #[test]
412 fn test_try_from_i64_for_value(
413 ) -> Result<(), crate::io::reader::record_buf::data::field::value::ParseError> {
414 use crate::io::reader::record_buf::data::field::value::ParseError;
415
416 fn t(n: i64, expected: Value) -> Result<(), ParseError> {
417 let actual = Value::try_from(n)?;
418 assert_eq!(actual, expected);
419 Ok(())
420 }
421
422 assert_eq!(
423 Value::try_from(-2147483649i64),
424 Err(ParseError::InvalidIntegerValue)
425 );
426
427 t(-2147483648, Value::Int32(i32::MIN))?;
428 t(-2147483647, Value::Int32(-2147483647))?;
429
430 t(-32769, Value::Int32(-32769))?;
431 t(-32768, Value::Int16(i16::MIN))?;
432 t(-32767, Value::Int16(-32767))?;
433
434 t(-129, Value::Int16(-129))?;
435 t(-128, Value::Int8(i8::MIN))?;
436 t(-127, Value::Int8(-127))?;
437
438 t(-1, Value::Int8(-1))?;
439 t(0, Value::UInt8(0))?;
440 t(1, Value::UInt8(1))?;
441
442 t(254, Value::UInt8(254))?;
443 t(255, Value::UInt8(u8::MAX))?;
444 t(256, Value::UInt16(256))?;
445
446 t(65534, Value::UInt16(65534))?;
447 t(65535, Value::UInt16(u16::MAX))?;
448 t(65536, Value::UInt32(65536))?;
449
450 t(4294967294, Value::UInt32(4294967294))?;
451 t(4294967295, Value::UInt32(u32::MAX))?;
452
453 assert_eq!(
454 Value::try_from(4294967296i64),
455 Err(ParseError::InvalidIntegerValue)
456 );
457
458 Ok(())
459 }
460}