These are chat archives for rust-lang/rust

27th
Nov 2018
Ali Shirvani
@alishir
Nov 27 2018 06:36
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
str::from_utf8(&bytes)
Ali Shirvani
@alishir
Nov 27 2018 06:49
@1tgr thanks a lot
octave99
@octave99
Nov 27 2018 08:42
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
Yep, you can’t implement other crates’ traits (eg Add) on other crates’ types (eg any T)
octave99
@octave99
Nov 27 2018 08:47
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
Why do you actually want that?
octave99
@octave99
Nov 27 2018 08:51
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
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
Right. Concatenate into new byte slice
Denis Lisov
@tanriol
Nov 27 2018 09:01
...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
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
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
What are you trying to do? Not a new serialization library, I hope?
octave99
@octave99
Nov 27 2018 09:25
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
What's a realistic example?
octave99
@octave99
Nov 27 2018 09:27
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
You have some structs, and you want them all to be able to extend a Vec<u8>?
octave99
@octave99
Nov 27 2018 09:29
That's correct
Tim Robinson
@1tgr
Nov 27 2018 09:29
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
Sure. Let me try those. Thanks for inputs.
Tim Robinson
@1tgr
Nov 27 2018 09:34

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
Sure. But I am trying to keep it simple and flexible without external libraries
Tim Robinson
@1tgr
Nov 27 2018 09:44
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
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
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
@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
@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
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
@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
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
@vmalloc Something like this: "hello world bla bla".splitn(3, ' ').collect::<Vec<&str>>()
Rotem Yaari
@vmalloc
Nov 27 2018 12:49
@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
@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
@polygdev thanks a lot, I totally forgotten to search the docs :-(
octave99
@octave99
Nov 27 2018 12:57
@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
@polygdev I already joined actix community, but i think there is some magic rules for Ok()
red75prime
@red75prime
Nov 27 2018 13:04
@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
@red75prime @polygdev I see. Thanks!
toxicafunk
@toxicafunk
Nov 27 2018 13:32
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
Instant::now() and then elapsed doesn't work for your case?
toxicafunk
@toxicafunk
Nov 27 2018 13:36
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
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
Yes. It should not. But result is not 0
toxicafunk
@toxicafunk
Nov 27 2018 13:39
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
started is recreated on every router() call
toxicafunk
@toxicafunk
Nov 27 2018 13:41
oh $*%!
octave99
@octave99
Nov 27 2018 13:41
yeah, that's the case
toxicafunk
@toxicafunk
Nov 27 2018 13:41
i thought it was outside the request
Richard Berry
@rjsberry
Nov 27 2018 13:44
Is anyone familiar with rust-embedded/cross?
toxicafunk
@toxicafunk
Nov 27 2018 13:44
thx @polygdev and @red75prime !
don't know how i missed that :(
red75prime
@red75prime
Nov 27 2018 13:45
lazy_static will be instrumental in making started global.
toxicafunk
@toxicafunk
Nov 27 2018 13:46
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 :)
trsh
@trsh
Nov 27 2018 13:47
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
@trsh xor the string with a key
trsh
@trsh
Nov 27 2018 13:58
@polygdev whaaaat?
octave99
@octave99
Nov 27 2018 13:59
use xor encoding
trsh
@trsh
Nov 27 2018 14:01
@polygdev what makes you advice this joice?
Tim Robinson
@1tgr
Nov 27 2018 14:02
XOR encoding
octave99
@octave99
Nov 27 2018 14:03
@trsh Don't like xor or what?
The Gitter client turns that word into an emoji
trsh
@trsh
Nov 27 2018 14:03
@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

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
@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
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
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
That's elegant thank you
trsh
@trsh
Nov 27 2018 14:26
@polygdev can I use string for safer key?
Hmm, not
octave99
@octave99
Nov 27 2018 14:28
@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
@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
trsh
@trsh
Nov 27 2018 14:31
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
@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
@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
That was it
Conner Bryan
@cab
Nov 27 2018 14:57

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?

trsh
@trsh
Nov 27 2018 14:58
@red75prime thanks fot suggestion
Ichoran
@Ichoran
Nov 27 2018 19:38
@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.