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 crate::iter::*;
use alloc::vec::Vec;
use indexmap::IndexMap;
/// 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())
}
/// 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().copied())
}
/// 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())
}
}