Implement to_string() on ByteStr and ByteString - #159300
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
but why? |
For #134915 but I wasn't going to link it until I got CI to pass |
|
hmm. see also #134915 (comment) |
c9b6c8c to
91ae0c4
Compare
also for note this is a totally reasonable thing to do, sorry to bother, I only asked because the PR kind of made me do a double-take ("but ByteStr isn't even stable...?") |
91ae0c4 to
06765dd
Compare
to_string() on ByteStr and ByteStringto_string() on ByteStr and ByteString
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
r? @clarfonthey rustbot has assigned @clarfonthey. Use Why was this reviewer chosen?The reviewer was selected based on:
|
|
If this looks good I'll squash it before merging |
| /// Try to get a `String` representation of the `&ByteString`, if it is | ||
| /// valid UTF-8. | ||
| /// | ||
| /// This method is named `to_string()` because we want `ByteString` to | ||
| /// implement `Display`, but the `ToString` trait has a blanket | ||
| /// implementation for types that implement `Display`, and the trait version | ||
| /// will use the Unicode replacement character rather than returning a | ||
| /// `Result` and allowing for the possibility of the content not being UTF-8. | ||
| #[unstable(feature = "bstr", issue = "134915")] | ||
| #[rustc_allow_incoherent_impl] | ||
| pub fn to_string(&self) -> Result<String, FromUtf8Error> { | ||
| String::from_utf8(self.0.clone()) | ||
| } |
There was a problem hiding this comment.
Based upon the precedent set by other APIs like CString and OsString, this should be into_string. That is a bit annoying, however, since it appears that OsString and PathBuf just return the old string on error, whereas CString has its own custom IntoStringError type. I don't like just copying that from std::ffi into std::bstr, but that seems like the best option.
There was a problem hiding this comment.
The idea was that this would ensure that people don't use the ToString blanket implementation for types implementing Display - calling this into_string() would leave the to_string() method being the problematic display version
We could switch this to be into_string() and then add a version of to_string() that emits deprecation warnings, but my understanding of the discussion on #134915 was that it was preferrable to just have to_string() do the conversion, but returning a result rather than being lossy
There was a problem hiding this comment.
Note: I think it's fair to have both in this case, although at least with this method there is one key problem: the Vec is allocated before it's validated, and so, you end up throwing away the allocation if it's invalid UTF-8. I would expect this to at least run str::from_utf8 first and then do String::from_utf8_unchecked on the result if it passes.
There was a problem hiding this comment.
So I started working on switching to that, but that would change the error type from alloc::string::FromUtf8Error (which has a copy of the bytes) to core::str::Utf8Error (which doesn't)
The allocation of the vec isn't thrown away if it is invalid UTF-8, it is just returned in the FromUtf8Error rather than in a String. I'm fine with switching, but wanted to make sure that the change in error type was an intentional part of the suggestion
| impl ByteStr { | ||
| /// Try to get a `String` representation of the `&ByteStr`, if it is valid | ||
| /// UTF-8. | ||
| /// | ||
| /// This method is named `to_string()` because we want `ByteStr` to | ||
| /// implement `Display`, but the `ToString` trait has a blanket | ||
| /// implementation for types that implement `Display`, and the trait version | ||
| /// will use the Unicode replacement character rather than returning a | ||
| /// `Result` and allowing for the possibility of the content not being UTF-8. | ||
| #[unstable(feature = "bstr", issue = "134915")] | ||
| #[rustc_allow_incoherent_impl] | ||
| pub fn to_string(&self) -> Result<String, FromUtf8Error> { | ||
| String::from_utf8(self.0.to_vec()) | ||
| } | ||
| } |
There was a problem hiding this comment.
So, just seeing this code makes me a little sceptical about this due to the presence of the extra allocation also being a bit of a weird footgun.
Sure, to_string is automatically added by Display, but I would imagine most people would want this to be a shorthand for str::from_utf8, for which simply a to_str method would be fine. The main benefit of that is that if you want to pass &str to a method when you have the correct lifetime for the &ByteStr, it will Just Work tm, whereas if you do &s.to_string() it won't because you have a reference to a temporary. There may be APIs using AsRef<str> that get around this, but then you're just allocating a new string for no reason.
So, I think perhaps we could allow this, if we also have a to_str method that just calls str::from_utf8. But I'm still feeling a bit weird about it. Either way, no matter what we do, it should have a separate feature flag so it can be dealt with separately.
|
(Also apologies for taking so long to get to this; I'm going to try to get to my |
This comment has been minimized.
This comment has been minimized.
4115019 to
8a12241
Compare
| @@ -65,3 +66,16 @@ fn test_display() { | |||
| assert_eq!(&format!("{b2:-^6.3}!"), "-�(�--!"); | |||
| assert_eq!(&format!("{b2:->6.3}!"), "---�(�!"); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test_to_string() { | |||
There was a problem hiding this comment.
Since we generally just do all string tests in alloctests, and this is redundant anyway, I'd remove it.
|
So, looking at this, final notes:
Otherwise, I'm fine merging this. Specifically, r=me with those changes. Thank you for working on this! |
|
@rustbot author |
|
Reminder, once the PR becomes ready for a review, use |
View all comments