These are chat archives for rust-lang/rust

4th
Feb 2019
David Vo
@auscompgeek
Feb 04 00:34
If you just need libc, use the libc crate
Ryan
@rnleach
Feb 04 02:37
@auscompgeek I want everything EXCEPT libc.
David Vo
@auscompgeek
Feb 04 03:58
you are saying very contradictory things
Ryan
@rnleach
Feb 04 04:01
When I run bindgen, it creates bindings for the C-library I want, plus a bunch of stuff in libc that I don't want in my bindings, I want to use it from libc.
Denis Lisov
@tanriol
Feb 04 07:21
There are whitelist and blacklist options in bindgen. Whitelist is usually a better idea.
knewt
@knewt
Feb 04 19:37
Is there a simple way to take something supplying a Read and send it to two separate things implementing Write?
Ichoran
@Ichoran
Feb 04 19:49
Just read_to_end and then write that with each of the two things, if you can store it all in memory. Maybe there's something that will chunk it for you, but I'm not aware of anything.
toidiu
@toidiu
Feb 04 20:27
@knewt the Read.read(&mut self) requires a mutable reference so only one Reader at a time. I havnt tried this but maybe you could use a crossbeam_channel to emmit the value and write it. Although you will probably incur some performance penalty since I image the channel woud have to do a clone.
or mwybe write a custom Write impl that writes to multiple things.. but then I guess you question was if there was a trivial way to do this already
knewt
@knewt
Feb 04 20:33
@toidiu yeah, was hoping someone had already written something. I’ll have a zipfile Read, which I’ll be pulling a specified number of bytes from, and I need to send those bytes to both a Sha512 digest, and an LZ4 compressor, with the latter passing on into a Vec. and i’d really rather not have to read the whole block of data into an intermediate buffer first
so something that can act as a Write, duplicate the data, and pass it on to both destination Write’s would be perfect
Ichoran
@Ichoran
Feb 04 20:40
Can you pull out the logic so you have the Read and the two Writes available at once? It's then a trivial matter of calling read once and write twice.
You could write a dispatcher as you mention (without duplicating the data since the data for write is just borrowed, not mutably borrowed), but you could also just do it by hand if you don't need to do it in many different places.
knewt
@knewt
Feb 04 20:45
hmm. i guess I can just take the source from std::io::copy and make my own version that takes two Write's
Ichoran
@Ichoran
Feb 04 20:47
The main thing you need to decide is what happens if you can't write everything to both channels.
If "partial success" is cool, then you can't even represent it as Write because you have just a single Result.
knewt
@knewt
Feb 04 20:48
nah, failure on either leg would be a failure. I need both the hash and the compressed Vec output, only one is no good
Tim Robinson
@1tgr
Feb 04 20:50
You could make a Write that writes to two other Writes
A Tee
knewt
@knewt
Feb 04 20:55
the complexity I guess comes from how to deal with one Write accepting a different number of bytes than the other upon a write() call
might just be easier to go the route of a custom version of io::copy, since that’s calling into write_all
hmm, there actually is a Tee already it seems, but it’s unstable, " the semantics of a partial read/write of where errors happen is currently unclear and may change"
Ichoran
@Ichoran
Feb 04 21:03
Exactly :P
But if you know what the semantics ought to be you can use some elaboration of
use std::io::Write;

struct Vee<A: Write, B: Write> {
    a: A,
    b: B
}

impl<A: Write, B: Write> Write for Vee<A, B> {
    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
        let n_a = self.a.write(buf)?;
        let n_b = self.b.write(buf)?;
        if n_a < buf.len()      { Err(std::io::Error::new(std::io::ErrorKind::WriteZero, "Write incomplete")) }
        else if n_b < buf.len() { Err(std::io::Error::new(std::io::ErrorKind::WriteZero, "Write incomplete")) }
        else                    { Ok(buf.len()) }
    }
    fn flush(&mut self) -> std::io::Result<()> {
        self.a.flush()?;
        self.b.flush()
    }
}
This one assumes that you always can write everything, which isn't safe for general use, but in your case it's probably okay.
knewt
@knewt
Feb 04 21:05
the existing Tee works a bit differently, and is a Read, that takes a Write, and upon a read() also does a write_all()
Ichoran
@Ichoran
Feb 04 21:05
Yeah, I should fix this one and call it Vee
knewt
@knewt
Feb 04 21:06
:)
Ichoran
@Ichoran
Feb 04 21:06
There we go.
Tim Robinson
@1tgr
Feb 04 21:06
Those two lines can be write_all instead?
For anything based around files I think write is fine
Ichoran
@Ichoran
Feb 04 21:08
Yeah, it's entirely possible that write_all is what you want, and you don't need to match anything.
Then it's just
    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
        self.a.write_all(buf)?;
        self.b.write_all(buf)?;
        Ok(buf.len())
    }
knewt
@knewt
Feb 04 21:09
I think the custom io::copy variant will actually be the simpler option here tbh :)
Ichoran
@Ichoran
Feb 04 21:09
Maybe. With write_all this is getting pretty simple (and we're running out of corner cases to care about).
knewt
@knewt
Feb 04 21:10
yeah
even with just a single Write I couldn’t directly use io::copy, since I only want to pull N number of bytes out
Ichoran
@Ichoran
Feb 04 21:10
I think @1tgr is correct that the write_all logic is fine in your case.
knewt
@knewt
Feb 04 21:16
yeah. i’ll have a play later this week when I actually have some spare time. thanks for the help
cacruden
@cacruden
Feb 04 22:33
I was running through the rust-by-examples and ran the one that is on there https://doc.rust-lang.org/rust-by-example/scope/borrow/freeze.html locally… it said it would not compel and I had to comment out a line to get it to compile. I run 1.32 locally and it ran fine - it did not freeze the borrowed reference. When I run it through the website playground it has compile issues. Does it no longer freeze or is this potentially a new defect?
Denis Lisov
@tanriol
Feb 04 22:37
This example is outdated. With so-called non-lexical lifetimes the borrow does not count unless it can actually be used later... here the compiler sees that the reference will not be used later, so it compiles fine.
cacruden
@cacruden
Feb 04 22:38
Thanks
Denis Lisov
@tanriol
Feb 04 22:39
If you add a println!("{}", _large_integer); before the "goes out of scope" comment, it will actually show you this conflict.