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
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
use indexmap::IndexMap;
use alloc::vec::Vec;
use crate::iter::*;

/// The contents of a ListInfo DAT file.
#[derive(Debug)]
pub struct DatDocument<'a> {
    pub(crate) document: IndexMap<&'a str, Vec<EntryFragment<'a>>>,
}

impl<'a> DatDocument<'a> {
    /// Get DAT entries with the given key as an iterator
    pub fn entry(&'a self, key: &str) -> Option<impl Iterator<Item = &EntryFragment<'a>>> {
        self.document.get(key).map(|f| f.iter())
    }

    /// Gets an key value iterator over the fragments of the entry.
    pub fn iter(&'a self) -> SliceIter<'a, EntryFragment<'a>> {
        SliceIter::new(self.document.iter())
    }
}

/// The contents of a sub-entry (such as `rom` or `disk`) that is a child of a ListInfo entry.
///
/// Sub-entries can not contain their own sub-entries and can only contain scalars or lists of scalars.
/// For example, the `rom` entries in the following fragment are sub-entries.
/// 
/// ```listinfo
/// game (
///  rom (name "Rom 1")
///  rom (name "Rom 2")
/// )
/// ```
#[derive(Debug, Eq, PartialEq)]
pub struct SubEntry<'a> {
    pub(crate) keys: IndexMap<&'a str, Node<&'a str>>,
}

impl<'a> SubEntry<'a> {
    /// Retrieves the value of an item data value in the sub-entry.
    pub fn value(&'a self, key: &str) -> Option<&'a Node<&'a str>> {
        self.keys.get(key)
    }

    /// Gets the entry node with the given key if it exists.
    ///
    /// This is shorthand for `subentry.value("key").map(|f| f.unique().as_ref())`
    pub fn value_unique(&'a self, key: &str) -> Option<&'a str> {
        self.keys.get(key).map(|f| f.unique().as_ref())
    }

    /// Gets the values with the given key if it exists.
    ///
    /// This is shorthand for `fragment.value("key").map(|f| f.iter().map(|&s| s))`
    pub fn value_iter(&'a self, key: &str) -> Option<impl Iterator<Item = &'a str>> {
        self.keys.get(key).map(|f| f.iter().map(|&s| s))
    }

    /// Gets a key value iterator over the values of this fragment.
    pub fn iter(&'a self) -> EntryIter<'a, &'a str, Node<&'a str>> {
        EntryIter::new(self.keys.iter())
    }
}

/// Represents an item data value of an entry.
#[derive(Debug, Eq, PartialEq)]
pub enum EntryData<'a> {
    /// A scalar string entry
    Scalar(&'a str),
    /// A sub-entry (such as `rom`, for example)
    SubEntry(SubEntry<'a>),
}

/// Represents nodes with the given key in an ListInfo entry.
///
/// The split between `Unique` and `Many` is mostly for performance reasons
/// to avoid unnecessary allocations. `Node::Unique` appeared exactly once in 
/// the parsed DAT file, while `Node::Unique` appeared more than once.
///
/// Instead of accessing the enum members directly, the `Node::iter` and `Node::unique`
/// methods abstract over the difference between `Unique` and `Many` for convenience.
#[derive(Debug, Eq, PartialEq)]
pub enum Node<T> {
    /// A uniquely keyed node (only one of such key exists in the entry)
    Unique(T),
    /// Multiple nodes with the same key.
    Many(Vec<T>),
}

impl<'a, T> Node<T> {
    /// Gets the values with the given key.
    ///
    /// If the provided key is a unique value, returns an iterator that yields
    /// that single value.
    pub fn iter(&'a self) -> NodeIter<'a, T> {
        NodeIter::new(self)
    }

    /// Gets a single value with the given key.
    ///
    /// If the provided key is not unique, retrieves the first
    /// value of the many-set with the given key.
    pub fn unique(&'a self) -> &T {
        match self {
            Node::Unique(entry) => entry,
            // Node::Many must have vec of arity 2 or more
            // Any other situation is a bug, and should panic.
            Node::Many(entries) => entries.first().unwrap(),
        }
    }
}

/// Represents a single ListInfo entry fragment.
///
/// An entry fragment is a top level element in a ListInfo DAT document.
///
/// The following is an example of a `clrmamepro` fragment with a `name` element.
///
/// ```listinfo
/// clrmamepro (
///   name "DAT file."
/// )
/// ```
#[derive(Debug)]
pub struct EntryFragment<'a> {
    keys: IndexMap<&'a str, Node<EntryData<'a>>>,
}

impl<'a> EntryFragment<'a> {
    #[doc(hidden)]
    pub(crate) fn new(keys: IndexMap<&'a str, Node<EntryData<'a>>>) -> Self {
        EntryFragment { keys }
    }

    /// Gets the entry node with the given key if it exists.
    pub fn entry(&'a self, key: &str) -> Option<&'a Node<EntryData<'a>>> {
        self.keys.get(key)
    }

    /// Gets the entry node with the given key if it exists.
    ///
    /// This is shorthand for `fragment.entry("key").map(|f| f.unique())`
    pub fn entry_unique(&'a self, key: &str) -> Option<&'a EntryData> {
        self.keys.get(key).map(|f| f.unique())
    }

    /// Gets the values with the given key if it exists.
    ///
    /// This is shorthand for `fragment.entry("key").map(|f| f.iter())`
    pub fn entry_iter(&'a self, key: &str) -> Option<impl Iterator<Item = &'a EntryData>> {
        self.keys.get(key).map(|f| f.iter())
    }

    /// Gets an key value iterator over the entries of this fragment.
    pub fn iter(&'a self) -> EntryIter<'a, &'a str, Node<EntryData<'a>>> {
        EntryIter::new(self.keys.iter())
    }
}