Factor out _read_or_write()