The two functions extracted here are mostly copied verbatim, but we use dataclasses to marshal the values back.