somewhat inefficient, but working