1use std::marker::PhantomData;
12
13#[cfg(any(feature = "llvm18-0", feature = "llvm19-0", feature = "llvm20-0"))]
14use crate::error::TableGenError;
15#[cfg(any(feature = "llvm16-0", feature = "llvm17-0"))]
16use crate::error::{SourceLocation, TableGenError, WithLocation};
17use crate::{
18    Error, SourceInfo, TableGenParser,
19    raw::{
20        TableGenRecordKeeperIteratorRef, TableGenRecordKeeperRef, TableGenRecordVectorRef,
21        tableGenRecordKeeperFree, tableGenRecordKeeperGetAllDerivedDefinitions,
22        tableGenRecordKeeperGetClass, tableGenRecordKeeperGetDef,
23        tableGenRecordKeeperGetFirstClass, tableGenRecordKeeperGetFirstDef,
24        tableGenRecordKeeperGetNextClass, tableGenRecordKeeperGetNextDef,
25        tableGenRecordKeeperItemGetName, tableGenRecordKeeperItemGetRecord,
26        tableGenRecordKeeperIteratorClone, tableGenRecordKeeperIteratorFree,
27        tableGenRecordVectorFree, tableGenRecordVectorGet,
28    },
29    record::Record,
30    string_ref::StringRef,
31};
32
33#[derive(Debug, PartialEq, Eq)]
35pub struct RecordKeeper<'s> {
36    raw: TableGenRecordKeeperRef,
37    pub(crate) parser: TableGenParser<'s>,
38}
39
40impl<'s> RecordKeeper<'s> {
41    pub(crate) unsafe fn from_raw(
42        raw: TableGenRecordKeeperRef,
43        parser: TableGenParser<'s>,
44    ) -> RecordKeeper<'s> {
45        RecordKeeper { raw, parser }
46    }
47
48    pub fn classes(&self) -> NamedRecordIter<'_, IsClass> {
52        unsafe { NamedRecordIter::from_raw(tableGenRecordKeeperGetFirstClass(self.raw)) }
53    }
54
55    pub fn defs(&self) -> NamedRecordIter<'_, IsDef> {
59        unsafe { NamedRecordIter::from_raw(tableGenRecordKeeperGetFirstDef(self.raw)) }
60    }
61
62    pub fn class(&self, name: &str) -> Result<Record<'_>, Error> {
64        unsafe {
65            let class = tableGenRecordKeeperGetClass(self.raw, StringRef::from(name).to_raw());
66            if class.is_null() {
67                Err(TableGenError::MissingClass(name.into()).into())
68            } else {
69                Ok(Record::from_raw(class))
70            }
71        }
72    }
73
74    pub fn def(&self, name: &str) -> Result<Record<'_>, Error> {
76        unsafe {
77            let def = tableGenRecordKeeperGetDef(self.raw, StringRef::from(name).to_raw());
78            if def.is_null() {
79                Err(TableGenError::MissingDef(name.into()).into())
80            } else {
81                Ok(Record::from_raw(def))
82            }
83        }
84    }
85
86    pub fn all_derived_definitions(&self, name: &str) -> RecordIter<'_> {
89        unsafe {
90            RecordIter::from_raw_vector(tableGenRecordKeeperGetAllDerivedDefinitions(
91                self.raw,
92                StringRef::from(name).to_raw(),
93            ))
94        }
95    }
96
97    pub fn source_info(&self) -> SourceInfo<'_> {
98        SourceInfo(&self.parser)
99    }
100}
101
102impl Drop for RecordKeeper<'_> {
103    fn drop(&mut self) {
104        unsafe {
105            tableGenRecordKeeperFree(self.raw);
106        }
107    }
108}
109
110#[doc(hidden)]
111pub struct IsClass;
112#[doc(hidden)]
113pub struct IsDef;
114
115trait NextRecord {
116    unsafe fn next(raw: &mut TableGenRecordKeeperIteratorRef);
117}
118
119impl NextRecord for IsClass {
120    unsafe fn next(raw: &mut TableGenRecordKeeperIteratorRef) {
121        unsafe {
122            tableGenRecordKeeperGetNextClass(raw);
123        }
124    }
125}
126
127impl NextRecord for IsDef {
128    unsafe fn next(raw: &mut TableGenRecordKeeperIteratorRef) {
129        unsafe {
130            tableGenRecordKeeperGetNextDef(raw);
131        }
132    }
133}
134
135#[derive(Debug)]
136pub struct NamedRecordIter<'a, T> {
137    raw: TableGenRecordKeeperIteratorRef,
138    _kind: PhantomData<&'a T>,
139}
140
141impl<T> NamedRecordIter<'_, T> {
142    unsafe fn from_raw(raw: TableGenRecordKeeperIteratorRef) -> Self {
143        NamedRecordIter {
144            raw,
145            _kind: PhantomData,
146        }
147    }
148}
149
150impl<'a, T: NextRecord> Iterator for NamedRecordIter<'a, T> {
151    type Item = (Result<&'a str, std::str::Utf8Error>, Record<'a>);
152
153    fn next(&mut self) -> Option<Self::Item> {
154        let current = if self.raw.is_null() {
155            return None;
156        } else {
157            unsafe {
158                Some((
159                    StringRef::from_raw(tableGenRecordKeeperItemGetName(self.raw)).try_into(),
160                    Record::from_raw(tableGenRecordKeeperItemGetRecord(self.raw)),
161                ))
162            }
163        };
164        unsafe { T::next(&mut self.raw) };
165        current
166    }
167}
168
169impl<T> Clone for NamedRecordIter<'_, T> {
170    fn clone(&self) -> Self {
171        unsafe { Self::from_raw(tableGenRecordKeeperIteratorClone(self.raw)) }
172    }
173}
174
175impl<T> Drop for NamedRecordIter<'_, T> {
176    fn drop(&mut self) {
177        unsafe { tableGenRecordKeeperIteratorFree(self.raw) }
178    }
179}
180
181pub struct RecordIter<'a> {
182    raw: TableGenRecordVectorRef,
183    index: usize,
184    _reference: PhantomData<&'a ()>,
185}
186
187impl<'a> RecordIter<'a> {
188    unsafe fn from_raw_vector(ptr: TableGenRecordVectorRef) -> RecordIter<'a> {
189        RecordIter {
190            raw: ptr,
191            index: 0,
192            _reference: PhantomData,
193        }
194    }
195}
196
197impl<'a> Iterator for RecordIter<'a> {
198    type Item = Record<'a>;
199
200    fn next(&mut self) -> Option<Record<'a>> {
201        let next = unsafe { tableGenRecordVectorGet(self.raw, self.index) };
202        self.index += 1;
203        if next.is_null() {
204            None
205        } else {
206            unsafe { Some(Record::from_raw(next)) }
207        }
208    }
209}
210
211impl Drop for RecordIter<'_> {
212    fn drop(&mut self) {
213        unsafe { tableGenRecordVectorFree(self.raw) }
214    }
215}
216
217#[cfg(test)]
218mod test {
219    use crate::TableGenParser;
220
221    #[test]
222    fn classes_and_defs() {
223        let rk = TableGenParser::new()
224            .add_source(
225                r#"
226                class A;
227                class B;
228                class C;
229                def D1: A;
230                def D2: B;
231                def D3: C;
232                "#,
233            )
234            .unwrap()
235            .parse()
236            .expect("valid tablegen");
237        rk.classes()
238            .for_each(|i| assert!(i.1.name().unwrap() == i.0.unwrap()));
239        rk.defs()
240            .for_each(|i| assert!(i.1.name().unwrap() == i.0.unwrap()));
241        assert!(rk.classes().map(|i| i.0.unwrap()).eq(["A", "B", "C"]));
242        assert!(rk.defs().map(|i| i.0.unwrap()).eq(["D1", "D2", "D3"]));
243    }
244
245    #[test]
246    fn derived_defs() {
247        let rk = TableGenParser::new()
248            .add_source(
249                r#"
250                class A;
251                class B;
252                class C;
253
254                def D1: A;
255                def D2: A, B;
256                def D3: B, C;
257                "#,
258            )
259            .unwrap()
260            .parse()
261            .expect("valid tablegen");
262        let a = rk.all_derived_definitions("A");
263        assert!(a.map(|i| i.name().unwrap().to_string()).eq(["D1", "D2"]));
264        let b = rk.all_derived_definitions("B");
265        assert!(b.map(|i| i.name().unwrap().to_string()).eq(["D2", "D3"]));
266    }
267
268    #[test]
269    fn single() {
270        let rk = TableGenParser::new()
271            .add_source(
272                r#"
273                class A;
274                def D1;
275                "#,
276            )
277            .unwrap()
278            .parse()
279            .expect("valid tablegen");
280        assert_eq!(rk.class("A").expect("class exists").name().unwrap(), "A");
281        assert_eq!(rk.def("D1").expect("def exists").name().unwrap(), "D1");
282    }
283}