1 | use super::*; |
2 | |
3 | #[derive (Copy, Clone, Debug, Hash, PartialEq, Eq, Ord, PartialOrd)] |
4 | pub struct Row { |
5 | file: &'static File, |
6 | index: usize, |
7 | } |
8 | |
9 | impl Row { |
10 | pub(crate) fn new(file: &'static File, index: usize) -> Self { |
11 | Self { file, index } |
12 | } |
13 | } |
14 | |
15 | pub trait AsRow: Copy { |
16 | const TABLE: usize; |
17 | fn to_row(&self) -> Row; |
18 | fn from_row(row: Row) -> Self; |
19 | |
20 | fn file(&self) -> &'static File { |
21 | self.to_row().file |
22 | } |
23 | |
24 | fn reader(&self) -> &'static Reader { |
25 | // Safety: At this point the File is already pointing to a valid Reader. |
26 | unsafe { &*self.file().reader } |
27 | } |
28 | |
29 | fn index(&self) -> usize { |
30 | self.to_row().index |
31 | } |
32 | |
33 | fn usize(&self, column: usize) -> usize { |
34 | self.file().usize(self.index(), Self::TABLE, column) |
35 | } |
36 | |
37 | fn str(&self, column: usize) -> &'static str { |
38 | self.file().str(self.index(), Self::TABLE, column) |
39 | } |
40 | |
41 | fn row(&self, column: usize) -> Row { |
42 | Row::new(self.file(), self.usize(column) - 1) |
43 | } |
44 | |
45 | fn decode<T: Decode>(&self, column: usize) -> T { |
46 | T::decode(self.file(), self.usize(column)) |
47 | } |
48 | |
49 | fn blob(&self, column: usize) -> Blob { |
50 | self.file().blob(self.index(), Self::TABLE, column) |
51 | } |
52 | |
53 | fn list<R: AsRow>(&self, column: usize) -> RowIterator<R> { |
54 | self.file().list(self.index(), Self::TABLE, column) |
55 | } |
56 | } |
57 | |
58 | pub struct RowIterator<R: AsRow> { |
59 | file: &'static File, |
60 | rows: std::ops::Range<usize>, |
61 | phantom: std::marker::PhantomData<R>, |
62 | } |
63 | |
64 | impl<R: AsRow> RowIterator<R> { |
65 | pub(crate) fn new(file: &'static File, rows: std::ops::Range<usize>) -> Self { |
66 | Self { |
67 | file, |
68 | rows, |
69 | phantom: std::marker::PhantomData, |
70 | } |
71 | } |
72 | } |
73 | |
74 | impl<R: AsRow> Iterator for RowIterator<R> { |
75 | type Item = R; |
76 | |
77 | fn next(&mut self) -> Option<Self::Item> { |
78 | self.rows |
79 | .next() |
80 | .map(|row: usize| R::from_row(Row::new(self.file, index:row))) |
81 | } |
82 | } |
83 | |
84 | pub trait HasAttributes { |
85 | fn attributes(&self) -> RowIterator<Attribute>; |
86 | fn find_attribute(&self, name: &str) -> Option<Attribute>; |
87 | fn has_attribute(&self, name: &str) -> bool; |
88 | fn guid_attribute(&self) -> Option<GUID>; |
89 | fn arches(&self) -> i32; |
90 | } |
91 | |
92 | impl<R: AsRow + Into<HasAttribute>> HasAttributes for R { |
93 | fn attributes(&self) -> RowIterator<Attribute> { |
94 | self.file() |
95 | .equal_range(0, Into::<HasAttribute>::into(*self).encode()) |
96 | } |
97 | |
98 | fn find_attribute(&self, name: &str) -> Option<Attribute> { |
99 | self.attributes().find(|attribute| attribute.name() == name) |
100 | } |
101 | |
102 | fn has_attribute(&self, name: &str) -> bool { |
103 | self.find_attribute(name).is_some() |
104 | } |
105 | |
106 | fn guid_attribute(&self) -> Option<GUID> { |
107 | self.find_attribute("GuidAttribute" ).map(|attribute| { |
108 | fn unwrap_u32(value: &Value) -> u32 { |
109 | match value { |
110 | Value::U32(value) => *value, |
111 | _ => panic!(), |
112 | } |
113 | } |
114 | fn unwrap_u16(value: &Value) -> u16 { |
115 | match value { |
116 | Value::U16(value) => *value, |
117 | rest => panic!(" {rest:?}" ), |
118 | } |
119 | } |
120 | fn unwrap_u8(value: &Value) -> u8 { |
121 | match value { |
122 | Value::U8(value) => *value, |
123 | rest => panic!(" {rest:?}" ), |
124 | } |
125 | } |
126 | |
127 | let args = attribute.args(); |
128 | |
129 | GUID( |
130 | unwrap_u32(&args[0].1), |
131 | unwrap_u16(&args[1].1), |
132 | unwrap_u16(&args[2].1), |
133 | unwrap_u8(&args[3].1), |
134 | unwrap_u8(&args[4].1), |
135 | unwrap_u8(&args[5].1), |
136 | unwrap_u8(&args[6].1), |
137 | unwrap_u8(&args[7].1), |
138 | unwrap_u8(&args[8].1), |
139 | unwrap_u8(&args[9].1), |
140 | unwrap_u8(&args[10].1), |
141 | ) |
142 | }) |
143 | } |
144 | |
145 | fn arches(&self) -> i32 { |
146 | let mut arches = 0; |
147 | |
148 | if let Some(attribute) = self.find_attribute("SupportedArchitectureAttribute" ) { |
149 | if let Some((_, Value::I32(value))) = attribute.args().first() { |
150 | arches = *value; |
151 | } |
152 | } |
153 | |
154 | arches |
155 | } |
156 | } |
157 | |