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
Use core::fmt::Write
instead of custom StrWrite
?
#492
Comments
Yes, it's because Write would require an additional utf-8 check when converting the buffer to a string (or an unsafe section that assumes we only write strings into it), while StrWrite allows us to maintain the invariant that the buffer is valid utf-8 entirely using safe code. If you look at the history you'll see some iteration on this. |
|
Hmm, I'm pretty sure use std::fmt;
fn write<W: fmt::Write>(writer: &mut W, text: &str) {
writer.write_str(text).unwrap();
}
fn main() {
let mut string = String::new();
write(&mut string, "hello string!");
println!("{}", string);
} |
Ah, I was confusing fmt::Write and io::Write. We also want to be able to write to files (or, more generally, anything which impl's io::Write), which can be done with |
Ah, okay :) Maybe I can add a blanket impl for |
Opened rust-lang/rust#77733. |
It seems like a good idea to reuse a core trait. If we can't have a blanket implementation of This would be a compatibility break technically, but I think it should require minimal changes to upgrade. |
Yes, thinking about this now, switching to fmt::Write and adapting our own WriteWrapper seems quite workable. The blanket in Rust looks like it's not going to happen as it can break coherence. I agree that client changes would be quite minimal, so I'd be ok with the (technical) compatibility breakage. |
Cool. @camelid: if you want to do the honors, I'd be happy to merge a PR making this change. |
Sure! |
Hmm, this code: impl<W> fmt::Write for WriteWrapper<W>
where
W: fmt::Write,
{
#[inline]
fn write_str(&mut self, s: &str) -> fmt::Result {
self.0.write_str(s)
}
#[inline]
fn write_fmt(&mut self, args: Arguments) -> fmt::Result {
self.0.write_fmt(args)
}
}
impl<W> fmt::Write for WriteWrapper<W>
where
W: io::Write,
{
#[inline]
fn write_str(&mut self, s: &str) -> fmt::Result {
match self.0.write_all(s.as_bytes()) {
Ok(()) => Ok(()),
Err(err) => Err(fmt::Error),
}
}
#[inline]
fn write_fmt(&mut self, args: Arguments) -> fmt::Result {
match self.0.write_fmt(args) {
Ok(()) => Ok(()),
Err(err) => Err(fmt::Error),
}
}
} Causes this error:
How do I get around this? EDIT: Removed duplicate trait bound in code (issue is still there though). |
We should only need impl<W> fmt::Write for WriteWrapper<W>
where
W: io::Write,
{ .. } because one wouldn't need |
Hmm, but what about this? use std::fmt::Write;
// ...
pub fn write_html<'a, I, W>(writer: W, iter: I) -> fmt::Result
where
I: Iterator<Item = Event<'a>>,
W: Write,
{
HtmlWriter::new(iter, WriteWrapper(writer)).run()
}
Should I accept the suggestion? |
Actually I think I figured it out: I just changed the requirement to |
I would be interested in this as well. It would be really nice to be able to reuse the struct EscapedHtml(CowStr);
impl Display for EscapedHtml {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
escape_html(f, &self.0)
}
} Which would then permit: // ...
Code(text) => write!(w, "<code>{}</code>", EscapedHtml(&text))
// ... Note that this pattern might also be useful for the stock |
Is there a particular reason that pulldown-cmark defines its own type,
StrWrite
, rather than using the built-in Rust traitcore::fmt::Write
? Previouslycore::fmt::Write
's documentation saidBut in a recent PR, I changed it to remove that section since no one knew of a reason why it said that. Perhaps it would be good to move pulldown over to that built-in trait?
The text was updated successfully, but these errors were encountered: