I'm implementing a type of BSP tree in Rust, and I am wanting to write a function that tells which side of a parent node a node belongs to. This is what I have
enum Side {
L = 0,
R = 1,
}
enum RegionKind {
Split {
subregion: [Option<Rc<Region>>; 2],
},
Client{
window: i32,
},
}
struct Region {
kind: RegionKind,
container: Option<Rc<Region>>,
tags: u8,
}
impl Region {
fn from(&self) -> Option<Side> {
if let RegionKind::Split{subregion,..} = &self.container.as_ref()?.kind {
match &subregion[0] {
None => None,
Some(r) => if eq(Rc::<Region>::as_ptr(&r),self) {
Some(Side::L)
} else {
None
}.or_else(|| { match &subregion[1] {
None => None,
Some(r) => if eq(Rc::<Region>::as_ptr(&r),self) {
Some(Side::R)
} else {
None
}
}})
}
} else {
None
}
}
}
There are currently two things in place that are making this function quite the behemoth.
I need to repeat the check on on subregion[0] and subregion[1]. I would really like to be able to return the
Side
of the index (given that L = 0 and R = 1 like shown in the enum declaration) and be able to combine these into one, hence why I am asking to match over the elements of the array. Something like how you useSome(r) => ...
to unbox ther
out of theSome
I need to check if the
RegionKind
isSplit
. I can assert that any Region'scontainer
will always haveRegionKind::Split
as theirkind
, so I would like to be able to eliminate theif let else
entirely (I would prefer topanic!()
in that else block if I must have it as well, but the compiler gets upset about return types so I need to add theNone
at the end anyways, which just ends up getting marked as unreachable)
I figure there's probably some arcane Rust syntax that can make this much more concise and I just don't know it or don't know how to employ it here. This same function can be a single line macro in C.