-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Designspace v5 fields #340
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Glad to see you're enjoying your time off! Gave this a quick once-over for you :)
src/designspace.rs
Outdated
/// Describes a single axis subset for a variable font. | ||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] | ||
#[serde(untagged)] | ||
pub enum AxisSubset { | ||
/// Describes a range of an axis. | ||
Range { | ||
/// The name of the axis under consideration. | ||
name: String, | ||
/// Optionally, the lower end of the range, in user coordinates | ||
#[serde(rename = "@userminimum", default, skip_serializing_if = "Option::is_none")] | ||
user_minimum: Option<f64>, | ||
/// Optionally, the upper end of the range, in user coordinates | ||
#[serde(rename = "@usermaximum", default, skip_serializing_if = "Option::is_none")] | ||
user_maximum: Option<f64>, | ||
/// Optionally, the new default value of subset axis, in user coordinates. | ||
#[serde(rename = "@userdefault", default, skip_serializing_if = "Option::is_none")] | ||
user_default: Option<f64>, | ||
}, | ||
/// Describes a single point of an axis. | ||
Discrete { | ||
/// The name of the axis under consideration. | ||
name: String, | ||
/// The single point of the axis. | ||
#[serde(rename = "@uservalue")] | ||
user_value: f64, | ||
}, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be more useful/helpful to use inner structs for the range/discrete values here. By keeping the values in the enum itself, you have to hold an AxisSubset
and can only access inner fields with matching, whereas if there's an inner struct you can pull (a reference to) that out the first time you match and hold that for future use.
So, unless you specifically expect users to only need to match on this enum and inspect its values once, I'd recommend creating AxisSubsetRange
and AxisSubsetDiscrete
structs (or similar)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By this you mean going for an enum AxisSubset { Range(AxisSubsetRange), Discrete(AxisSubsetDiscrete) }
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, sorry if that wasn't clear!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both with the current and your suggested approach, I run into DeError(Custom("data did not match any variant of untagged enum AxisSubset"))
when trying to load MutatorSans2.designspace 🤔 Not sure what's going on there...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do the name
fields need a #[serde(rename = "@name")]
annotation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh DUH, thanks. Now I get a different error. Progress.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I move the structs out, I am back at the "data did not match any variant" error and when I leave them as they are, the discrete variant is deserialized as a ranged one. The joys of untagged data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Put the discrete variant first in the enum declaration, as it's harder to match (requiring name
and user_value
). If serde isn't rejecting unknown fields, then discrete can match range.
As for why decomposing the enum isn't working, it probably something to do with how (IIRC) the XML deserialisation cares about the struct name(?) Worth finding a workaround to before we merge this though imo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moving the variant up top also didn't work... Maybe I'll need to write a custom function for this.
Todo: