Structs

Classic Structs

struct ColorClassicStruct {
    red: i32,
    green: i32,
    blue: i32,
}


let green = ColorClassicStruct {
    red: 0,
    green: 255,
    blue: 0,
};

assert_eq!(green.red, 0);
assert_eq!(green.green, 255);
assert_eq!(green.blue, 0);

Tuples

struct ColorTupleStruct(i32, i32, i32);


let green = ColorTupleStruct(0, 255, 0);

assert_eq!(green.0, 0);
assert_eq!(green.1, 255);
assert_eq!(green.2, 0);

Unit-Like Struct

Unit-like Struct: No fields, no data stored, behave similarly to ()

struct UnitLikeStruct;


let unit_like_struct = UnitLikeStruct;
let message = format!("{:?}s are fun!", unit_like_struct);

Patterns of methods arguments

  • fn get_char(data: String) takes the String by value, allowing you to modify the string data, but it will make a full copy of the string data, which can be expensive for large strings.
  • fn get_char(data: &String) takes a reference to a String, allowing you to access the string data, but not modify it.
  • fn get_char(mut data: &String) Wrong syntax - you cannot take a mutable reference to an immutable reference.
  • fn get_char(mut data: String) takes a mutable String, allowing you to modify the string data, but it will also make a full copy of the string data.
SyntaxOwnershipMutable
fn get_char(data: &String)CallerNo
fn get_char(mut data: &String)N/AN/A
fn get_char(data: String)Transferred to FunctionNo
fn get_char(mut data: String)Transferred to FunctionYes

Enum

enum Message {
    Quit,
    Move(Point),
    Echo(String),
    ChangeColor((u8, u8, u8)),
}

fn triggerSpecificEvent(message: Message) {
    // TODO: create a match expression to process the different message variants
    match message {
        Message::ChangeColor((a, b, c)) => change_color((a, b, c)),
        Message::Echo(s) => echo(s),
        Message::Move(p) => move_position(p),
        Message::Quit => quit(),
    }
}

Strings

  • String is a string type that is stored as a vector (Vec<u8>) of bytes, but it guarantees that it is a valid UTF-8 sequence. String is heap-allocated, growable, and not null-terminated.
  • &str is a string slice type that always points to a slice (&[u8]) of a valid UTF-8 sequence, and can be used to view the contents of a String, much like how &[T] is to Vec<T>. &str does not own the data it references, so it is typically used as a function parameter type.
  • The two differ primarily in ownership and heap allocation. When you need to modify strings, it is recommended to use the String type because it is mutable and owns the data, allowing you to modify its contents at will. When you only need to view or reference a string, it is recommended to use the &str type instead, because it is immutable and does not own the heap memory, reducing memory overhead and copying operations.
  • String processing functions in Rust usually take and return &str types instead of String types. This is because &str is more flexible and easier to use. If you need to convert a String to an &str type, you can use the & symbol or the as_str() method. If you need to convert an &str type to a String type, you can use the to_string() or to_owned() methods.

fn string_slice(arg: &str) { 
    println!("{}", arg);
}
fn string(arg: String) { 
    println!("{}", arg);
}

fn main() {
    let string1 = "blue"; // &str
    let string2 = String::from("hi"); // String
    let string3 = "rust is fun!".to_owned(); // String
    let string4 = "nice weather".into(); // String
    let string5 = format!("Interpolation Station"); // String
    let string6 = &String::from("abc")[0..1]; // &str
    let string7 = "   hello there   ".trim(); // &str
    let string8 = "Happy Monday!".replace("Monday", "Tuesday"); // String
    let string9 = "my SHIFT KEY IS STUCK".to_lowercase(); // String

    string_slice(string1);
    string(string2);
    string(string3);
    string(string4);
    string(string5);
    string_slice(string6);
    string_slice(string7);
    string(string8);
    string(string9);
}