/* --- 结构体 --- */
/* #[derive(Debug)]
struct User {
    username: String,
    email: String,
    sign_in_count: u64,
    active: bool,
}

fn main() {
    // 一旦实例可变，所有字段都可变
    let mut user1 = User {
        email: String::from("someone@example.com"),
        username: String::from("someusername123"),
        active: true,
        sign_in_count: 1,
    };

    user1.email = String::from("anotheremail@example.com");

    // 结构体更新语法 ..<instance>
    let user2 = User {
        email: String::from("another@example.com"),
        username: String::from("anotherusername567"),
        ..user1 // 注意不会像 JS 一样字段被后面覆盖
    };

    println!("{:?}", user2);

    // 使用不需要对字段命名的[元组结构体]来创建不同的类型
    struct Color(i32, i32, i32);
    struct Point(i32, i32, i32);

    let black = Color(0, 0, 0);
    let origin = Point(0, 0, 0);

    // struct QUser {
    //     username: String,
    //     email: &str, // missing lifetime specifier
    //     sign_in_count: u64,
    //     active: bool,
    // }
}

// 在函数体最后一个表达式中构造构造结构体实例，隐式地将这个实例作为结果返回
fn builder_user(email: String, username: String) -> User {
    User {
        email,
        username,
        active: true,
        sign_in_count: 1,
    }
} */

/* --- 结构体中的引用 --- */

// 生命周期保证了结构体实例中引用数据的有效期不短于实例本身
/* #[derive(Debug)]
struct User<'a> {
    username: &'a str,
    email: &'a str,
    sign_in_count: u64,
    active: bool,
}

fn main() {
    let s = "sss";
    let user1 = User {
        email: "someone@example.com",
        username: s,
        active: true,
        sign_in_count: 1,
    };
    println!("{:?}", user1);
    drop(user1);
    println!("{}", s); // "sss"

    // println!("{}", s); // "sss" ?
} */

/* --- 计算长方形面积 --- */
/* #[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

fn main() {
    // let width1 = 30;
    // let height1 = 50;
    // let rect1 = (width1, height1);
    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };

    println!(
        "The area of the rectangle is {} square pixels.",
        area(&rect1)
    );

    println!("check ownership {:?}", rect1);
}

// 原方程
// fn area(width: u32, height: u32) -> u32 {
//     width * height
// }

// 通过元组重构(缺点: 不直观)
// fn area(dimensions: (u32, u32)) -> u32 {
//     dimensions.0 * dimensions.1
// }

// 使用结构体增加有意义的描述(此处为结构体的不可变借用)
fn area(rectangle: &Rectangle) -> u32 {
    // 引用类型 ? 保留 main rect1 的所有权
    rectangle.width * rectangle.height
    // (*rectangle).width * (*rectangle).height // 等价
} */

/* --- 方法 --- */

// 方法被定义在某个结构体、枚举、trait 对象的上下文中，且第一个参数永远是 self

/* #[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    // 在结构体中定义 area 方法
    fn area(&self) -> u32 {
        self.width * self.height
    }

    // 增加 can_hold 方法
    fn can_hold(&self, other: &Rectangle) -> bool {
        self.width > other.width && self.height > other.height
    }
}

fn main() {
    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };

    let rect2 = Rectangle {
        width: 10,
        height: 40
    };

    println!(
        "The area of the rectangle is {} square pixels.",
        rect1.area()
    );
    println!(
        "Can rect1 hold rect2? {}", rect1.can_hold(&rect2)
    )
}
 */

/* --- 关联函数 associated function --- */

// 不会作用某个实例而是被用作构造器返回新实例
// 所以定义时不需要 &self，调用时也不需要实例

/* struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    fn square(size: u32) -> Rectangle {
        Rectangle {
            width: size,
            height: size,
        }
    }
}

fn main() {
    // let rect = Rectangle {
    //     width: 30,
    //     height: 50,
    // };

    let sq = Rectangle::square(3);
    // let sqtest = rect.square(3); // no method named `square` found for struct `Rectangle` in the current scope
    //  this is an associated function, not a method
} */
