Initial implementation

See ba560b4a552e8500ea85c85a5c8c3844ac1368c0