These are chat archives for rust-lang/rust

9th
Jan 2017
Chris Natoli
@NatoliChris
Jan 09 2017 06:10
Hey everyone,
I’m quite new to Rust, can anyone point me in the right direction for using parking_lot::RwLock, I have a RwLock<Item_Here>, not sure how to read the Item_Here so I can use it (e.g. Item_Here.someFunc())
Appreciate any help :)
Aleksey Kladov
@matklad
Jan 09 2017 06:12
Something like let i = rw_lock.read(); i.some_funct() should work I think...
But note that i will not be a plain ItemHere, it would be a special guard object (like smartpointer), which can deference to ItemHere.
Chris Natoli
@NatoliChris
Jan 09 2017 06:16
Thanks, I’ll give it a try
Matanel Levi
@matanelevi
Jan 09 2017 19:19
is it possible to move an array of u8 to an array of u16?
Alexander Ronald Altman
@pthariensflame
Jan 09 2017 19:31
It might be aligned improperly, but other than that your only real option is mem::transmute.
Matanel Levi
@matanelevi
Jan 09 2017 19:34
This message was deleted
Alexander Ronald Altman
@pthariensflame
Jan 09 2017 19:34
Here’s the best code I’ve found for doing it properly: https://github.com/llogiq/bytecount/blob/master/src/lib.rs#L156-L170
Matanel Levi
@matanelevi
Jan 09 2017 19:36
@pthariensflame :O, thanks..
Alexander Ronald Altman
@pthariensflame
Jan 09 2017 19:38
It’s a pity bytecount doesn’t expose that function. :)
Aleksey Kladov
@matklad
Jan 09 2017 19:38
@matanelevi do you have an array [u8; 10] or a slice &[u8]?
Matanel Levi
@matanelevi
Jan 09 2017 19:39
@matklad want to [u8; 512] -> [u16; 256]
@matklad but what did you want to do with &[u8]?
Aleksey Kladov
@matklad
Jan 09 2017 19:41
If you have a fixed sized array, I think you can write a macro/loop to transform elements one by one and hope that compiler optimizes this correctelly
Matanel Levi
@matanelevi
Jan 09 2017 19:41
@matklad yeah, but loop over the arrays isn't much efficient
in C, you would just array_of_u16 = array_of_u8;
Alexander Ronald Altman
@pthariensflame
Jan 09 2017 19:42
The equivalent of looping is to use the batching combinator from itertools.
The direct equivalent of that C code is calling mem::transmute, but then you risk unaligned accesses. All that machinery in bytecount is to take care of possible alignment issues.
Aleksey Kladov
@matklad
Jan 09 2017 19:45

in C, you would just array_of_u16 = array_of_u8;

Hm, in C arrays are not assignable...

At least, this fails:

#include "stdint.h"

void main(void) {
    uint8_t  a[2] = {0};
    uint16_t b[1] = {1};
    b = a;
}
Alexander Ronald Altman
@pthariensflame
Jan 09 2017 19:46
You have a partially initialized array in a there…
Aleksey Kladov
@matklad
Jan 09 2017 19:46
And I doubt that the standard would gurantee anything about reinterpreting pairs of u8 as u16, because, for example, byte order bay be fiffrenten.
Alexander Ronald Altman
@pthariensflame
Jan 09 2017 19:48
Assuming you’re working on a known target, you can cast pointers in C, and thus cast “arrays.”
But you run into the same alignment issues that I mentioned above.
Aleksey Kladov
@matklad
Jan 09 2017 19:49

You have a partially initialized array in a there…

Thanks! I've also got the main wrong :(

Alexander Ronald Altman
@pthariensflame
Jan 09 2017 19:50
Also, endianness is a possible issue that I forgot about, as @matklad hinted at.
The code in bytecount doesn't actually care about endianness because of its use case, so it’s fine that it just ignores it, but if you’re going to use the results u16s as numbers, you shouldn't do that.
Aleksey Kladov
@matklad
Jan 09 2017 19:53

yeah, but loop over the arrays isn't much efficient

