What does BigUint::from(24u32) do? - rust

BigUint::from(24u32)
I understand that it is related to a big unsigned integer since it is part of a cryptography module to factor big numbers. I don't understand what the part from(24u32) does.
For example, if it is used in this context
let b: BigUint = (BigUint::from(24u32) * &n).sqrt() + &one;

Conversions between types in Rust are defined by the From trait which defines a function from, so that Foo::from (bar) converts the value bar to the type Foo. In your case, you are therefore converting 24u32 to type BigUint, but what's this 24u32?
Integer literals in Rust can use a suffix to specify their actual type. If you wrote just 24, it could be for example an i32, a u8 or a u32. Most of the time the compiler is able to infer the actual type from the way the value is used, and when it can't it defaults to i32. But in your case that won't work: there is no BigUint::from<i32> but there are conversion functions for all the regular unsigned types: u8, u16, u32, u64 and u128, so the compiler doesn't know which one to use. Adding the u32 suffix clarifies the type, so 24u32 is the value 24 with the type u32, allowing the compiler to understand that you want BigUint::from<u32> (24).

The BigUint struct implements the From<u32> trait, which means that it will implement a from(u32) function.
Implementations of the From<_> trait are used to perform a value conversion that will consume the original input. In your example the BigUint struct is constructed from the 24u32 number.

Related

Do I have to use a usize to access elements of a vector?

I have a 2D vector that rejects indexing using i32 values, but works if I cast those values using as usize:
#[derive(Clone)]
struct Color;
struct Pixel {
color: Color,
}
fn shooting_star(p: &mut Vec<Vec<Pixel>>, x: i32, y: i32, w: i32, h: i32, c: Color) {
for i in x..=w {
for j in y..=h {
p[i][j].color = c.clone();
}
}
}
fn main() {}
When I compile, I get the error message
error[E0277]: the trait bound `i32: std::slice::SliceIndex<[std::vec::Vec<Pixel>]>` is not satisfied
--> src/main.rs:11:13
|
11 | p[i][j].color = c.clone();
| ^^^^ slice indices are of type `usize` or ranges of `usize`
|
= help: the trait `std::slice::SliceIndex<[std::vec::Vec<Pixel>]>` is not implemented for `i32`
= note: required because of the requirements on the impl of `std::ops::Index<i32>` for `std::vec::Vec<std::vec::Vec<Pixel>>`
If I change the code to have
p[i as usize][j as usize].color = c.clone();
Then everything works fine. However, this feels like it would be a really bizarre choice with no reason not to be handled by the Vec type.
In the documentation, there are plenty of examples like
assert_eq!(vec[0], 1);
By my understanding, if a plain number with no decimal is by default an i32, then there's no reason using an i32 to index shouldn't work.
Unlike Java, C# or even C++, numeric literals in Rust do not have a fixed type. The numeric type of a literal is usually inferred by the compiler, or explicitly stated using a suffix (0usize, 0.0f64, and so on). In that regard, the type of the 0 literal in assert_eq!(vec[0], 1); is inferred to be a usize, since Rust allows Vec indexing by numbers of type usize only.
As for the rationale behind using usize as the indexing type: a usize is equivalent to a word in the target architecture. Thus, a usize can refer to the index/address of all possible memory locations for the computer the program is running on. Thus, the maximum possible length of a vector is the maximum possible value that can be contained in a isize (isize::MAX == usize::MAX / 2). Using usize sizes and indices for a Vec prevents the creation and usage of a vector larger than the available memory itself.
Furthermore, the usage of an unsigned integer just large enough to refer all possible memory locations allows the removal of two dynamic checks, one, the supplied size/index is non-negative (if isize was used, this check would have to be implemented manually), and two, creating a vector or dereferencing a value of a vector will not cause the computer to run out of memory. However, the latter is guaranteed only when the type stored in the vector fits into one word.

How is from_raw_parts_mut able to transmute between types of different sizes?

