These are chat archives for rust-lang/rust

10th
Dec 2017
Andrii Zymohliad
@azymohliad
Dec 10 2017 07:08 UTC
Hi all. I'm looking for a crate which provides functionality to encrypt single block using AES. I've checked ring, but didn't find related functionality, rust-crypto, but it seems to give only higher level API (encrypt full message in CBC/CTR/ECB mode with padding). And I just need single block encryption. I'm very new to cryptography and have very limited experience in rust, so I'm sorry if my question sounds stupid. Can anyone point me to the right direction?
Aleksey Kladov
@matklad
Dec 10 2017 08:30 UTC
@azymohliad hm, doesn't aessafe module from rust-crypto fit you? https://docs.rs/rust-crypto/0.2.36/crypto/aessafe/index.html I think this is the low-level thing, on which the high-level aes module is based.
Andrii Zymohliad
@azymohliad
Dec 10 2017 10:36 UTC
@matklad thank you! It seems to be exactly what I was looking for.
Aleksey Kladov
@matklad
Dec 10 2017 10:37 UTC
@azymohliad glad to here that! You might want to take a look at how aes module is implemented (there's src link in the docs): aessafe is only one backend, there's also a native(?) backend or something.
Michal 'vorner' Vaner
@vorner
Dec 10 2017 10:37 UTC
Hello. I have problems boxing a closure. It tells me the boxed thing doesn't implement Fn<()>. https://play.rust-lang.org/?gist=cb73444163f83e861d3d281294a6ff15&version=stable What am I doing wrong?
Fra ns
@snarf95_twitter
Dec 10 2017 10:39 UTC
run(*clo);
@vorner
Michal 'vorner' Vaner
@vorner
Dec 10 2017 10:45 UTC
Hmm. That works. But it doesn't solve my original problem, which was that I wanted to return it from some function as boxed trait object. https://play.rust-lang.org/?gist=687f0d2368a9a8bbc4aea46a8baeeb99&version=stable And before I'm told to pass &F there, I want to state that I intend to store it for later, so I need to move it into the parameter :-|.
Fra ns
@snarf95_twitter
Dec 10 2017 10:46 UTC
run(&*clo);
@vorner
Michal 'vorner' Vaner
@vorner
Dec 10 2017 11:09 UTC

That's still isn't what I need. OK, the full code/problem. I have a struct that stores a factory function it wants to call from time to time in the future. https://github.com/vorner/slog-retry/blob/master/src/lib.rs#L147. If I do it with the &*clo trick, I pass a reference inside, not the box. Therefore, the whole struct gets a non-'static lifetime. However, where I use it, I need it to be 'static.

I could mandate that a Box<Fn() -> _> is passed in. But then, if someone has a non-boxed Fn, the extra box seems wasteful. I was trying to write something like where for<'a> &'a F: Fn() -> _, but that doesn't seem to work.

Denis Lisov
@tanriol
Dec 10 2017 11:17 UTC
@vorner What are you trying to change in that code?
Michal 'vorner' Vaner
@vorner
Dec 10 2017 11:18 UTC
As I said, I can call Retry::new(move || { do_stuff_here() }). But I can't call it with Retry::new(Box::new(move || { do_stuff_here(); })), because it tells me Box<closure> doesn't implement Fn<()>.
It is kind of right, box doesn't implement it directly, it just can be dereferenced to something that does. But I don't know how to write such stuff (eg. give me something that either implements Fn directly or can be dereferenced to something that does).
Michal 'vorner' Vaner
@vorner
Dec 10 2017 11:26 UTC
I guess one thing would be to define my own trait and implement it for T: Fn() and for Box<T> where T: Fn() and maybe other smart pointers. But that also doesn't sound right.
Naja Melan
@najamelan
Dec 10 2017 11:32 UTC
@seanr707 if using components.last() in an if expression and using components.pop in the if block, it says "can't borrow components mutably because it is already borrowed immutably". That's why I ended up putting the first borrow in a separate scope so it would have come back. It turns out that putting it in the match expression as you did scopes it differently. It's quite surprising for me, but it works.
Sean
@seanr707
Dec 10 2017 14:25 UTC
@nikita-y I used to have the same problem. As @tanriol said, the function only reads so much data at a time, so if the JSON is too large, it is broken into chunks. You must create a mutable vector at a higher scope to push the bytes to. For example
// set up easy stuff
let mut vector: YourType = vec![];

// Transfer write function starts here
  vector.push(data.clone());
// End func

transfer.perform().unwrap();

serde::json::from_slice(vector) // or however it is called
@najamelan Ah, I know the error now, it isn't really the scope, but how you use the variables. It is an issue that will be fixed in Rust eventually. I don't recall the exact name, something like 'Lexical Scope Borrowing'; it is an issue with the compiler
if components.last() /* Immutable here */ {
   components.pop(); // Mutating here
} 

// Can be fixed using 'let' binding
let last = components.last();

if last {
  components.pop();
}
James McCoy
@jamessan
Dec 10 2017 15:45 UTC
NLL (non-lexical lifetimes)
Naja Melan
@najamelan
Dec 10 2017 19:43 UTC
ok thanks, it's good to hear that such inconveniences have a chance to disappear in the future
Kris
@VersBinarii
Dec 10 2017 23:43 UTC

Hello, i was trying to figure out a way to provide a way to implement a default implementation of a trait and also allow for the functionality to be overridden later on. I came up with the following:

trait MyTrait<T> {
    fn do_stuff(&self) -> T;
}

struct DefaultImpl;
impl MyTrait<String> for DefaultImpl {
    fn do_stuff(&self) -> String {
        println!("Doing Default stuff");
        String::new()
    }
}

struct MyStruct<T> {
    field: Box<MyTrait<T>>,
}

impl MyStruct<String>
{
    fn new() -> Self {
        MyStruct { field: Box::new(DefaultImpl{}) }
    }
    pub fn new_with_formatter<F: MyTrait<String> + 'static>(f: F) -> Self { 
        MyStruct {
            field: Box::new(f)
        }
    }
}

fn main(){

    struct UserImpl;
    impl MyTrait<String> for UserImpl {
        fn do_stuff(&self) -> String {
            println!("Doing User defined stuff");
            String::new()
        }
    }

    let a = MyStruct::new();
    a.field.do_stuff();

    let b = MyStruct::new_with_formatter(UserImpl{});
    b.field.do_stuff();
}

But this does not allow the the return type of the trait function to be changed from the "default implementation". Is there a way to do this? Or is this approach totally silly?