-
-
Notifications
You must be signed in to change notification settings - Fork 377
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
fix: use to_string
to serialize Color
#934
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #934 +/- ##
=====================================
Coverage 89.4% 89.4%
=====================================
Files 61 61
Lines 15430 15465 +35
=====================================
+ Hits 13799 13834 +35
Misses 1631 1631 ☔ View full report in Codecov by Sentry. |
I think you don't need this in Ratatui. This works for me to serialize and deserialize #[serde_as]
#[derive(Debug, Deserialize, Serialize)]
pub struct Config {
#[serde_as(as = "DisplayFromStr")]
pub background_color: ratatui::style::Color,
} If I export an instance of this struct to toml, I get something like this: [config]
background_color = "#111827" |
But it does make sense that a Ratatui color should be able to make a round trip. Plus |
For context, the code block I shared above does round trip, I'm able to read and write to toml and I am able to read |
One missing thing from my comment was probably "by default". Of course you could make it do that, but why not make it the default. |
Good point. One reason I can think of is that people may want to serialize into |
My guess is that this would never be a default serialization format, only a deserialization. I could be wrong though, the only way I can think of to be able to make serialization work would be to keep the colors a I think hex is a reasonable default serialization format rather than "Color(r,g,b)" (I'm assuming this is the current default?) |
Yes, with this change we're serializing as hex instead of e.g. without this change the test fails like so:
|
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.
How does this change existing serialized colors?
- Can you write tests for the existing serialization format?
If it makes the previous serialization format fail, then this is a breaking change, which we should:
a) work out whether we need to provide a serialization method that understands both formats (it's possible that we broke things when switching to using the from_str
method - I'm not sure how many apps use serialization, it's likely a small amount but growing)
b) document the breaking change as such in the breaking changes doc
- Can you please update the first comment in the PR to summarize the changes in behavior that users would notice (e.g. write a sucint message for the changelog).
(Something like Color::Indexed is now serialized as ..., Color::Rgb ...)
(also, thanks for submitting your first PR to Ratatui!) |
I like hex as a default, but I'm just not familiar enough with serde to know if supporting other formats would be possible after adding this default. For example, Base16 color schemes use
And I think it doesn't make sense to implement |
You are still able to provide serealizers/deserializers other than the default using the This would still be more difficult when wanting custom colour logic for something like |
This test does fail #[cfg(feature = "serde")]
#[test]
fn deserialize_with_previous_format() -> Result<(), serde_json::Error> {
assert_eq!(Color::White, serde_json::from_str::<Color>("\"White\"")?);
assert_eq!(
Color::Rgb(255, 0, 255),
serde_json::from_str::<Color>("{\"Rgb\":[255,0,255]}")?
);
assert_eq!(
Color::Indexed(10),
serde_json::from_str::<Color>("{\"Indexed\":10}")?
);
Ok(())
} Fixed thanks to https://bgrande.de/blog/custom-deserialization-of-multiple-type-field-from-json-in-rust/ |
I have made the deserializer accept the existing serialized format. Are we still considering this a breaking change, since we changed how things are serialized? |
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.
A couple of small things to add regarding comments, but otherwise good to go.
Nope - this might break people with tests for exact serialization to strings, but that's really everything. I don't consider that a breaking change worth worrying about. |
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.
Generally approving the code, still a couple of minor things to get it over the line.
Would it be fine if the value being deserialized is not a string or one of the old formats (for example passing an empty array), it would create this error |
Thanks for fixing up the requested changes (and apologies in the delay in response). Merging this. |
Since deserialize now uses `FromStr` to deserialize color, serializing `Color` RGB values, as well as index values, would produce an output that would no longer be able to be deserialized without causing an error. Color::Rgb will now be serialized as the hex representation of their value. For example, with serde_json, `Color::Rgb(255, 0, 255)` would be serialized as `"#FF00FF"` rather than `{"Rgb": [255, 0, 255]}`. Color::Indexed will now be serialized as just the string of the index. For example, with serde_json, `Color::Indexed(10)` would be serialized as `"10"` rather than `{"Indexed": 10}`. Other color variants remain the same.
Since deserialize now uses `FromStr` to deserialize color, serializing `Color` RGB values, as well as index values, would produce an output that would no longer be able to be deserialized without causing an error. Color::Rgb will now be serialized as the hex representation of their value. For example, with serde_json, `Color::Rgb(255, 0, 255)` would be serialized as `"#FF00FF"` rather than `{"Rgb": [255, 0, 255]}`. Color::Indexed will now be serialized as just the string of the index. For example, with serde_json, `Color::Indexed(10)` would be serialized as `"10"` rather than `{"Indexed": 10}`. Other color variants remain the same.
Since deserialize now uses `FromStr` to deserialize color, serializing `Color` RGB values, as well as index values, would produce an output that would no longer be able to be deserialized without causing an error. Color::Rgb will now be serialized as the hex representation of their value. For example, with serde_json, `Color::Rgb(255, 0, 255)` would be serialized as `"#FF00FF"` rather than `{"Rgb": [255, 0, 255]}`. Color::Indexed will now be serialized as just the string of the index. For example, with serde_json, `Color::Indexed(10)` would be serialized as `"10"` rather than `{"Indexed": 10}`. Other color variants remain the same.
Since deserialize now uses
FromStr
to deserialize color, serializingColor
RGB values, as well as index values, would produce an output that would no longer be able to be deserialized without causing an error.Color::Rgb will now be serialized as the hex representation of their value.
For example, with serde_json,
Color::Rgb(255, 0, 255)
would be serialized as"#FF00FF"
rather than{"Rgb": [255, 0, 255]}
.Color::Indexed will now be serialized as just the string of the index.
For example, with serde_json,
Color::Indexed(10)
would be serialized as"10"
rather than{"Indexed": 10}
.Other color variants remain the same.