1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
mod value;

use std::io;

use self::value::parse_value;
use crate::{header::record::value::map::info::Type, variant::record::info::field::Value, Header};

pub(super) fn parse_field<'a>(
    src: &mut &'a str,
    header: &Header,
) -> io::Result<(&'a str, Option<Value<'a>>)> {
    use crate::header::record::value::map::info::definition::definition;

    const DELIMITER: char = ';';
    const MAX_COMPONENTS: usize = 2;
    const MISSING: &str = ".";
    const SEPARATOR: char = '=';

    let (buf, rest) = match src.find(DELIMITER) {
        Some(i) => {
            let (buf, rest) = src.split_at(i);
            (buf, &rest[1..])
        }
        None => src.split_at(src.len()),
    };

    *src = rest;

    if buf.is_empty() {
        return Err(io::Error::from(io::ErrorKind::UnexpectedEof));
    }

    let mut components = buf.splitn(MAX_COMPONENTS, SEPARATOR);
    let key = components.next().unwrap_or_default();
    let raw_value = components.next();

    let definition = header
        .infos()
        .get(key)
        .map(|info| (info.number(), info.ty()))
        .or_else(|| definition(header.file_format(), key).map(|(n, t, _)| (n, t)));

    if definition.is_none() && raw_value.is_none() {
        return Ok((key, Some(Value::Flag)));
    }

    let (number, ty) = definition.unwrap_or_default();

    let value = match raw_value {
        Some(MISSING) => None,
        Some(t) => parse_value(t, number, ty).map(Some)?,
        None if ty == Type::Flag => Some(Value::Flag),
        None => return Err(io::Error::new(io::ErrorKind::InvalidData, "missing value")),
    };

    Ok((key, value))
}