0

I need to generate an array of random 20 bytes between a given range of arrays. Since arrays are comparable in Rust, this works:

let low = [0u8; 20];
let high = [2u8; 20];
assert_eq!(true, low < high);
assert_eq!(false, low > high);
assert_eq!(true, low == [0u8; 20]);

For these bounds:

let low: [u8; 20] = [98, 0, 1, 0, 2, 6, 99, 3, 0, 5, 23, 3, 5, 6, 11, 8, 0, 2, 0, 17];
let high: [u8; 20] = [99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];

These would be a valid result:

[98, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

These are not:

[98, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]

I want to do something like:

use rand::prelude::*;

fn main() {
    let low = [0u8; 20];
    let high = [2u8; 20];
    let value = rand::thread_rng().gen_range(low, high);
    println!("{:?}", value);
}

but I get following error:

error[E0277]: the trait bound `[u8; 20]: rand::distributions::uniform::SampleUniform` is not satisfied
 --> src\main.rs:6:36
  |
6 |     let value = rand::thread_rng().gen_range(low, high);
  |                                    ^^^^^^^^^ the trait `rand::distributions::uniform::SampleUniform` is not implemented for `[u8; 20]`

I tried implementing SampleUniform and UniformSampler without much success. Is there a simple way to implement this?

4
  • What do you mean with "between given range of arrays"? Do the arrays represent a number? For the rand crate, each array is just a sequence of bytes. There is no such concept as the range of values between two arrays Commented May 26, 2019 at 13:35
  • If you can use a Vec instead of an array, I would just do: let value: Vec<u8> = iter::repeat_with(|| rand::thread_rng().gen_range(low, high)).take(20).collect(); Commented May 26, 2019 at 13:49
  • @aochagavia - The bounds are just two 160 bit number (big endian). I want to get a random value between these bounds. For example [1u8;20] would be a valid result between [0u8;20] and [2u8;20]. Commented May 26, 2019 at 13:58
  • I think you need to implement the various rand traits. However, you won't be able to do that for [u8; 20] because that is not defined in your own crate and neither are the traits. Instead you'd have to create a newtype. e.g. struct U8x20([u8; 20]) and implement for that. Commented May 26, 2019 at 14:30

1 Answer 1

1

If you want to treat the byte arrays as big integers, use the num-bigint crate with the rand feature enabled:

use bigint::{ToBigInt, RandBigInt};

let low = -10000.to_bigint().unwrap();
let high = 10000.to_bigint().unwrap();
let b = rng.gen_bigint_range(&low, &high);

You could also use unsigned integers instead of signed. There are methods to convert to and from big endian byte arrays:

See also:

Sign up to request clarification or add additional context in comments.

5 Comments

I tried it but getting no method named ``gen_biguint_range`` found for type ``rand::rngs::thread::ThreadRng`` in the current scope
does it recommend using a certain trait after the message?
use bigint::{ToBigInt, RandBigInt};
Tried that.. it doesn't work. Also, doesn't recommend any traits. It keeps saying RandBigInt is not in the root. I am using rand 0.6.
You also need to enable the "rand" feature

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.