It could be optimized in theory, and with macro you can completely avoid the loop.

Alexander Ronald Altman
@pthariensflame
Jan 09 2017 19:53
It would be possible to alter that code to account for endianness properly, but it seems like more trouble that it's worth.
Matanel Levi
@matanelevi
Jan 09 2017 20:01
@matklad How would you do it with macro?
Alexander Ronald Altman
@pthariensflame
Jan 09 2017 20:04
Here’s a completely safe solution with no bounds checks, although it results in a Vec<u8> instead.
extern crate itertools;
use itertools::Itertools;

array_of_u8.iter().batching(|mut it| {
    let low = iter.next().map(|v| v as u16);
    let high = iter.next().map(|v| (v as u16) << 8);
    low.and_then(|x| high.and_then(|y| x + y))
}).collect::<Vec<_>>()
s/it/iter/
Aleksey Kladov
@matklad
Jan 09 2017 20:07
There's batching specifically for slices in standard library (.chunks):
fn cast(xs: [u8; 512]) -> [u16; 256] {
    let mut ys = [0; 256];
    for (y, xx) in ys.iter_mut().zip(xs.chunks(2)) {
        let hi = xx[0] as u16;
        let lo = xx[1] as u16;
        *y = hi << 8 + lo;
    }
    ys
}
Matanel Levi
@matanelevi
Jan 09 2017 20:53
@matklad How do you meant to implement the macro?
btw, what is the simplest way to read a file to a vector?
Aleksey Kladov
@matklad
Jan 09 2017 20:54
pub fn cast_macro(xs: [u8; 512]) -> [u16; 256] {
    let mut r = [0; 256];
    macro_rules! n {
        ( $i:expr ) => {
            r[$i] = ((xs[2*$i] as u16) << 8) + xs[2*$i+1] as u16;
        }
    }
    macro_rules! fill {
        (              => $lo:expr; $hi:expr ) => { n!($lo) };

        ( | $q:pat $(| $p:pat)* => $lo:expr ; $hi:expr ) => {
            fill!( $(| $p)* => $lo ; ($lo + $hi) / 2 );
            fill!( $(| $p)* => ($lo + $hi) / 2 ; $hi)
        }
    }

    fill!(| _ | _ | _ | _ | _ | _ | _ | _ => 0; 256);
    r
}
something like this...
Matanel Levi
@matanelevi
Jan 09 2017 20:54
let mut file = fs::File::open(filename).unwrap();
    let file_size = file.metadata().unwrap().len();

    let mut data = vec![0; file_size as usize];
    file.read_to_end(&mut data).unwrap();

    data
This seems pretty long
Aleksey Kladov
@matklad
Jan 09 2017 20:55
You don't need to specify the vector size explicitelly, it will be extended automatically.
Matanel Levi
@matanelevi
Jan 09 2017 20:55
@matklad yeah, it's a bug
forgot to fix it
Aleksey Kladov
@matklad
Jan 09 2017 21:05
@matanelevi and none of the apropriate solutions optimizes to the memcpy :( https://godbolt.org/g/fRhl3f
Alexander Ronald Altman
@pthariensflame
Jan 09 2017 21:18
Try play.rust-lang.org instead of godbolt, although I don't know if you'll get a better result. :/
Matanel Levi
@matanelevi
Jan 09 2017 22:01
@matklad nah..
use byteorder::{BigEndian, ReadBytesExt};
use std::io::{Cursor, Read};
let file = fs::File::open(filename).expect("read_file: open");
    let mut cursor = Cursor::new(file);
    let mut data = Vec::new();
    while let Ok(v) = cursor.read_u16::<BigEndian>() {
        data.push(v);
    }
Why this code not compile?
I get error: no method named read_u16 found for type std::io::Cursor<std::fs::File> in the current scope
Aleksey Kladov
@matklad
Jan 09 2017 22:06
I think that Cursor is not needed there. Cursor is for wrapping [u8], and File is already Seek.
Matanel Levi
@matanelevi
Jan 09 2017 22:09
@matklad You're right! thanks :)