first implementation, with tests