I am looking at the code of from_raw_parts_mut:
pub unsafe fn from_raw_parts_mut<'a, T>(p: *mut T, len: usize) -> &'a mut [T] {
mem::transmute(Repr { data: p, len: len })
}
It uses transmute to reinterpret a Repr to a &mut [T]. As far as I understand, Repr is a 128 bit struct. How does this transmute of differently sized types work?
mem::transmute() does only work when transmuting to a type of the same size - so that means an &mut[T] slice is also the same size.
Looking at Repr:
#[repr(C)]
struct Repr<T> {
pub data: *const T,
pub len: usize,
}
It has a pointer to some data and a length. This is exactly what a slice is - a pointer to an array of items (which might be an actual array, or owned by a Vec<T>, etc.) with a length to say how many items are valid.
The object which is passed around as a slice is (under the covers) exactly what the Repr looks like, even though the data it refers to can be anything from 0 to as many T as will fit into memory.
In Rust, some references are not just implemented as a pointer as in some other languages. Some types are "fat pointers". This might not be obvious at first since, especially if you are familiar with references/pointers in some other languages! Some examples are:
Slices &[T] and &mut [T], which as described above, are actually a pointer and length. The length is needed for bounds checks. For example, you can pass a slice corresponding to part of an array or Vec to a function.
Trait objects like &Trait or Box<Trait>, where Trait is a trait rather than a concrete type, are actually a pointer to the concrete type and a pointer to a vtable — the information needed to call trait methods on the object, given that its concrete type is not known.

How do I solve the "missing associated type `Err` value" error?

I'm trying to make a simple utility function that reads multiple elements from stdin and puts them in collection and returns it. However I'm stuck at this point. The compiler says missing associated type Err value. How do I make it work, while keeping it generic as possible?
While this function seems useless, it's for learning the language and its type system.
use std::io::{ stdin };
use std::str::FromStr;
use std::io::Read;
use std::iter::FromIterator;
pub fn read_all<C>() -> C
where C: FromIterator<FromStr<Err>>
{
let mut buff = String::new();
stdin().read_to_string(&mut buff).expect("read_to_string error");
buff.split_whitespace()
.filter_map(|w| w.parse().ok())
.collect()
}
Usage example:
let v: Vec<i32> = read_all();
Working code
The only thing you need to change to your code in order to make it compile is the type signature of the function:
pub fn read_all<C, F>() -> C
where F: FromStr,
C: FromIterator<F>
Explanation
Your code is almost correct, but there is a problem:
FromIterator<T> is a trait, but T is a type.
You use FromStr in the place of T, but FromStr is a trait, not a type.
To solve this, you need to get a type that implements FromStr. You can do this by adding a type parameter F to the function and constraining it with where F: FromStr. Then you can write FromIterator<F>.
A note on associated types
Besides the issue of using a trait instead of a type, typing FromStr<Err> is wrong syntax. While in this case it is not necessary to specify the type of Err in the FromStr trait, you could do it as shown below:
pub fn read_all<C, F, E>() -> C
where F: FromStr<Err=E>,
C: FromIterator<F>
As you can see, instead of writing FromStr<E> we need to write FromStr<Err=E>. That is, you need to explicitly type the name of the associated type you are referring to.
A note on types vs traits
Usually traits cannot be treated as types. However, there are exceptions to this rule, as illustrated by the example below:
use std::fmt::Display;
pub fn print_box(thing: Box<Display>) {
println!("{}", thing)
}
fn main() { print_box(Box::new(42)); }
Here, you would expect T in Box<T> to be a type, but the Display trait is supplied instead. However, the compiler does not reject the program. The type checker sees Display as an unsized type. That is, the type of an object with a size unknown at compile time (because it could be any type implementing Display). When T in Box<T> is a trait, the resulting type is usually referred to as a trait object. It is impossible to cover this topic in depth here, but the links I refer to are a good starting point in case you want to know more.

Is there any way to restrict a generic type to one of several types?

