These are chat archives for rust-lang/rust

7th
Dec 2018
David O'Connor
@David-OConnor
Dec 07 2018 03:08
Another Q where I struggle with macros: Is there a way using dec macros, to accept a value that could be either a &str or a number/boolean, and convert it to string if it's the latter? I tried creating a wrapper struct, and implementing From for it. The macro then creates a wrapper instance, and passes it to the actual func using into(). Unfortunately, the compiler then wishes for a type annotation, which defeats the purpose (concise syntax for an API). Is there a way around this? Example that looks like it does this, but requires the annotation:
impl From<(&str, bool)> for Helper {
    fn from(attr: (&str, bool)) -> Self {
        Self { key: attr.0.to_string(), val: attr.1.to_string() }
    }
}
// (Also a trivial one for (&str, &str), ones for numbers etc

#[macro_export]
macro_rules! attrs {
    { $($key:expr => $value:expr);* } => {
        {
            let mut vals = std::collections::HashMap::new();
            $(
                // Here we create the helper, with the intent of accepting any of several var types.
                let helper: Helper = ($key, val: $value).into();
                vals.insert(&helper.key, &helper.val);

            )*
            Attrs::new(vals)
        }
     };
}
Tim Robinson
@1tgr
Dec 07 2018 07:27

accept a value that could be either a &str or a number/boolean, and convert it to string if it's the latter?

Not sure what the problem is here, or why you couldn't call $(value).to_string() directly?

octave99
@octave99
Dec 07 2018 10:16
Could someone see, why the below code works the one way but not the other:
impl Stream for Sniffer {
  type Item = usize;
  type Error = io::Error;

  fn poll(&mut self) -> Poll<Option<usize>, io::Error> {
    // This works
    // loop {
    //   let ret = try_ready!(self.socket.poll_recv(&mut self.buf));
    //   print!("{:?}\n", ret);
    // }
    // I want to process the return from main, so trying below
    // But this stucks with strace - futex(0x7fed7d224a04, FUTEX_WAIT_PRIVATE, 1, NULL
    let ret = try_ready!(self.socket.poll_recv(&mut self.buf));
    Ok(Async::Ready(Some(ret)))
  }
}
octave99
@octave99
Dec 07 2018 10:32
Well its very strange behavior to me, unless it was meant to be like that. The above code did return the data when I waited for 10 secs. Instead of continuously sending the data, it returned 128 data chunks at once after 10 secs.
Here is how I am polling it from event loop
tokio::run(
    server
      .for_each(|s| {
        print!("Bytes: {:?}", s);
        Ok(())
      }).map_err(|e| println!("server error = {:?}", e)),
  );
Denis Lisov
@tanriol
Dec 07 2018 10:34
What is self.socket?
octave99
@octave99
Dec 07 2018 10:35
Its my implementation of RawSocket in non-blocking with mio

When I loop it in poll

// loop {
    //   let ret = try_ready!(self.socket.poll_recv(&mut self.buf));
    //   print!("{:?}\n", ret);
    // }

It prints the received bytes in real-time

Denis Lisov
@tanriol
Dec 07 2018 10:36
Looks like you don't set up readiness notification correctly.
octave99
@octave99
Dec 07 2018 10:36
But in the other way, it stucks for few seconds and then spills the received data chunks in one go
poll_recv method has this:
try_ready!(self.io.poll_read_ready(mio::Ready::readable()));
Denis Lisov
@tanriol
Dec 07 2018 10:50
How does poll_recv look?
octave99
@octave99
Dec 07 2018 10:51
pub fn poll_recv(&mut self, buf: &mut [u8]) -> Poll<usize, io::Error> {
    try_ready!(self.io.poll_read_ready(mio::Ready::readable()));

    // match self.io.get_ref().recv(buf) { //tokio-udp/src/socket.rs Line: 133
    match self.io.get_ref().read(buf) {
      Ok(n) => Ok(n.into()),
      Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
        self.io.clear_read_ready(mio::Ready::readable())?;
        Ok(Async::NotReady)
      }
      Err(e) => Err(e),
    }
  }
Its same as //tokio-udp/src/socket.rs
and then read is
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
    let rv = unsafe { libc::read(self.0, buf.as_mut_ptr() as *mut libc::c_void, buf.len()) };
    if rv < 0 {
      return Err(Error::last_os_error());
    }
    Ok(rv as usize)
  }
Denis Lisov
@tanriol
Dec 07 2018 10:55
And I suppose you have configured the socket as a nonblocking one, correct?
octave99
@octave99
Dec 07 2018 10:56
yes :)
let mut nonblocking = 1 as libc::c_ulong;
let res = unsafe { libc::ioctl(fd, libc::FIONBIO, &mut nonblocking) }
Denis Lisov
@tanriol
Dec 07 2018 10:59
Sorry, no more ideas :-( looks like it should work ok.
octave99
@octave99
Dec 07 2018 10:59
One strange thing is
tokio::run(
    server
      .for_each(|s| {
        print!("Bytes: {:?}", s);
        Ok(())
      }).map_err(|e| println!("server error = {:?}", e)),
  );
The batch size printing is always happening when the main received 128 chunks
Its fixed size is making me think about some issue somewhere
Denis Lisov
@tanriol
Dec 07 2018 11:02
Sounds weird, indeed. Is this a standard raw socket or something less known?
octave99
@octave99
Dec 07 2018 11:02
Also, I have not implemented AsyncRead and AsyncWrite, I read that PollEvented does it
let fd = unsafe { socket(AF_PACKET, SOCK_RAW, (ETH_P_ALL as u16).to_be() as i32) };
@tanriol Thanks for your time. Let me try to play around with some manual stream and tokio-udp echo example to see if can get some clue.
David O'Connor
@David-OConnor
Dec 07 2018 13:53
@1tgr Thanks again - nailed it! I'd discounted the possibility that Strings and &strs had a to_string() method!
David O'Connor
@David-OConnor
Dec 07 2018 15:07
Looks like even owned Strings have this method
Tim Robinson
@1tgr
Dec 07 2018 15:08
Any Display type gains to_string automatically https://doc.rust-lang.org/std/string/trait.ToString.html
Suzuki Tomohiro
@suztomo_twitter
Dec 07 2018 17:10
@lloydmeta and Centril, thank you for your frunk crate. I have a question posted to Stackoverflow: https://stackoverflow.com/questions/53673834/frunks-foldl-against-elements-that-share-same-trait-with-different-type-paramet
I appreciate if you can share a better way to use "foldl" method.
Tim Robinson
@1tgr
Dec 07 2018 17:38
I don't know the frunk crate but these are not the same value:
hlist![
    // All of the element are same and seem redundant. Can this argument be simplified?
    Layer::static_forward,
    Layer::static_forward,
    Layer::static_forward
],
They're instantiated under different generic types, and the generic types aren't mentioned in the source code because they're inferred by the compiler
You could probably write a macro to repeat Layer::static_forward n times... like an hlist equivalent to vec![Layer::static_forward; 3]
Suzuki Tomohiro
@suztomo_twitter
Dec 07 2018 17:42
@1tgr Thank you for the idea.
Mehmet ERİBOL
@mehmeteribol_gitlab
Dec 07 2018 18:43
hi
opss, sorry. not here :)
Suzuki Tomohiro
@suztomo_twitter
Dec 07 2018 22:21