Better generation of newtype-uuid types?
sunshowers opened this issue · 0 comments
At Oxide we're moving towards adding type safety to our UUID usage via the newtype-uuid crate. The handling of typed UUIDs in progenitor results in some friction, and @davepacheco mentioned a possibility that progenitor/typify gets smarter about handling these types.
(The rest of this issue is going to be based on this test, which produces the outputs shown here.)
newtype-uuid
implements JsonSchema
, and the type TypedUuid<MyKind>
turns into TypedUuidForMyKind
. This gets reflected in the JSON schema as a new type with the UUID format.
When turned back into Rust code with typify, this becomes a newtype wrapper, with conversions to and from Uuid
. This is not a horrendously bad outcome, but it has a couple of issues:
- This type is its own thing and doesn't hook into the typed UUID infrastructure at all -- we'd manually have to write
From
impls each way. - The code automatically generates conversions from
TypedUuidForMyKind
toUuid
and back -- that's something we're trying to be more explicit about in newtype-uuid with theGenericUuid
trait.
The outcome with a replace
directive is ideal. But as we add more typed UUID kinds, we'll have to remember to add corresponding replace
directives for them to all of their corresponding clients. That's a bit unfortunate, and I'm wondering if we can do better.
Questions
One challenge is that while we know where TypedUuid
lives, we don't know where MyKind
lives in general. (In omicron it'll always live in omicron-uuid-kinds
.) So I'm wondering whether some notion of replace
patterns based on regexes might help. For example:
replace_patterns = {
^TypedUuidFor([A-Za-z][A-Za-z0-9]*)$ = ::newtype_uuid::TypedUuid<::omicron_uuid_kinds::\\1>,
}
Is this, or something like it, worth implementing?
Could newtype-uuid
help out here somehow by providing hints?