84 lines
2.7 KiB
Rust
84 lines
2.7 KiB
Rust
mod string;
|
|
mod fmt_debug;
|
|
|
|
// when a String is passed to this function a move occurs:
|
|
// BUT only the stack allocation (ptr, len, cap) is copied over
|
|
// AND the underlying heap is preserved, without copy
|
|
//
|
|
// Why do we call it a "move"?
|
|
// A move indicates ownership transfer, not data transfer
|
|
fn takes_string(_s: String) {
|
|
|
|
}
|
|
|
|
fn takes_string_ref(_s: &String) {
|
|
|
|
}
|
|
|
|
// Compilation error and warning:
|
|
// rustc: the size for values of type `str` cannot be known at compilation time
|
|
// the trait `Sized` is not implemented for `str` [E0277]
|
|
// rustc: function arguments must have a statically known size,
|
|
// borrowed types always have a known size: `&` [E0277]
|
|
//
|
|
// Ok, so rust is an unsized type,
|
|
// and compiler requires sized types for function params at compile time
|
|
//
|
|
// Why is this a problem?
|
|
// rust doesn't know how much space to allocate for the variable
|
|
//
|
|
// str inactuality is the raw (UTF-8) bytes, not a container
|
|
// fn takes_str(s: str) { }
|
|
|
|
// this is fine because now the variable is a fat pointer: pointer + length
|
|
// it's the length aspect that makes us abot to work on the str
|
|
fn takes_str_ref(_s: &str) {
|
|
|
|
}
|
|
|
|
// yeah, we can do this
|
|
fn _get_static_str() -> &'static str {
|
|
"hello"
|
|
}
|
|
|
|
fn main() {
|
|
println!("Hello, world!");
|
|
fmt_debug::test_report();
|
|
|
|
let s = String::new(); // no heap allocation until we add characters (capacity > 0)
|
|
|
|
// let s_r: str; // ERROR: size not known at compile time
|
|
let _s_rr: &str; // allowed
|
|
let _s_rrr: &String; // allowed
|
|
|
|
takes_string_ref(&s);
|
|
takes_string_ref(&s); // works because the string was not moved in first call
|
|
|
|
let ss = String::from("1"); // one heap allocation!
|
|
takes_string(ss); // move occurs here
|
|
// takes_string(ss); // ERROR: use of moved value here
|
|
// takes_string_ref(&ss); // ERROR: borrow of moved value here
|
|
|
|
let sss = String::new();
|
|
// deref coersion:
|
|
// because String implements the trait Deref<Target = str>
|
|
takes_str_ref(&sss);
|
|
// *sss dereferences the String into its underlying str
|
|
takes_str_ref(&*sss); // same as this!
|
|
takes_str_ref(sss.as_ref()); // and this!
|
|
|
|
let s4 = String::from("string4");
|
|
//let s4_slice = s4[0..]; // again we hit no size problem at compile time
|
|
let _s4_slice = &s4[0..]; // but this works, because the &str has the length!
|
|
|
|
// literals
|
|
// &'static str is held onto by &str:
|
|
// that's the programs read-only binary
|
|
let s_lit = "easy as pie, right?";
|
|
let _s_lit2 : &str = "easy as pie, right?"; // same, data not copied, we just point to it
|
|
let _s5 = String::from("literal is copied to heap"); // data copied to heap
|
|
let _s6 = String::from(s_lit); //underlying data copied to heap
|
|
|
|
// todo: Cow
|
|
}
|