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
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}