[core] Make PersonName hold both borrowed and owned strings#635
[core] Make PersonName hold both borrowed and owned strings#635Enet4 merged 1 commit intoEnet4:masterfrom AlexTMjugador:feat/owned-pn-components
PersonName hold both borrowed and owned strings#635Conversation
|
Hello @AlexTMjugador! That is an interesting idea, but I wonder whether we can introduce this without a semver breaking change. Extending the owned version of a person name into a dedicated type (
Let me know your thoughts on this. |
|
Hello! I believe we could introduce the variation you proposed if our primary goal here is to avoid any semver-breaking changes. However, the current approach in this PR has several characteristics that, in my view, may justify keeping it as is:
let mut name_builder = PersonName::builder();
name_builder.with_given("John"); // Borrowed from constant binary data
name_builder.with_family(String::from("Doe")); // Owned, may come from a buffer
let dicom_pn = name_builder.build().to_dicom_string(); // Doe^JohnUltimately, I'd understand if you decide this approach is not worth the technicality of being backwards incompatible, so please let me know how you'd like to proceed. For what it’s worth, in my experience as a library user, the |
|
Fair enough, this can added to the 0.9 milestone. |
At the moment, `PersonName` cannot be ergonomically used by application code as an structure to group and pass around owned person name components that are meant to conform to DICOM's PN value semantics. It is, for example, difficult to come up with code for deserializing a `PersonName` if strings cannot be borrowed from the data source, which is a common ocurrence when the source is e.g. a stream that reads data chunks to temporary buffers. To improve on that, let's make `PersonName` have `Cow<'a, str>` fields instead, and update `PersonNameBuilder` to accept them. `Cow`s are smart pointers that can hold both borrowed and owned data, so while `&'a str` can be wrapped in a `Cow<'a, str>` at virtually no cost, an owned `String` may also be wrapped with the same type but an indefinitely long lifetime, `Cow<'static, str>`. Therefore, code that borrows name components can still use `PersonName`s as before, and new code that relies on `PersonName`s owning their components can now easily work by just using a `'static` lifetime bound.
Enet4
left a comment
There was a problem hiding this comment.
Just clarifying that by me this is good and ready (thanks!), I am just holding it here until it's time to start merging all breaking changes for DICOM-rs 0.9.0.
|
Thanks for the reminder, @Enet4! I just wanted to quietly rebase this PR onto the latest master commits to keep it mergeable and not too distant from the mainline :) |
At the moment,
PersonNamecannot be ergonomically used by application code as an structure to group and pass around owned person name components that are meant to conform to DICOM's PN value semantics. It is, for example, difficult to come up with code for deserializing aPersonNameif strings cannot be borrowed from the data source, which is a common ocurrence when the source is e.g. a stream that reads data chunks to temporary buffers.To improve on that, let's make
PersonNamehaveCow<'a, str>fields instead, and updatePersonNameBuilderto accept them.Cows are smart pointers that can hold both borrowed and owned data, so while&'a strcan be wrapped in aCow<'a, str>at virtually no cost, an ownedStringmay also be wrapped with the same type but an indefinitely long lifetime,Cow<'static, str>. Therefore, code that borrows name components can still usePersonNames as before, and new code that relies onPersonNames owning their components can now easily work by just using a'staticlifetime bound.These changes are technically semver breaking due to the removal of the
Copytrait onPersonName, and minor changes in the semantics of thePersonNameBuilder::buildmethod.