windows_metadata/reader/
row.rs1use 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
46unsafe impl Send for Row<'_> {}
47unsafe impl Sync for Row<'_> {}
48
49impl<'a> Row<'a> {
50 pub(crate) fn new(index: &'a Index, file: usize, pos: usize) -> Self {
51 Self { index, file, pos }
52 }
53}
54
55pub trait AsRow<'a>: Copy {
56 const TABLE: usize;
57 fn to_row(&self) -> Row<'a>;
58 fn from_row(row: Row<'a>) -> Self;
59
60 fn index(&self) -> &'a Index {
61 let row = self.to_row();
62 row.index
63 }
64
65 fn file(&self) -> &'a File {
66 let row = self.to_row();
67 row.index.files(row.file)
68 }
69
70 fn pos(&self) -> usize {
71 self.to_row().pos
72 }
73
74 fn usize(&self, column: usize) -> usize {
75 self.file().usize(self.pos(), Self::TABLE, column)
76 }
77
78 fn str(&self, column: usize) -> &'a str {
79 self.file().str(self.pos(), Self::TABLE, column)
80 }
81
82 fn row<R: AsRow<'a>>(&self, column: usize) -> R {
83 let row = self.to_row();
84 R::from_row(Row::new(row.index, row.file, self.usize(column) - 1))
85 }
86
87 fn decode<T: Decode<'a>>(&self, column: usize) -> T {
88 let row = self.to_row();
89 T::decode(row.index, row.file, self.usize(column))
90 }
91
92 fn blob(&self, column: usize) -> Blob<'a> {
93 let row = self.to_row();
94 Blob::new(
95 row.index,
96 row.file,
97 self.file().blob(self.pos(), Self::TABLE, column),
98 )
99 }
100
101 fn list<R: AsRow<'a>>(&self, column: usize) -> RowIterator<'a, R> {
102 let row = self.to_row();
103 RowIterator::new(
104 row.index,
105 row.file,
106 self.file().list(self.pos(), Self::TABLE, column, R::TABLE),
107 )
108 }
109
110 fn equal_range<L: AsRow<'a>>(&self, column: usize, value: usize) -> RowIterator<'a, L> {
111 let row = self.to_row();
112
113 RowIterator::new(
114 row.index,
115 row.file,
116 self.file().equal_range(L::TABLE, column, value),
117 )
118 }
119
120 fn parent_row<P: AsRow<'a>>(&'a self, column: usize) -> P {
121 let row = self.to_row();
122
123 P::from_row(Row::new(
124 row.index,
125 row.file,
126 self.file().parent(self.pos(), P::TABLE, column),
127 ))
128 }
129}
130
131pub struct RowIterator<'a, R: AsRow<'a>> {
132 index: &'a Index,
133 file: usize,
134 rows: std::ops::Range<usize>,
135 phantom: std::marker::PhantomData<R>,
136}
137
138impl<'a, R: AsRow<'a>> RowIterator<'a, R> {
139 pub(crate) fn new(index: &'a Index, file: usize, rows: std::ops::Range<usize>) -> Self {
140 Self {
141 index,
142 file,
143 rows,
144 phantom: std::marker::PhantomData,
145 }
146 }
147}
148
149impl<'a, R: AsRow<'a>> Iterator for RowIterator<'a, R> {
150 type Item = R;
151
152 fn next(&mut self) -> Option<Self::Item> {
153 self.rows
154 .next()
155 .map(|row| R::from_row(Row::new(self.index, self.file, row)))
156 }
157}
158
159pub trait HasAttributes<'a> {
160 fn attributes(&self) -> RowIterator<'a, Attribute<'a>>;
161 fn find_attribute(&self, name: &str) -> Option<Attribute<'a>>;
162 fn has_attribute(&self, name: &str) -> bool;
163}
164
165impl<'a, R: AsRow<'a> + Into<HasAttribute<'a>>> HasAttributes<'a> for R {
166 fn attributes(&self) -> RowIterator<'a, Attribute<'a>> {
167 self.equal_range(0, Into::<HasAttribute>::into(*self).encode())
168 }
169
170 fn find_attribute(&self, name: &str) -> Option<Attribute<'a>> {
171 self.attributes()
172 .find(|attribute| attribute.ctor().parent().name() == name)
173 }
174
175 fn has_attribute(&self, name: &str) -> bool {
176 self.find_attribute(name).is_some()
177 }
178}