[2023.09.26]: JsValue的转换体验与as关键字的浅析

昨天解决了焦点问题,今天就开始搬砖了。本以为可以一帆风顺,但是还是遇到了几个问题,不过还好,都被一一解决,这里我分享一下JsValue的转换体验以及关键字as的使用浅析。

场景描述

我是在什么情况下遇到JsValue的转换的呢?获取当前窗口的内部宽度和内部高度。api的接口定义如下:

pub fn inner_width(&self) -> Result<JsValue, JsValue>
pub fn inner_height(&self) -> Result<JsValue, JsValue> 

我使用当前窗口的内部宽度和内部高度的地方在Modal组件中:

#[derive(Properties, Clone, PartialEq)]
pub struct Props {...#[prop_or(200)]pub width: u32,#[prop_or(500)]pub height: u32,
}

也就是说,我要将JsValue转换成u32类型。

问题解决

先看这个问题最终是怎么解决的吧。和Javascript代码比起来,是稍微复杂了一点点。

pub fn get_window_size() -> Option<(u32, u32)> {if let Some(window) = get_window() {let width = window.inner_width().unwrap_or_else(|_| JsValue::from_f64(default_width1));let height = window.inner_height().unwrap_or_else(|_| JsValue::from_f64(default_height1));let width1: f64 = width.as_f64()?;let height1: f64 = height.as_f64()?;let width2 = width1 as u32;let height2 = height1 as u32;return Some((width2, height2));}None
}

逻辑比较简单,步骤如下

  1. 先通过window对象拿到widthheight;
  2. 通过方法as_f64将JsValue转换成f64类型;
  3. 通过rust的as关键字将f64类型转换成u32类型;

问题展开

从问题的解决层面上来说,明确上面3步,就可以拿到我们需要的数据,但是这显然只是冰山一角。水下面的东西很多,这里我挑2个容易的来说。

关于JsValue的数据转换

JsValue定义在wasm_bindgen中,关于数据转换的接口有下面这几个:

pub fn as_bool(&self) -> Option<bool>;
pub fn as_f64(&self) -> Option<f64>;
pub fn as_string(&self) -> Option<String>;pub const fn from_bool(b: bool) -> JsValue;
pub fn from_f64(n: f64) -> JsValue;
pub fn from_str(s: &str) -> JsValue;

也就是说,wasm_bindgen::JsValue中,只关心布尔值,字符串和数字,而数字在rust中使用的是f64,即rust std中支持的容量最大,精度最高的数字。JsValue代表了Javascript环境中的数据。因此,了解这一点,我们就可以自由的进行Javascript和Rust的数据交换了。

关于as

在上面的代码中,我们通过rust的as关键字,将f64数字类型转换成了u32数字类型。
在Rust中,as关键字可以用于类型转换,将一个类型转换为另一个类型,这里的类型必须原始类型(primitive types),但显然不是指所有的原始类型。
什么是原始类型呢?原始类型是Rust语言的基本的数据类型,它们是语言的一部分。Rust语言的原始类型包括一下几种:

布尔类型(bool):表示逻辑值,只能是true或false。
字符类型(char):表示单个Unicode字符。
整数类型(integer):包括有符号整数(i8、i16、i32、i64、isize)和无符号整数(u8、u16、u32、u64、usize)。
浮点数类型(floating-point):包括单精度浮点数(f32)和双精度浮点数(f64)。
元组类型(tuple):可以包含多个不同类型的值。
数组类型(array):包含固定长度的相同类型的值。
切片类型(slice):对数组的引用,可以动态指定长度。
指针类型(pointer):包括原始指针(const T和mut T)和引用(&T)。

在我们的问题场景中,我们用asf64转换成了u32。难道还能将tuple转换成u32不成,显然是不可能的。还好编译器会给出提示。

    let num1 = (-33, -5);let num: u32 = num1 as u32;

报错:

3 |     let num: u32 = num1 as u32;|                    ^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object

其实在这里,我用as关键字是迫不得已的。因为我没有在u32这个类型上找到impl TryFrom<f64> for u32这样的方法。那将f64类型的数据转换成u32类型的数据,编译器没有报错,是不是就意味着没有问题呢?在我们的问题场景中,应该是没有问题的。但是从数据本身的角度,是有问题的。

fn main() {let num: f64 = -323.3;let num1: u32 = num as u32;println!("numbers:{}, {}", num, num1);
}

打印结果如下:

numbers:-323.3, 0

我想你应该总结处理这里的规律了吧,再看看下面这段就让你大跌眼镜了:

