Layered configuration parameters

Does anyone know of any crate that allows layered in-memory configurations? The basic gist of it is that I have three (maybe four, in the future) levels of objects in a hierarchy. In the lowest levels I want to be able to read some variables, but if they aren't set, I want to travel up the hierarchy until it finds the variable.

Think of it as there being a top root object, called "GlobalRuntime" or something. This keeps a list of "Interface" objects, which keeps a list of "ClientConnection" objects.

When a "ClientConnection" is initialized it needs to set a bunch of internal variables -- for instance a "MaxRecvBufLen". If this is set specifically for this instance of the client connection, then use that value. If it isn't, then check if it is set in the "Interface" object this client connection lives under. If it isn't set there, then check for it in the "GlobalRuntime".

This is easy to model in code using Option<> in structs. However, I find myself adding more variables than initially planned, and there's a pretty substantial amount of repetitive changes (i.e. copy/paste errors) and boilerplate, and I'm also not looking forward to all the repetitive changes if I end up adding the extra object layer.

I'm looking for something along the line of (extremely simplified):

let confparams = ConfParams::new(Some(&parent));

confparams.set_u64("some_param", 42);

// Will find the param in confparams

// Will search for the parameter in parent
let max_recv_buf_len = confparams.get_u64("max_recv_buf_len").unwrap();

Preferably with the ability to use an enum rather than strings for the keys.

Does such a thing already exist? I haven't found anything, but I'm unsure what the terminology would be.

How about config?