not quite abstracted like I want, but it's a start