fn main() {let num: i32 = -3;let num1: u32 = num as u32;println!("numbers:{}, {}", num, num1);
}

按照之前的f64u32的经验,打印的结果应该是:-3, 0,对吧?
错,结果也让我吓一跳:

numbers:-3, 4294967293 

u32的最大数值是:4294967295。
这里的水有多深,我就不往下说了,我怕淹死在这里,哈哈。

正确的做法是:

fn main() {let num: i32 = -3;let num1: u32 = u32::try_from(num).unwrap_or_else(|_| 0);println!("numbers:{}, {}", num, num1);
}

所以,关于使用as来转换数据,如果类型本身实现了TryFrom<T> for ...,那么就不要使用as来进行类型转换。

总结

在基于wasm_bindgen的WebAssembly开发过程中,JsValue与Rust原始数据类型之间的转换会是家常便饭。对于JsValue来说,它只关心布尔值,字符串和数字,分别对应Rust中的boolStringf64f64与其它Rust数字之间的转换需要依赖as关键字。但是,如果数字类型实现了TryFrom<T>这个trait,就不要使用as关键字来进行转换。

今天就到这里,欢迎大家留言交流。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/144780.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2023年十大开源项目:革新技术创新

来源整理 : 小托 | 开源社翻译组PM 翻译 : 张锋 | 开源社翻译 Open-source projects have revolutionized the world of software development by fostering innovation, collaboration, and community-driven contributions. These projects are often the backbone of countl…

iOS应用程序的签名、重签名和安装测试

目录 前言 打开要处理的IPA文件 设置签名使用的证书和描述文件 开始ios ipa重签名 前言 ipa编译出来后&#xff0c;或者ipa进行修改后&#xff0c;需要进行重新签名才能安装到测试手机&#xff0c;或者提交app store供apple 商店审核上架。ipaguard有签名和重签名功能&…

vue前端项目中添加独立的静态资源

如果想要在vue项目中放一些独立的静态资源&#xff0c;比如html文件或者用于下载的业务模板或其他文件等&#xff0c;需要在vue打包的时候指定一下静态资源的位置和打包后的目标位置。 使用的是 copy-webpack-plugin 插件&#xff0c;如果没有安装则需要先安装一下&#xff0c;…

记一次实战案例

1、目标&#xff1a;inurl:news.php?id URL&#xff1a;https://www.lghk.com/news.php?id5 网站标题&#xff1a;趋时珠宝首饰有限公司 手工基础判断&#xff1a; And用法 and 11: 这个条件始终是为真的, 也就是说, 存在SQL注入的话, 这个and 11的返回结果必定是和正常页…

【深度学习实验】卷积神经网络(三):自定义二维卷积层:步长、填充、输入输出通道

目录 一、实验介绍 二、实验环境 1. 配置虚拟环境 2. 库版本介绍 三、实验内容 0. 导入必要的工具包 1. 步长、填充 a. 二维互相关运算&#xff08;corr2d&#xff09; b. 二维卷积层类&#xff08;Conv2D&#xff09; c. 模型测试 d. 代码整合 2. 输入输出通道 a…

【冰糖R语言】创建R包(打包R程序)

目标&#xff1a;将现有R程序打包 可能涉及知识点&#xff1a;devtools包、usethis包、Rstudio软件 一、R包的类型 通常一个R包中包含以下元素&#xff1a; 1&#xff09;R文件夹&#xff1a;函数代码 2&#xff09;man文件夹&#xff1a;存放每个函数的注释文件 3&#x…

KNN(上):数据分析 | 数据挖掘 | 十大算法之一

⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ &#x1f434;作者&#xff1a;秋无之地 &#x1f434;简介&#xff1a;CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作&#xff0c;主要擅长领域有&#xff1a;爬虫、后端、大数据…

36 二叉树中序遍历

二叉树中序遍历 题解1 递归题解2 迭代 给定一个二叉树的根节点 root &#xff0c;返回它的 中序 遍历 。 提示&#xff1a; 树中节点数目在范围 [0, 100] 内-100 < Node.val < 100 进阶: 递归算法很简单&#xff0c;你可以通过迭代算法完成吗&#xff1f; 题解1 递归…

解决大模型行业落地三大挑战,华为云GaussDB向量数据库正式发布

随着AI大模型产品及应用呈现爆发式增长,新的AI时代已经到来。向量数据库可与大语言模型配合使用,解决大模型落地过程中的痛点,已成为企业数据处理和应用大模型的必选项。在近日举行的华为全联接大会2023期间,华为云正式发布GaussDB向量数据库。GaussDB向量数据库基于GaussD…

