These are chat archives for rust-lang/rust

27th
Nov 2018
Ali Shirvani
@alishir
Nov 27 2018 06:36 UTC
Hi there, do you know how can I create &str from bytes:Bytes? I got following error: expected &str, found struct bytes::Bytes
Tim Robinson
@1tgr
Nov 27 2018 06:47 UTC
str::from_utf8(&bytes)
Ali Shirvani
@alishir
Nov 27 2018 06:49 UTC
@1tgr thanks a lot
octave99
@octave99
Nov 27 2018 08:42 UTC
Is there a way to implement Add operation for Types implementing a Trait (MyMath) in this case.
impl<T> Add<T> for T
where
  T: MyMath,
{
  type Output = u8;

  fn add(self, other: T) -> u8 {
    return 1;
  }
}
Above code shows an error: type parameter T must be used as the type parameter for some local type (e.g. MyStruct<T>)
Tim Robinson
@1tgr
Nov 27 2018 08:45 UTC
Yep, you can’t implement other crates’ traits (eg Add) on other crates’ types (eg any T)
octave99
@octave99
Nov 27 2018 08:47 UTC
Ok. So what in your opinion could be the best way to deal with it
Implement it for every type, one by one?
Denis Lisov
@tanriol
Nov 27 2018 08:48 UTC
Why do you actually want that?
octave99
@octave99
Nov 27 2018 08:51 UTC
Trying to make my code look more readable and nice which converts two structs to &[u8] and then concatenates them into one &[u8] as output
Was trying if it can be done as
```
let out: &[u8]
let out: &[u8] = struct1 + struct2;
where struct1 and struct2 could be two different definitions implementing MyMath trait with trait requirement to have "to_raw" function which transforms struct into &[u8]
Denis Lisov
@tanriol
Nov 27 2018 08:56 UTC
Note that a &[u8] is a reference to a byte slice, and you cannot easily concatenate them without allocating...
octave99
@octave99
Nov 27 2018 08:57 UTC
Right. Concatenate into new byte slice
Denis Lisov
@tanriol
Nov 27 2018 09:01 UTC
...what I'd do is impl<T1: ToRaw, T2: ToRaw> ToRaw for (T1, T2) { ... } and use it like (header, payload).to_raw()
And I'd really suggest writing them into a writer instead, at least as an option.
octave99
@octave99
Nov 27 2018 09:09 UTC
Thanks. In my case, there could be 10 structs seeking addition
So, may be I will need to think of something else
Or the worst, impl add for each type
octave99
@octave99
Nov 27 2018 09:22 UTC
use std::ops::Add;

struct Town{
    population: i32,
    area: i32,
}

struct City{
    population: i32,
    town_count: i32,
}

trait Conversion{
    fn to_raw(&self) -> i32;
}

impl Conversion for Town{
    fn to_raw(&self) -> i32{
        self.population
    }
}

impl Conversion for City{
    fn to_raw(&self) -> i32{
        self.town_count
    }
}

fn add_item<T: Conversion>(r: &mut Vec<i32>, i: T) {
    r.push(i.to_raw());
}

fn main(){
    let mut result: Vec<i32> = Vec::new();
    let town = Town{population: 11, area: 2};
    let city = City{population: 14, town_count: 22};
    add_item(&mut result, town);
    add_item(&mut result, city);
    print!("{:?}", result);
}
This one appears to be closest to my solution, would appreciate inputs to further improve:
Denis Lisov
@tanriol
Nov 27 2018 09:24 UTC
What are you trying to do? Not a new serialization library, I hope?
octave99
@octave99
Nov 27 2018 09:25 UTC
Not at all. Trying to craft packets and wish to get bytes from structs Ethernet + TCP + HTTP and then send over the wire
Tim Robinson
@1tgr
Nov 27 2018 09:26 UTC
What's a realistic example?
octave99
@octave99
Nov 27 2018 09:27 UTC
Just wanted to be nice with the API if Add can be implemented, but I think have to settle with add_layer sort of function
Tim Robinson
@1tgr
Nov 27 2018 09:28 UTC
You have some structs, and you want them all to be able to extend a Vec<u8>?
octave99
@octave99
Nov 27 2018 09:29 UTC
That's correct
Tim Robinson
@1tgr
Nov 27 2018 09:29 UTC
Off the top of my head, I would have the structs expose iter(&self) -> impl Iterator<Item=u8>
Then you could result.extend(town.iter()) and result.extend(city.iter())
I'm guessing the structs don't hold the physical bytes, or else they could implement as_ref(&self) -> &[u8]
octave99
@octave99
Nov 27 2018 09:32 UTC
Sure. Let me try those. Thanks for inputs.
Tim Robinson
@1tgr
Nov 27 2018 09:34 UTC

Not a new serialization library, I hope?

I wonder if you could adapt serde to serialise to network wire formats

octave99
@octave99
Nov 27 2018 09:34 UTC
Sure. But I am trying to keep it simple and flexible without external libraries
Tim Robinson
@1tgr
Nov 27 2018 09:44 UTC
Sure, you just got me thinking
I wrote a Serde serializer and deserializer for FIX messages without much trouble
octave99
@octave99
Nov 27 2018 09:48 UTC
Sure. Let me add that to try list as well. Will benchmark and go with the best. Thanks.
Rotem Yaari
@vmalloc
Nov 27 2018 11:13 UTC
Hi, what is the idiomatic way to split a string by whitespaces, but allow no more than N resulting strings? Something like Python's s.split(None, 2)?
octave99
@octave99
Nov 27 2018 11:26 UTC
@vmalloc How about this: s.split(" ").take(2).collect::<Vec<&str>>()
Or rather this version since you mentioned whitepaces, s.split_whitespace().take(2).collect::<Vec<&str>>()
Rotem Yaari
@vmalloc
Nov 27 2018 11:43 UTC
@polygdev but that version won't let me keep the remainder, no?
like "hello world bla bla" would lose the "bla bla" string...
octave99
@octave99
Nov 27 2018 11:51 UTC
let s = "hello world bla bla";
    let words = s.split_whitespace().collect::<Vec<&str>>();
    print!("{:?}\n", words[..2].to_vec());
    print!("{:?}", words[2..].to_vec());
This should do the job
Rotem Yaari
@vmalloc
Nov 27 2018 12:07 UTC
@polygdev that's not entirely what I need. I need a string like first second third part (note multiple whitespaces in between) to return first, second and third part...
any spaces between third and part should be preserved unchanged
That's what Python's split does, for example...
Ali Shirvani
@alishir
Nov 27 2018 12:34 UTC
In actix-http source code there is Response::Ok() associated function, but I couldn't find the function definition in the source codes, is there any magic rule for Ok() associated function?
octave99
@octave99
Nov 27 2018 12:41 UTC
@vmalloc Something like this: "hello world bla bla".splitn(3, ' ').collect::<Vec<&str>>()
Rotem Yaari
@vmalloc
Nov 27 2018 12:49 UTC
@polygdev nope - the following doesn't work as expected (an empty string is returned):
fn main() {
    println!(
        "{:?}",
        "hello   world bla bla"
            .splitn(3, ' ')
            .collect::<Vec<&str>>()
    );
}
because of the multiple spaces between hello and world
In Python, it would return "hello", "world", "bla bla"
octave99
@octave99
Nov 27 2018 12:52 UTC
@vmalloc You will need to do a little extra here, read this one: https://stackoverflow.com/questions/49143986/how-to-combine-splitn-and-split-whitespace-in-rust
Ali Shirvani
@alishir
Nov 27 2018 12:54 UTC
@polygdev thanks a lot, I totally forgotten to search the docs :-(
octave99
@octave99
Nov 27 2018 12:57 UTC
@alishir By the way, you may even join actix community at gitter
Its pretty active and helpful community for your actix queries
Ali Shirvani
@alishir
Nov 27 2018 12:58 UTC
@polygdev I already joined actix community, but i think there is some magic rules for Ok()
red75prime
@red75prime
Nov 27 2018 13:04 UTC
@vmalloc The required feature didn't make it to stdlib yet ( rust-lang/rust#43090 ). It can be done with a bit of pointer arithmetic, though https://play.rust-lang.org/?version=stable&mode=debug&edition=2015&gist=ecbdabb24be9df582d08a6b2ce68b922
Rotem Yaari
@vmalloc
Nov 27 2018 13:12 UTC
@red75prime @polygdev I see. Thanks!
toxicafunk
@toxicafunk
Nov 27 2018 13:32 UTC
what would be the easiest way to ask my rust program how long its been running?
I have a tokio runtime
a hyper server plus a kafka consumer
i just want to add a prometheus gauge with time running value
octave99
@octave99
Nov 27 2018 13:36 UTC
Instant::now() and then elapsed doesn't work for your case?
toxicafunk
@toxicafunk
Nov 27 2018 13:36 UTC
i tried something like
let started = Instant::now();

    match (req.method(), req.uri().path()) {
        (&Method::GET, "/metrics") => {
            let elapsed = &started.elapsed().as_secs();
            info!("Elapsed time: {}", elapsed);
            PROCESS_STARTED_GAUGE.set(*elapsed as f64);
            let metric_families = prometheus::gather();
but elapsed is always 0
elapsed should not be given reference
toxicafunk
@toxicafunk
Nov 27 2018 13:38 UTC
yah, I put the reference because I got 0
so it doesn matter whether its a ref or not, its still 0 :(
octave99
@octave99
Nov 27 2018 13:39 UTC
Yes. It should not. But result is not 0
toxicafunk
@toxicafunk
Nov 27 2018 13:39 UTC
i saw that on the example
but iḿ doing this inside a hyoper router
so something gets lost along the way
pub fn router(req: Request<Body>) -> BoxFut {
    let mut response = Response::new(Body::empty());
    let encoder = TextEncoder::new();
    let started = Instant::now();

    match (req.method(), req.uri().path()) {
        (&Method::GET, "/metrics") => {
            let elapsed = started.elapsed().as_secs();
            info!("Elapsed time: {}", elapsed);
            PROCESS_STARTED_GAUGE.set(elapsed as f64);
            let metric_families = prometheus::gather();
            let mut buffer = vec![];
            encoder.encode(&metric_families, &mut buffer).unwrap();
            *response.body_mut() = Body::from(buffer);
        }
        _ => {
            *response.status_mut() = StatusCode::NOT_FOUND;
        }
    };

    Box::new(future::ok(response))
}
red75prime
@red75prime
Nov 27 2018 13:40 UTC
started is recreated on every router() call
toxicafunk
@toxicafunk
Nov 27 2018 13:41 UTC
oh $*%!
octave99
@octave99
Nov 27 2018 13:41 UTC
yeah, that's the case
toxicafunk
@toxicafunk
Nov 27 2018 13:41 UTC
i thought it was outside the request
Richard Berry
@rjsberry
Nov 27 2018 13:44 UTC
Is anyone familiar with rust-embedded/cross?
toxicafunk
@toxicafunk
Nov 27 2018 13:44 UTC
thx @polygdev and @red75prime !
don't know how i missed that :(
red75prime
@red75prime
Nov 27 2018 13:45 UTC
lazy_static will be instrumental in making started global.
toxicafunk
@toxicafunk
Nov 27 2018 13:46 UTC
yah
lazy_static! {
    static ref PROCESS_STARTED_GAUGE: Gauge = register_gauge!(opts!(
        "server_running_time",
        "Seconds elapsed since server started"
        //labels!{"handler" => "all",}
    )).unwrap();

    static ref STARTED: Instant = Instant::now();
}
this works as expected :)
hi! I want to encode a string with a key, and then decode it with same.. can anybody suggest a good lib, and algohoritm?
octave99
@octave99
Nov 27 2018 13:56 UTC
@trsh xor the string with a key
@polygdev whaaaat?
octave99
@octave99
Nov 27 2018 13:59 UTC
use xor encoding
@polygdev what makes you advice this joice?
Tim Robinson
@1tgr
Nov 27 2018 14:02 UTC
XOR encoding
octave99
@octave99
Nov 27 2018 14:03 UTC
@trsh Don't like xor or what?
The Gitter client turns that word into an emoji
@polygdev I think I have to lose my xor virginity
I cant find any create for this method
There is only command tool
Chikirev Sirguy
@cheblin
Nov 27 2018 14:07 UTC

needed from outer function return function that accept as argument a function..

fn outer<G, R>() -> R
                  where
                      G: Fn(usize, usize, i32),
                      R: Fn(usize, usize, G)
{
    fn inner<T: G>(d0: usize, d1: usize, getter: T)
    {};

    inner
}

correct me please.

octave99
@octave99
Nov 27 2018 14:09 UTC
@trsh You don't need a crate as its not that hard to implement:
let input = "testing";
    let key = 123;
    let crypted:Vec<u8> = input.as_bytes().iter().map(|c| c ^ key).collect();
    let decrypted:Vec<u8> = crypted.iter().map(|c| c ^ key).collect();
    print!("{:?}", String::from_utf8(decrypted));
Kelly Thomas Kline
@kellytk
Nov 27 2018 14:23 UTC
Until try_from is stablized what is the next best alternative for converting a usize to a u16?
Tim Robinson
@1tgr
Nov 27 2018 14:25 UTC
Without try_from, I've been doing it like this:
fn try_usize_into_u16(n: usize) -> Option<u16> {
    if n >= u16::min_value() && n <= u16::max_value() {
        Some(n as u16)
    } else {
        None
    }
}
Kelly Thomas Kline
@kellytk
Nov 27 2018 14:26 UTC
That's elegant thank you
@polygdev can I use string for safer key?
Hmm, not
octave99
@octave99
Nov 27 2018 14:28 UTC
@trsh You can, but then you will have to write some more code to transform key str to bytes and then xor with those bytes and at the end of bytes, reposition from 0
Kelly Thomas Kline
@kellytk
Nov 27 2018 14:31 UTC
@1tgr It syntax checks for you? u16::min_value() and u16::max_value() generate a mismatched types error that it expected usize but found u16
I better use some lib
But cant google one
This lib is allready in my cargo > https://docs.rs/rust-crypto/0.2.36/crypto/, but can't figure out if there some two way crypting
Tim Robinson
@1tgr
Nov 27 2018 14:39 UTC
@kellytk ah yep, it needs u16::min_value() as usize
I copied and pasted from an example with f64 and i64
red75prime
@red75prime
Nov 27 2018 14:40 UTC
@trsh I would recommend rust-openssl or other C library wrapper. Cryptography has much more to it than Rust safety guaranties can provide.
Kelly Thomas Kline
@kellytk
Nov 27 2018 14:43 UTC
That was it
Conner Bryan
@cab
Nov 27 2018 14:57 UTC

is it possible / what's the idiomatic way to have a struct that borrows from itself? like

struct Data {
  field_one: HashMap<String, Value>,
  field_two: Vec<&Value>
}

where field_two borrows Values from field_one?

@red75prime thanks fot suggestion
Ichoran
@Ichoran
Nov 27 2018 19:38 UTC
@trsh - xor is like the least secure way imaginable to encrypt things with a key. If you just want a little mixing, it's fine; otherwise, use a proper encryption algorithm.