Strings

  • Explanation .

    • At the end of the video there is a summary.

  • No null terminator.

  • All strings are valid UTF-8.

  • Immutable by default.

Append
  • Example:

  • With format!

    let s1 = String::from("hello ");
    let s2 = String::from("world");
    let s3 = format!("{}{}", s1, s2);
    
    • This macro uses references so that this call doesn’t take ownership of any  of its parameters.

  • With concatenation:

    let s1 = String::from("hello ");
    let s2 = String::from("world");
    let s3 = s1 + &s2;  // s1 is moved.
    
  • With .push  or .push_str :

    let mut s = String::from("hello");
    s.push_str("bar");   // Receives a string slice.
    s.push('!');         // Receives a char.
    
Accessing characters
for c in "hello world".chars() {
    println!("{c}");
}

Formatting

let x = 5;
let y = 10;

println!("x = {x} and y + 2 = {}", y + 2);

Types

Literals
  • Raw strings :

    • They are the same:

    let text = "he said \"goodbye\" and left";
    let text = r#"he said "goodbye" and left"#;
    
    • This is used to avoid having to use \  every time you want to use quotes inside strings.

    • Very useful for RegEx.

  • Byte strings :

    let http_ok = b"HTTP/1.1 200 OK\r\n";
    let http_ok: &[u8; 17] = b"HTTP/1.1 200 OK\r\n";
    
    • Creates a 'slice of bytes'.

    • Useful when dealing with network protocols that expect a byte sequence, such as HTTP.

String (String)
let my_string: String = String::from("hello!");
  • Owned type.

  • **Use:

    • Create and modify strings.

      • Read files.

      • User inputs.

&str (string slice)
let my_string: &str = &my_string; 
  • Borrowed type.

    • Not the owner, just has access.

  • Read-only.

  • It's a pointer to the start of the string and the length of the string.

  • **Use:

    • Read and analyze an existing string without changing it.

      • Parse a string

      • Search for a substring.

  • Static:

    let my_string: &str = "hello world";
    let my_string: &'static str = "hello world";
    
    • Both represent the same thing.

    • The 'static' indicates the pointed value is guaranteed to be available for the entire runtime of the program.

Box<str> (boxed string slice)
  • Owned, non-growable, heap-allocated string slice.

  • "Freeze a string to prevent further modification".

let my_string: String = String::from("this is a long string");
let my_boxed_str: Box<str> = my_string.into_boxed_str();
  • This drops the capacity information, reducing memory usage.

Rc<str> (Reference counted string slice)
  • Shared, immutable string slice.

  • Not thread-safe.

  • "~duplicate an object without duplicating it in memory", something like that.

Arc<str> (Atomic reference counted string slice)
  • Same as Rc<str> , but thread-safe.

  • Useful when you want to use the string across different threads.

Vec<u8> (Vector of UTF-8 bytes)
  • It's basically the same thing as String .

  • Useful when dealing with non-UTF-8 encoded strings.

Specialized string types, less known

&mut str (mutable reference to a sequence of string bytes)
  • Normally avoided in idiomatic Rust code because it's complex and poses potential problems ensuring the content remains valid UTF-8.

Cow<'a, str> (copy on write)
  • I didn't quite understand it.

Interoperability

  • "Helps connect Rust code with other languages".

OsString, OsStr
  • Can contain any byte sequence, not just UTF-8.

Path
  • Deals with paths.

  • Used to inspect filesystem paths.

PathBuf
  • "mutable and owned version of a path".

CString, CStr
  • Useful when interacting with C code that expects a null terminator.