Skip to content

Commit

Permalink
rbx_reflection: Superclass Iterator (#448)
Browse files Browse the repository at this point in the history
  • Loading branch information
krakow10 authored Sep 30, 2024
1 parent 0f2edcf commit a9252ac
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 0 deletions.
1 change: 1 addition & 0 deletions rbx_reflection/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# rbx_reflection Changelog

## Unreleased Changes
* Added `ReflectionDatabase::superclasses_iter`

## 4.7.0 (2024-08-22)
* Update to rbx_types 1.10
Expand Down
27 changes: 27 additions & 0 deletions rbx_reflection/src/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,24 @@ pub struct ReflectionDatabase<'a> {
pub enums: HashMap<Cow<'a, str>, EnumDescriptor<'a>>,
}

pub struct SuperClassIter<'a> {
database: &'a ReflectionDatabase<'a>,
descriptor: Option<&'a ClassDescriptor<'a>>,
}
impl<'a> SuperClassIter<'a> {
fn next_descriptor(&self) -> Option<&'a ClassDescriptor<'a>> {
let superclass = self.descriptor?.superclass.as_ref()?;
self.database.classes.get(superclass)
}
}
impl<'a> Iterator for SuperClassIter<'a> {
type Item = &'a ClassDescriptor<'a>;
fn next(&mut self) -> Option<Self::Item> {
let next_descriptor = self.next_descriptor();
std::mem::replace(&mut self.descriptor, next_descriptor)
}
}

impl<'a> ReflectionDatabase<'a> {
/// Creates an empty `ReflectionDatabase` with a version number of 0.0.0.0.
pub fn new() -> Self {
Expand Down Expand Up @@ -59,6 +77,15 @@ impl<'a> ReflectionDatabase<'a> {
Some(list)
}

/// Returns an iterator of superclasses for the provided ClassDescriptor. This
/// iterator will start with the provided class and end with `Instance`.
pub fn superclasses_iter(&'a self, descriptor: &'a ClassDescriptor<'a>) -> SuperClassIter {
SuperClassIter {
database: self,
descriptor: Some(descriptor),
}
}

/// Finds the default value of a property given its name and a class that
/// contains or inherits the property. Returns `Some(&Variant)` if a default
/// value exists, None otherwise.
Expand Down
23 changes: 23 additions & 0 deletions rbx_reflection_database/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,33 @@ pub fn get() -> &'static ReflectionDatabase<'static> {

#[cfg(test)]
mod test {
use rbx_reflection::ClassDescriptor;

use super::*;

#[test]
fn smoke_test() {
let _database = get();
}

#[test]
fn superclasses_iter_test() {
let database = get();
let part_class_descriptor = database.classes.get("Part");
let mut iter = database.superclasses_iter(part_class_descriptor.unwrap());
fn class_descriptor_eq(lhs: Option<&ClassDescriptor>, rhs: Option<&ClassDescriptor>) {
let eq = match (lhs, rhs) {
(Some(lhs), Some(rhs)) => lhs.name == rhs.name,
(None, None) => true,
_ => false,
};
assert!(eq, "{:?} != {:?}", lhs, rhs);
}
class_descriptor_eq(iter.next(), part_class_descriptor);
class_descriptor_eq(iter.next(), database.classes.get("FormFactorPart"));
class_descriptor_eq(iter.next(), database.classes.get("BasePart"));
class_descriptor_eq(iter.next(), database.classes.get("PVInstance"));
class_descriptor_eq(iter.next(), database.classes.get("Instance"));
class_descriptor_eq(iter.next(), None);
}
}

0 comments on commit a9252ac

Please sign in to comment.