factor out internal fn