factor out this logic so it's reusable