I'm trying to create a generic struct which uses an "integer type" for references into an array. For performance reasons I'd like to be able to specify easily whether to use u16, u32 or u64. Something like this (which obviously isn't valid Rust code):
struct Foo<T: u16 or u32 or u64> { ... }
Is there any way to express this?
For references into an array usually you'd just use a usize rather than different integer types.
However, to do what you are after you can create a new trait, implement that trait for u16, u32 and u64 and then restrict T to your new trait.
pub trait MyNewTrait {}
impl MyNewTrait for u16 {}
impl MyNewTrait for u32 {}
impl MyNewTrait for u64 {}
struct Foo<T: MyNewTrait> { ... }
You may then also add methods onto MyNewTrait and the impls to encapsulate the logic specific to u16, u32 and u64.
Sometimes you may want to use an enum rather than a generic type with a trait bound. For example:
enum Unsigned {
U16(u16),
U32(u32),
U64(u64),
}
struct Foo { x: Unsigned, ... };
One advantage of making a new type over implementing a new trait for existing types is that you can add foreign traits and inherent behavior to the new type. You can implement any traits you like for Unsigned, like Add, Mul, etc. When Foo contains an Unsigned, implementing traits on Unsigned doesn't affect the signature of Foo like it would to add them as bounds on Foo's parameter (e.g. Foo<T: Add<Output=Self> + PartialCmp + ...>). On the other hand, you do still have to implement each trait.
Another thing to note: while you can generally always make a new type and implement a trait for it, an enum is "closed": you can't add new types to Unsigned without touching the rest of its implementation, like you could if you used a trait. This may be a good thing or a bad thing depending on what your design calls for.
"Performance reasons" is a bit ambiguous, but if you're thinking of storing a lot of Unsigneds that will all be the same internal type, and this:
struct Foo([Unsigned; 1_000_000]);
would waste a ton of space over storing a million u16s, you can still make Foo generic! Just implement From<u16>, From<u32>, and From<u64> for Unsigned and write this instead:
struct Foo<T: Into<Unsigned>>([T; 1_000_000]);
Now you only have one simple trait bound on T, you're not wasting space for tags and padding, and functions that deal with T can always convert it to Unsigned to do calculations with. The cost of the conversion may even be optimized away entirely.
See Also
Should I use enum to emulate the polymorphism or use trait with Box<trait> instead?

Is it possible to return part of a struct by reference?

Consider the following two structs:
pub struct BitVector<S: BitStorage> {
data: Vec<S>,
capacity: usize,
storage_size: usize
}
pub struct BitSlice<'a, S: BitStorage> {
data: &'a [S],
storage_size: usize
}
Where BitStorage is practically a type that is restricted to all unsigned integers (u8, u16, u32, u64, usize).
How to implement the Deref trait? (BitVector<S> derefs to BitSlice<S> similar to how Vec<S> derefs to &[S])
I have tried the following (Note that it doesn't compile due to issues with lifetimes, but more importantly because I try to return a value on the stack as a reference):
impl<'b, S: BitStorage> Deref for BitVector<S> {
type Target = BitSlice<'b, S>;
fn deref<'a>(&'a self) -> &'a BitSlice<'b, S> {
let slice = BitSlice {
data: self.data,
storage_size: self.storage_size,
};
&slice
}
}
I am aware that it is possible to return a field of a struct by reference, so for example I could return &Vec<S> or &usize in the Deref trait, but is it possible to return a BitSlice noting that I essentially have all the data in the BitVector already as Vec<S> can be transformed into &[S] and storage_size is already there?
I would think this is possible if I could create a struct using both values and somehow tell the compiler to ignore the fact that it is a struct that is created on the stack and instead just use the existing values, but I have got no clue how.
Deref is required to return a reference. A reference always points to some existing memory, and any local variable will not exist long enough. While there are, in theory, some sick tricks you could play to create a new object in deref and return a reference to it, all that I'm aware of result in a memory leak. Let's ignore these technicalities and just say it's plain impossible.
Now what? You'll have to change your API. Vec can implement Deref because it derefs to [T], not to &[T] or anything like that. You may have success with the same strategy: Make BitSlice<S> an unsized type containing only a slice [S], so that the return type is &'a BitSlice<S>. This assume the storage_size member is not needed. But it seems that this refers to the number of bits that are logically valid (i.e., can be accessed without extending the bit vector) — if so, that seems unavoidable1.
The other alternative, of course, is to not implement a Deref. Inconvenient, but if your slice data type is too far from an actual slice, it may be the only option.
RFC PR #1524 that proposed custom dynamically-sized types, then you could have a type BitSlice<S> that is like a slice but can have additional contents such as storage_size. However, this doesn't exist yet and it's far from certain if it ever will.
1 The capacity member on BitVector, however, seems pointless. Isn't that just sizeof S * 8?

Resources