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