code moved into its own file, untested