Skip to content

Q: Idiomatic way to specify the length of an arbitrary vector #297

@rrybarczyk

Description

@rrybarczyk

Is there documentation on the idiomatic way to specify the length of an arbitrary vector?

My specific example is this:

I have a struct with fields containing various data types (like max 64-bytes, max 255-bytes, exactly 32-bytes, etc.) that I need to implement Arbitrary for. As an example, I will use one field in the Foo struct that represents a vector of 255 bytes.

struct Foo {
  bar: B0255
}

Where

struct B0255<'b>(Inner<'b>);

enum Inner<'a> {
   Ref(&'a [u8]),
   Owned(Vec<u8>),
}

To test this struct, I have created a new struct and implemented Arbitrary, which calls a function from_random which is implemented for Foo. from_random is needed because Arbitrary needs to be implemented in another crate.

struct RandomFoo(Foo);
impl Arbitrary from RandomFoo {
  fn arbitrary(g: &mut Gen) -> Self {
    RandomFoo(Foo::from_random(g))
  }
}

Currently, I am passing in the generator to the from_random function and generating the 255 byte vectors as:

impl Foo {
  fn from_random(g: &mut Gen) -> Self {
    let mut bar = Vec<u8>::arbitrary(g);
    bar.truncate(255);
    let bar: B0255 = bar.try_into().unwrap();
    Foo { bar }
  }
}

Here I am truncating the vector to avoid a panic caused by a vector that is too big. Was thinking that the best approach may be having the try_into return the right error when called with a value that is too big, but I am not sure if this is possible as Arbitrary needs to return Self?

Additionally, when from_random is implemented for fixed size primitives (eg U256) should resize(255, 0) be used instead of truncate?

Alternatively, I can implement from_random as:

impl Foo {
  fn from_random(g: &mut Gen) -> Self {
    let mut bar: B0255 = Gen::new(255);
    bar: B0255 = Vec::<u8>::arbitrary(&mut bar).try_into().unwrap();
    Foo { bar }
  }
}

Which, if either, from_random implementation is the idiomatic way to generate a vector of a specific size?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions