- unsafe-rust
- advance-trait
- trait-ref-type 与trait相关的关联类型
- default type param 默认参数类型
- fully qualified syntax 完全限定语法
- supertraits 超父类
- newtype模式
- advance-type
- more about new-type pattern
- type alias 类型别名
- never type
- dymatic-size type 动态大小类型
- advance function and closure
- function point 函数指针
- return closure 返回闭包
- macro 宏
unsafe-rust
the-addional-super power of unsafe
- 解引用裸指针
- 调用不安全的函数或方法
- 访问或修改可变静态变量
- 实现不安全的trait
- 访问union字段
the owner-check is still on
unref-raw-point
- ignore owner-rule, allow mut and immute ref.
- not ensure the point valid
- allow empty
- not implement auto-clean.
/// create immute and mut raw-point
/// you can create raw-point in safe-code, but can only deref it in unsafe code.
let mut num = 5;
let r1 = &num as *const i32;
let r2 = &mut num as *mut i32;
unsafe {
println!("r1 is: {}", *r1);
println!("r2 is: {}", *r2);
}
/// unsure validate raw-point
let address = 0x123456usize;
let r = address as &const i32;
call unsafe function or method
unsafe fn dangerous() {}
unsafe {
dangerous();
}
/// can create safe-abstaction on unsafe-code
/// rust cannot understand ref twice
use std::slice;
fn split_at_mut(slice: &mut [i32], mid: usize) -> (&mut [i32], &mut[i32]) {
let len = slice.len();
let ptr = slice.as_mut_ptr();
assert!(mid <= len);
unsafe {
(slice::from_raw_parts_mut(ptr, mid),
slice::from_raw_parts_mut(ptr.add(mid), len - mid))
}
}
use extern
to call extern-code
foreign function interface, FFI applicaton binary interface, ABI
extern "C" {
fn abs(input: i32) -> i32;
}
/// export extern-function must add ~no_mangle~
#[no_mangle]
pub extern "C" fn call_from_c() {
println!("Just called a rust function from c!", );
}
fn main() {
unsafe {
println!("Absolute value of -3 according to C: {}", abs(-3));
}
}
visit or modify mutable-static variable
static mut COUNTER: u32 = 0;
fn add_to_count(inc: u32) {
unsafe {
COUNTER += inc;
}
}
fn main() {
add_to_count(3);
unsafe {
println!("COUNTER: {}", COUNTER);
}
}
implement unsaf-trait
unsafe trait Foo {
}
unsafe impl Foo for i32 {
}
advance-trait
associated types
pub trait Iterator {
/// 占位类型
type Item;
fn next(&mut self) -> Option<Self::Item>;
}
impl Interator for Counter {
/// unlike generic, this can only choose once.
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
// -snip-
}
}
/// generic can implement multi-times,
/// and need add generic-param
pub trait Iterator<T> {
fn next(&mut self) -> Option<T>;
}
impl Iterator<String> for Counter {
fn next<String>(&mut self) -> Option<String> {
// -snip-
}
}
impl Iterator<u32> for Counter {
fn next<u32>(&mut self) -> Option<u32> {
// -snip-
}
}
add default-type for Generic, A good example is Operator-overloading(运算符重载)
rust not allow create-op or overload-op, but can implement op list in std::ops
.
use std::ops::Add;
#[derive(Debug, PartialEq)]
struct Point {
x: i32,
y: i32,
}
impl Add for Point {
type Output = Point;
fn add(self, other: Point) -> Point {
Point {
x: self.x + other.x,
y: self.y + other.y,
}
}
}
/// Add Trait
// RHS is default-type-paramters, 默认类型参数
trait Add<RHS=Self> {
type Output;
fn add(self, rhs: RHS) -> Self::Output;
}
/// default-type-paramters can
/// 1) extends type and not broke existing-code
/// 2) customer in most-people not-need situation
struct Millimeters(u32);
struct Meters(u32);
impl Add(Meters> for Millimeters {
type Output = Millimeters;
fn add(self, other: Meters) -> Millimeters {
Millimeters(self.0 + (other.0 * 1000))
}
}
完全限定语法与消除歧义: 调用相同名称的方法 rust neither can avoid traits has same method-name, nor can avoid implement the two traits for same type.
trait Pilot {
fn fly(&self);
}
trait Wizard {
fn fly(&self);
}
struct Human;
impl Pilot for Human {
fn fly(&self){
println!("This is your captain speaking.");
}
}
impl Wizard for Human {
fn fly(&self) {
println!("Up!");
}
}
impl Human {
fn fly(&self) {
println!("*waving arms furiously*");
}
}
fn main() {
let person = Human;
/// this call method implement for type.
person.fly();
/// call method from certain trait
Pilot::fly(&person);
Wizard::fly(&person);
}
/// static-method or assoicate-method have no self-paramters.
/// so cannot use above method to call Trait-method.
/// you need to use *完全限定语法*
trait Animal {
fn baby_name() -> String;
}
struct Dog;
impl Dog {
fn baby_name() -> String {
String::from("Spot")
}
}
impl Animal for Dog {
fn baby_name() -> String {
String::from("puppy")
}
}
fn main() {
println!("A baby dog is called a {}", Dog::baby_name());
// *完全限定语法* syntax <Type as Trait>::function(receiver_if_method, next_arg, ...);
println!("A baby dog is called a {}", <Dog as Animal>::baby_name());
}
use other-trait functions in current trait. the depends-on trait also need tobe implemented. the depends-on trait is supertrait of current-trait.
use std::fmt;
trait OutlinePrint: fmt::Display {
fn outline_print(&self) {
let output = self.to_string();
let len = output.len();
println!("{}", "*".repeat(len + 4));
println!("*{}*", " ".repeat(len + 2));
println!("* {} *", output);
println!("*{}*", " ".repeat(len + 2));
println!("{}", "*".repeat(len + 4));
}
}
struct Point {
x: i32,
y: i32,
}
impl fnt::Display for Point {
fn fmt(&self, &mut fmt::Formatter) -> fmt::Result {
write!(f, "({}, {})", self.x, self.y)
}
}
/// this world raise if not implement Debug-Trait
impl OutlinePrint for Point {}
newtype 模式用以在外部类型上实现外部trait, newtype was concept come from haskell. no speed punish in runtime. you may need implement every-method in inner-type or implement-Deref trait.
use std::fmt;
struct Wrapper(Vec<String>);
impl fmt::Display for Wrapper {
fn fmt(&selff, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[{}]", self.0.join(", "))
}
}
fn main() {
let w = Wrapper(vec![String::from("hello"), String::from("world")]);
println!("w = {}", w);
}