Recursively create a tree in Rust

This code is meant to take a rectangular area, and randomly divide it up into smaller rectangles in a binary tree.

I'm somewhat new to Rust.

I'm concerned mostly about the create_subrooms function. I've tried lots of other permutations, but I can't find any more elegant way of writing this, and it still looks pretty ugly in my opinion.

Some specific questions I have:

• Would it be poor form to have the function take ownership of root, modify it and return it? This would mean I could create the tree in a single line instead of creating the Room, creating it's children and then explicitly assigning it to the left/right of it's parent
• Would I be better off having the function accept four size parameters, instead of creating the root Room beforehand and passing a reference? Or would that be too verbose?

This struct represents a node in the tree:

struct Room {
x: u32,
y: u32,
end_x: u32,
end_y: u32,
left: Option<Rc<Room>>>,
right: Option<Rc<Room>>,
}


And this function takes a previously created root Room, and recursively generates its children:

fn create_subrooms(&mut self, root: &mut Room, depth: u32) {
if depth < self.max_rec_depth && self.is_valid_size(root) {
let mut left: Room;
let mut right: Room;

// Horizontal and Vertical are the direction along which, the
// rectangle is split, and the new boundaries are randomly chosen
// perpendicular to that
match rand::random::<Direction>() {
Vertical => {
let cut = self.rng.gen_range(root.x, root.end_x);

// Not including the 'new' method for brevity,
// but it's form is (x, y, end_x, end_y)
// children are None by default
left = Room::new(root.x, root.y, cut, root.end_y);
right = Room::new(cut, root.y, root.end_x, root.end_y);
}
Horizontal => {
let cut = self.rng.gen_range(root.y, root.end_y);

left = Room::new(root.x, root.y, root.end_x, cut);
right = Room::new(root.x, cut, root.end_x, root.end_y);
}
};

self.create_subrooms(&mut left, depth + 1);
root.left = Some(Rc::new(left));

self.create_subrooms(&mut right, depth + 1);
root.right = Some(Rc::new(right));
}
}


The self parameters are from a Builder struct which is used to customise how the area is divided.

The create_rooms function is initially called like this:

fn divide_room(&mut self) {
let mut root = SubDungeon::new(0, 0, self.width, self.height);
self.create_subdungeons(&mut root, 0);
Rc::new(root)
}

• Is the tree important, or just the leaf nodes? If you're generating "rooms", I would expect just the leaf nodes. If it's "subrooms", what's the difference? – Austin Hastings Apr 19 at 23:43
• Can you add some code to the question that shows how create_rooms is called? That's helpful for understanding it. – Roland Illig Apr 20 at 4:39
• @AustinHastings the tree is important, as I need to do some task later where the tree is stepped through and a calculation is performed using the Rooms at each level of the tree. – JMac Apr 20 at 8:17