Rust 复杂函数参数 (结构体+枚举+元组+数组)

wasm-bindgen 开发指南 (wasmdev.cn) - 官方文档

Rust 不是面向对象的编程语言,没有类的概念(Class),但是它具有一些面向对象的特性

它有结构体 Struct 和枚举 Enum ,通过结构体和枚举等类型,可以用来封装属性数据

结构体本身,不能直接定义函数,但可以在结构体的实现(impl 块),为结构体定义方法

枚举成员本身,不能直接添加方法,但可以通过关联函数来达到添加函数的效果(impl 块)


目录:
一、Rust 方法格式
二、Rust 结构体
        1、定义结构体
        2、结构体实例化
        3、定义结构体的方法
        4、输出结构体
三、Rust 枚举类
        1、定义枚举类
        2、实例化枚举类
        3、定义枚举类的方法
四、trait 特征对象
五、编写 rust 和 JS 代码(关键)
        1、必备的结构
        2、结构体参数
        3、枚举类参数
        4、元组参数
        5、数组/切片参数
        6、混合参数


一、Rust 方法格式

        impl  结构体名 | 枚举名 | 特征名 {                            // Rust 使用 impl关键字定义方法
                 函数1
                 函数2 ...
        }

二、Rust 结构体

Rust 的结构体(Struct)与元组(Tuple)都可以将若干个类型不一定相同的数据捆绑在一起形成整体,但结构体的每个成员和其本身都有一个名字,访问成员时,不用下标,直接用名字即可。

1、定义结构体

        struct Site {                 // 结尾无分号,每个字段定义后逗号分隔(区别于C/C++)
            domain: String,
            name: String,
            nation: String,
            width: u32,
            height: u32,
        
}

2、结构体实例化

Rust 很多地方受 JS 的影响,在实例化结构体时,经常采用 JSON 对象 key: value 语法格式

        let runoob = Site {                   
            domain: String::from( "www.runoob.com" ),
            name: String::from( "RUNOOB" ),
            nation: String::from( "China" ),
            width: 30,
            eight: 50
        };

3、定义结构体的方法

Rust 使用 impl关键字定义方法,方法的第一个参数必须是 &self,但在调用时,无需填写 self 

        impl  Site {                                                               // 同名                   
                fn distance(&self) -> f64 {                               // &self :引用当前结构体的实例
                        (self.x * self.x + self.y * self.y)  as f64      // 如需类型转换,则需明确写出目标类型
                }
        }

注:&self 是 self: &Self 的简写,作用是通过 self 访问 当前结构体的实例

4、输出结构体

Rust 提供了一种输出整个结构体实例的方法,这在调试中,是非常有用的

         #[derive(Debug)]                                               // 引用调试库,放在代码第一行
......   println!("rect1 is {:?} ", rect1);                            // 用 {:?} 占位符输出一整个结构体

三、Rust 枚举类

枚举的目的是对某一类事物的分类,分类的目的是为了对不同的情况进行描述。

1、定义枚举类

        无需描述:enum Book{    Papery, Electronic,    }

        类型描述:enum Book {   Papery(u32), Electronic(String),   }

        属性命名:enum Book {   Papery{  index: u32  }, Electronic{  url: String  }, }

2、实例化枚举类

        let  book  = Book::Papery{  index: 1001  };

        let ebook = Book::Electronic{ url: String::from("url...") };

注1:创建一个 Book 枚举类型的实例  book, 为 Papery 变体,并设置索引为 1001

注2:创建一个 Book 枚举类型的实例 ebook,为 Electronic 变体,并设置 URL 为指定的字符串

3、定义枚举类的方法

枚举是为了对某一类事物的进行分类,再根据事物所属的枚举值,去执行相应的操作

        impl Book {
                fn description(&self) -> &'static str {        // 访问成员,返回一个静态不可变字符串
                         match self {                                       // 辨别成员,使用 match 分支判断语句
                                 Book::Papery => "这是纸质书",
                                 Book::Electronic => "这是电子书",
                        }
                }
        }

四、trait 特征对象

在 Rust 中,trait 类似接口,它定义了一组方法的签名(名称、参数、返回类型),而不提供具体的实现。任何类型(如结构体、枚举等)都能通过 impl实现 trait 中定义的方法。

        trait Draw {                                      // 定义特征 Draw,其中包含 draw 方法的签名
                fn draw(&self);               
        }

        struct Circle;

        impl Draw for Circle {                      // 为结构体实现了该特征,拥有了其中的方法
                fn draw(&self) {
                        println!("Drawing a circle");
                }
        }

        struct Square;

        impl Draw for Square {                     // 同上
                fn draw(&self) {
                        println!("Drawing a square");
                }
        }

        fn draw_shape(shape: &dyn Draw) {    // 为关联函数实现了该特征,拥有了其中的方法
                shape.draw();
        }

注:关联函数:指的是定义在 impl 中,且没有 self 的函数。它没有 self,即不能用 obj.method 的形式调用,而是使用::的形式来调用。因此它是函数不是方法。