Nodejs+vue高校机房设备管理系统jt07u

开发语言 node.js 框架&#xff1a;Express 前端:Vue.js 数据库&#xff1a;mysql 数据库工具&#xff1a;Navicat 开发软件&#xff1a;VScode 集成IDE对高校机房设备管理系统统进行开发,整合系统的各个模块。 拟开发的高校机房设备管理系统通过测试,确保在最大负载的情况下…

亚马逊无线鼠标FCC认证办理 FCC ID

无线鼠标是指无线缆直接连接到主机的鼠标&#xff0c;采用无线技术与计算机通信&#xff0c;从而省却电线的束缚。通常采用无线通信方式&#xff0c;包括蓝牙、Wi-Fi (IEEE 802.11)、Infrared (IrDA)、ZigBee (IEEE 802.15.4)等多个无线技术标准。随着人们对办公环境和操作便捷…

Polygon Miden:扩展以太坊功能集的ZK-optimized rollup

1. 引言 Polygon Miden定位为zkVM&#xff0c;定于2023年Q4上公开测试网。 zk、zkVM、zkEVM及其未来中指出&#xff0c;当前主要有3种类型的zkVM&#xff0c;括号内为其相应的指令集&#xff1a; mainstream&#xff08;WASM, RISC-V&#xff09;EVM&#xff08;EVM bytecod…

C理解(一):内存与位操作

本文主要探讨C语言的内存和为操作操作相关知识。 冯诺依曼结构和哈佛结构 冯诺依曼结构&#xff1a;数据和代码放在一起,便于读取和修改,安全性低 哈佛结构是&#xff1a;数据和代码分开存放,安全性高,读取和修麻烦 内存 内存是用来存储全局变量、局…

Cloudflare进阶技巧:缓存利用最大化

1. 引言 cloudflare我想你应该知道是什么&#xff0c;一家真正意义上免费无限量的CDN&#xff0c;至今未曾有哥们喷它的。当然&#xff0c;在国内的速度确实比较一般&#xff0c;不过这也不能怪它。 CDN最大的特色&#xff0c;我想就是它的缓存功能&#xff0c;达到防攻击&am…

云原生之使用Docker部署PDF多功能工具Stirling-PDF

云原生之使用Docker部署PDF多功能工具Stirling-PDF 一、Stirling-PDF介绍1.1 Stirling-PDF简介1.2 Stirling-PDF功能 二、本次实践规划2.1 本地环境规划2.2 本次实践介绍 三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本 四、下载Stirli…

redis查看耗时久的命令

redis查看耗时久的命令主要有两招&#xff1a;latency和slow log 【latency】 在Redis中&#xff0c;latency命令用于监视和测量Redis实例的延迟。 先进入redis: redis-cli -h 127.0.0.1 -p 24000[查看延迟监视器阈值] CONFIG GET latency-monitor-threshold这个值返回0&…

【计算机视觉】3.传统计算机视觉方法

传统计算机视觉方法 一、大纲图像分割人脸检测行人检测 二、图像分割基于阈值检测的方法基于边缘检测的方法基于区域的分割方法基于图论的分割方法 三、人脸检测四、行人检测五、SVM六、DPM 一、大纲 图像分割 基于阈值、基于边缘 基于区域、基于图论 人脸检测 Haar-like 特征…

Java实现使用多线程,实现复制文件到另一个目录,起不一样的名字,创建100万个数据

目录 1 需求2 实现 1 需求 我现在有一个300MB 的文件&#xff0c;想要根据这个文件&#xff0c;创建100万个大小一样的&#xff0c;名称不一样&#xff0c;如何实现&#xff0c;如何比较快点实现 2 实现 1 先准备好这个文件 2 准备好目录 3 写代码 private static void crea…

python:bottle + eel 模仿 mdict 查英汉词典

Eel 是一个轻量的 Python 库&#xff0c;用于制作简单的类似于离线 HTML/JS GUI 应用程序&#xff0c;并具有对 Python 功能和库的完全访问权限。 Eel 托管一个本地 Web 服务器&#xff0c;允许您使用 Python 注释函数&#xff08;annotate functions&#xff09;&#xff0c;…

(附源码)springboot体检预约APP 计算机毕设16370

目 录 摘要 1 绪论 1.1开发背景 1.2研究现状 1.3springboot框架介绍 1.4论文结构与章节安排 2 Springboot体检预约APP系统分析 2.1 可行性分析 2.1.1 技术可行性分析 2.1.2 经济可行性分析 2.1.3 操作可行性分析 2.2 系统流程分析 2.2.1 数据添加流程 2.2.2 数据…