One enum, two types with different Default

Scalable Vector Graphics (SVG) has some attributes which determine how coordinates are interpreted; they can have value "userSpaceOnUse" or "objectBoundingBox".

I have this enum:

enum CoordUnits {
    UserSpaceOnUse,
    ObjectBoundingBox
}

However, some SVG elements use one of those values as the default (if the attribute is not specified), and some other elements use the other value as default.

Currently I have some newtypes with crappy names, each with their respective default:

struct GradientUnits(CoordUnits);

impl Default for GradientUnits {
    fn default() -> Self {
        GradientUnits(CoordUnits::ObjectBoundingBox)
    }
}

struct PatternContentUnits(CoordUnits);

impl Default for PatternContentUnits {
    fn default() -> Self {
        PatternContentUnits(CoordUnits::UserSpaceOnUse)
    }
}

And so on for each particular SVG element. Note that there are only two possible values; it's just that each SVG element has a different default.

I like the newtypes because they each have a name that corresponds the element/attribute they will be used for.

I don't like having to impl Default for each of them. However, having two global types like HasDefaultA and HasDefaultB sounds ugly.

Is there a better way to do this? I could define a macro to construct the newtypes and their impl Default, but I'm not sure if it's the best way to go around this.

1 Like

How are you modeling the SVG elements themselves? Since they’re the ones that know the type of coordinate units they use by default, that logic seems to belong there and not in the enum?

1 Like

Yeah, I agree - the SVG elements are the ones that should determine the default value.

I have a macro now that creates a newtype around CoordUnits and provides a Default impl with a user-specified value. It's working pretty well, and it doesn't look ugly at all. Thanks!