五、编写 rust 和 JS 代码(关键)

编写代码的过程中,有三个难点:
        1、写出一个正确可运行的 rust 代码
        2、根据 wasm 语法规则,对 rust 代码进行改写,将 rust 的相关内容暴漏给 JavaScript
        3、写出一个可以调用 wasam 的 JavaScript 代码

注:wasm-bindgen 有其特定的语法规范,如果不遵循其规则,就很可能会导致 rust 的编译失败。比较麻烦的是,明明按照 wasm-bindgen 语法写了,但还是报错,定位错误的时候很麻烦。

1、必备的结构

        use wasm_bindgen::prelude::*;

        #[wasm_bindgen]

        ****pub rust函数代码****

注1:第一句,意思是引入 wasm_bindgen 库(一种 Rust 库)的“预备”(prelude)模块,该模块包含一些最常用的函数、宏或类型。当开发者要用某些函数时,就可以从这个模块中直接引用。

注2:第二句,它是一种属性,主要用于标记: ① 标记Rust 导出给 JavaScript 的函数、结构体、枚举、变量等内容;② 标记从 JavaScript 导入到 Rust 中的函数。标记完成后 wasm-bindgen工具,就会根据标记和相关设置,生成相应的 JavaScript 绑定代码

注3:pub关键字,主要用于搭配上述属性。因为 Rust 中的内容默认都是私有的,外部无法调用。

2、结构体参数

        use wasm_bindgen::prelude::*;                  // 按照 wasm 语法,改写 Rust 代码

        #[wasm_bindgen]
        #[derive(Debug)] 
        pub  struct Square {                                   // 定义结构体和相关字段
                pub width: u32,
                pub height: u32,
        }

        #[wasm_bindgen]
        pub
  impl Square {                                                       // 定义结构体的方法               
                pub  fn  new(width: u32, height: u32) -> Self {     // 构造函数,被 JS 调用后,创建实例
                        Self {  width, height  }                   
                }                                                        
                pub  fn  area(&self) -> u32 {                                // 功能函数,操作实例
                        self.width * self.height
                }
        }

注1:new 不是关键字,new()方法,用于创建 Square 对象的构造函数,标记为 pub ,方便后续 JavaScript 调用,使用 Self 关键字 引用当前的类型,创建一个新的结构体实例(看注2)

注2:在 JavaScript 代码中,使用 const square01 = Square.new(5, 10),即创建一个 Square 实例,并将其存储在 square01 变量中。

注3:area()方法,用于实现特定的功能,标记为 pub ,方便后续 JavaScript 的实例对象去调用

3、枚举类参数

由于 JavaScript 原生不支持枚举类型,无法处理 Rust 枚举类型。虽然 wasm_bindgen 能实现 Rust 类型到 JS 类型的转换,但对于枚举类型,它通常不能直接映射,但它们也不会阻止导出。

解决办法:   法一:用整数或字符串代替枚举              法二:只导出与枚举相关的函数
下面的实例,两种方法都用到

        use wasm_bindgen::prelude::*;

        #[wasm_bindgen]
        #[derive(Copy, Clone, Debug)]
        pub enum Season {                       // 定义枚举类型
                Spring = 1,                              // 为每个枚举值,关联一个整数编码,让 JS 理解
                Summer = 2,
                Autumn = 3,
                Winter = 4,
        }

        #[wasm_bindgen]                               // 不去定义枚举类的方法,而是定义一个普通的方法
        pub fn get_season_description(season_id: i32) -> String {                   // 编码值作为参数
                match season_id {                                                                         // match 分支判断
                        1 => "It's spring, time for new beginnings!".to_string(),  
                        2 => "It's summer, enjoy the warmth and sunshine!".to_string(),  
                        3 => "It's autumn, witness the beauty of changing leaves!".to_string(),  
                        4 => "It's winter, embrace the cold and snow!".to_string(),  
                        _ => "Unknown season".to_string(),                     // 用于 match 语句中的默认情况
               }  
        }  

4、元组参数

        use wasm_bindgen::prelude::*;             

        #[wasm_bindgen]  
        pub
  fn my_function( tuple: (i32, String )){       // 元组,作为函数参数,供 JavaScript 调用
                let (num, str) = tuple;                                  // 解构
                println!("Number: {}", num);
                println!("String: {}", str);
        }

5、数组/切片参数

        use wasm_bindgen::prelude::*;             

        #[wasm_bindgen]  
        pub
  fn process_fixed_array(arr: [i32 ; 5]) {    // 数组,作为函数参数,供 JavaScript 调用
                for num in arr {
                        println!("{}", num);
                }
        }

        pub  fn process_slice(arr: &[i32]) {              // 数组切片,作为函数参数,供 JavaScript 调用
                for num in arr {
                        println!("{}", num);
                }
        }

6、混合参数

实现一个函数,同时接受以上所有类型的参数,再进行对应的操作(直接混合即可)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值