Skip to main content

windows_metadata/reader/
row.rs

1use super::*;
2
3#[derive(Copy, Clone)]
4pub struct Row<'a> {
5    pub index: &'a Index,
6    pub file: usize,
7    pub pos: usize,
8}
9
10impl std::fmt::Debug for Row<'_> {
11    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
12        f.debug_struct("Row")
13            .field("file", &self.file)
14            .field("pos", &self.pos)
15            .finish()
16    }
17}
18
19impl std::hash::Hash for Row<'_> {
20    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
21        self.file.hash(state);
22        self.pos.hash(state);
23    }
24}
25
26impl PartialEq for Row<'_> {
27    fn eq(&self, other: &Self) -> bool {
28        (self.file, self.pos) == (other.file, other.pos)
29    }
30}
31
32impl Eq for Row<'_> {}
33
34impl Ord for Row<'_> {
35    fn cmp(&self, other: &Self) -> Ordering {
36        (self.file, self.pos).cmp(&(other.file, other.pos))
37    }
38}
39
40impl PartialOrd for Row<'_> {
41    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
42        Some(self.cmp(other))
43    }
44}
45
46impl<'a> Row<'a> {
47    pub(crate) fn new(index: &'a Index, file: usize, pos: usize) -> Self {
48        Self { index, file, pos }
49    }
50}
51
52pub trait AsRow<'a>: Copy {
53    const TABLE: usize;
54    fn to_row(&self) -> Row<'a>;
55    fn from_row(row: Row<'a>) -> Self;
56
57    fn index(&self) -> &'a Index {
58        let row = self.to_row();
59        row.index
60    }
61
62    fn file(&self) -> &'a File {
63        let row = self.to_row();
64        row.index.files(row.file)
65    }
66
67    fn pos(&self) -> usize {
68        self.to_row().pos
69    }
70
71    fn usize(&self, column: usize) -> usize {
72        self.file().usize(self.pos(), Self::TABLE, column)
73    }
74
75    fn str(&self, column: usize) -> &'a str {
76        self.file().str(self.pos(), Self::TABLE, column)
77    }
78
79    fn row<R: AsRow<'a>>(&self, column: usize) -> R {
80        let row = self.to_row();
81        R::from_row(Row::new(row.index, row.file, self.usize(column) - 1))
82    }
83
84    fn decode<T: Decode<'a>>(&self, column: usize) -> T {
85        let row = self.to_row();
86        T::decode(row.index, row.file, self.usize(column))
87    }
88
89    fn blob(&self, column: usize) -> Blob<'a> {
90        let row = self.to_row();
91        Blob::new(
92            row.index,
93            row.file,
94            self.file().blob(self.pos(), Self::TABLE, column),
95        )
96    }
97
98    fn list<R: AsRow<'a>>(&self, column: usize) -> RowIterator<'a, R> {
99        let row = self.to_row();
100        RowIterator::new(
101            row.index,
102            row.file,
103            self.file().list(self.pos(), Self::TABLE, column, R::TABLE),
104        )
105    }
106
107    fn equal_range<L: AsRow<'a>>(&self, column: usize, value: usize) -> RowIterator<'a, L> {
108        let row = self.to_row();
109
110        RowIterator::new(
111            row.index,
112            row.file,
113            self.file().equal_range(L::TABLE, column, value),
114        )
115    }
116
117    fn parent_row<P: AsRow<'a>>(&self, column: usize) -> P {
118        let row = self.to_row();
119
120        P::from_row(Row::new(
121            row.index,
122            row.file,
123            self.file().parent(self.pos(), P::TABLE, column),
124        ))
125    }
126}
127
128pub struct RowIterator<'a, R: AsRow<'a>> {
129    index: &'a Index,
130    file: usize,
131    rows: std::ops::Range<usize>,
132    phantom: std::marker::PhantomData<R>,
133}
134
135impl<'a, R: AsRow<'a>> RowIterator<'a, R> {
136    pub(crate) fn new(index: &'a Index, file: usize, rows: std::ops::Range<usize>) -> Self {
137        Self {
138            index,
139            file,
140            rows,
141            phantom: std::marker::PhantomData,
142        }
143    }
144}
145
146impl<'a, R: AsRow<'a>> Iterator for RowIterator<'a, R> {
147    type Item = R;
148
149    fn next(&mut self) -> Option<Self::Item> {
150        self.rows
151            .next()
152            .map(|row| R::from_row(Row::new(self.index, self.file, row)))
153    }
154}
155
156impl<'a, R: AsRow<'a>> ExactSizeIterator for RowIterator<'a, R> {
157    fn len(&self) -> usize {
158        self.rows.len()
159    }
160}
161
162pub trait HasAttributes<'a> {
163    fn attributes(&self) -> RowIterator<'a, Attribute<'a>>;
164    fn find_attribute(&self, name: &str) -> Option<Attribute<'a>>;
165    fn has_attribute(&self, name: &str) -> bool;
166    fn arches(&self) -> i32;
167}
168
169impl<'a, R: AsRow<'a> + Into<HasAttribute<'a>>> HasAttributes<'a> for R {
170    fn attributes(&self) -> RowIterator<'a, Attribute<'a>> {
171        self.equal_range(0, Into::<HasAttribute>::into(*self).encode())
172    }
173
174    fn find_attribute(&self, name: &str) -> Option<Attribute<'a>> {
175        self.attributes()
176            .find(|attribute| attribute.ctor().parent().name() == name)
177    }
178
179    fn has_attribute(&self, name: &str) -> bool {
180        self.find_attribute(name).is_some()
181    }
182
183    fn arches(&self) -> i32 {
184        let mut arches = 0;
185
186        if let Some(attribute) = self.find_attribute("SupportedArchitectureAttribute") {
187            arches = match attribute.value().first() {
188                Some((_, Value::I32(v))) => *v,
189                Some((_, Value::EnumValue(_, inner))) => {
190                    if let Value::I32(v) = inner.as_ref() {
191                        *v
192                    } else {
193                        0
194                    }
195                }
196                _ => 0,
197            };
198        }
199
200        arches
201    }
202}