Have a question: does the slice have any extra data for example zero at the end of the string or size of the string at the beginning of the string?
In this code:
use std::collections::HashMap;
fn main()
{
let mut hashmap : HashMap< &'static str, &'static str > = HashMap::new();
hashmap.insert( "EUR", "Euro" );
hashmap.insert( "USD", "US Dollar" );
hashmap.insert( "CHF", "Swiss Francs" );
let usd = hashmap.get( "EUR" );
if let Some( usd ) = usd
{
println!( "usd : {}", usd );
}
// < usd : Euro
}
Key as well as the value of the HashMap let mut hashmap : HashMap< &'static str, &'static str > could have any length. Right? I don't understand how does the program knows usd has length/size of 4? Does the slice have any extra data for example zero at the end of the string or size of the string at the beginning of the string?
Slice types such as str or [u8] are called unsized types, which means that they can have many different sizes, as you have noticed yourself. Whenever you have any kind of reference or pointer to an unsized type, the reference itself will include some extra information that lets you determine the length as part of the reference itself. You should think of a &str as the following struct:
struct &str {
first_elem: &u8,
length: usize,
}
Of course this is made up syntax and it is not defined with an actual struct.
To illustrate the difference, try computing the size of references to sized and unsized types:
use std::mem::size_of;
fn main() {
println!("Size of &u32 is {}", size_of::<&u32>());
println!("Size of &str is {}", size_of::<&str>());
}
Size of &u32 is 8
Size of &str is 16
The &str is larger because it has both a pointer and a length.
This design is also why subslicing works. If you included the length at the start or a null byte at the end, then you couldn't implement &my_str[4..7] because it would have to modify the string it points at.