当前位置: 首页 > news >正文

怎么查询网站是哪家公司做的营销宣传方案

怎么查询网站是哪家公司做的,营销宣传方案,动态网站开发大赛,google免费vps在 Rust 编程语言中,宏是一种强大的工具,可以用于在编译时生成代码。json! 是一个在 Rust 中广泛使用的宏,它允许我们在 Rust 代码中方便地创建 JSON 数据。 声明宏(declarative macros)是 Rust 中的一种宏&#xff0…

在 Rust 编程语言中,宏是一种强大的工具,可以用于在编译时生成代码。json! 是一个在 Rust 中广泛使用的宏,它允许我们在 Rust 代码中方便地创建 JSON 数据。

声明宏(declarative macros)是 Rust 中的一种宏,它们使用 macro_rules! 关键字定义。

本文将参考《Rust 程序设计(第二版)》,通过实现 json! 宏,深入理解声明宏的工作原理。

结论先行

本文我们将构建一个 json! 宏,它支持我们以字符串 JSON 风格的语法来编写 Json 值。如下面这个例子:

let students = json![{"name": "Hedon Wang","class_of": 2022,"major": "Software engineering"},{"name": "Jun Lei","class_of": 1991,"major": "Computor science"}
]

完整代码

实现 json!

定义 Json enum

首先我们需要思考一下 Json 结构是什么样子的?主要是以下 3 种模式:

{"name": "hedon","age": 18,"school": {"name": "Wuhan University","address": "Hubwi Wuhan"}
}
[{"name": "hedon"},{"name": "john"}
]
null

为此我们定义一个 Json 结构的枚举:

#[derive(Clone, PartialEq, Debug)]
pub enum Json {Null,Boolean(bool),Number(f64),String(String),Array(Vec<Json>),Object(HashMap<String, Json>),
}

你应该可以感到非常奇妙,使用一个这么简单的枚举,居然就可以表示所有的 Json 结构了。遗憾的是,现在这个结构编写 Json 值的语法相当冗长。

let people = Json::Object(HashMap::from([("name".to_string(), Json::String("hedon".to_string())),("age".to_string(), Json::Number(10.0)),("is_student".to_string(), Json::Boolean(true)),("detail".to_string(),Json::Object(HashMap::from([("address".to_string(), Json::String("beijing".to_string())),("phone".to_string(), Json::String("1234567890".to_string()))])))
]))

我们期望可以以下面这种方式来声明 Json 变量,这看起来就清爽许多了。

let students = json!([{"name": "Jim Blandy","class_of": 1926,"major": "Tibetan throat singing"},{"name": "Jason Orendorff","class_of": 1702,"major": "Knots"}
]);

猜想 json!

我们可以预见 Json 宏内部将会有多条规则,因为 JSON 数据有多种类型:对象、数组、数值等。事实上,我们可以合理地猜测每种 JSON 类型都将有一条规则:

macro_rules! json {(null)    => { Json::Null };([ ... ]) => { Json::Array(...) };({ ... }) => { Json::Object(...) };(???)     => { Json::Boolean(...) };(???)     => { Json::Number(...) };(???)     => { Json::String(...) };
}

然而这不太正确,因为宏模式无法区分最后 3 种情况,稍后我们会讨论如何处理。至于前 3 种情况,显然它们是以不同的语法标记开始的,所以这几种情况比较好处理。

实现 Null

我们先从最简单的 Null 分支开始,先编写如下测试用例:

#[cfg(test)]
mod tests {use super::*;#[test]fn test_null_json() {let json = json!(null);assert_eq!(json, Json::Null);}
}

想要通过上述测试用例非常简单,我们只需要在 macro_rules! 支持中匹配这种情况即可:

#[macro_export]
macro_rules! json {(null) => {Json::Null};
}
  • #[macro_export] 注解是 Rust 中的一个属性,用于指示这个宏应该被导出到调用者的作用域中,这样其他模块也可以使用它。
  • macro_rules! 宏定义了一个自定义的宏。在这里,它创建了一个名为 json 的宏,用于生成 JSON 数据。
  • 宏定义中 (null) 是匹配模式。这意味着当你调用 json! 宏并传递 null 作为参数时,将会触发这个规则。
  • => 符号用于指示匹配模式后的代码块。在这里,它指定了当匹配 (null) 时应该生成的代码块。
  • Json::Null 是一个 JSON 类型的枚举值,表示 JSON 中的 null 值。这个宏的目的是将传入的 null 转换为 Json::Null

实现 Boolean/Number/String

我们先准备如下测试用例:

#[test]
fn test_boolean_number_string_json() {let json = json!(true);assert_eq!(json, Json::Boolean(true));let json = json!(1.0);assert_eq!(json, Json::Number(1.0));let json = json!("hello");assert_eq!(json, Json::String("hello".to_string()));
}

通过观察分析,它们其实都是同一种模式:

Boolean/Number/String 分析

现在需要解决的问题就是,如何将这 3 种模式进行统一,这样在 macro_rules! 中才可以统一匹配模式并进行代码生成。

这里我们其实需要做的就是将 boolf64&str 转为对应的 Json 类型。那就需要用到标准库中的 From trait 了。

做法很简单,我们实现如下代码:

impl From<bool> for Json {fn from(value: bool) -> Self {Json::Boolean(value)}
}impl From<&str> for Json {fn from(value: &str) -> Self {Json::String(value.to_string())}
}impl From<f64> for Json {fn from(value: f64) -> Self {Json::Number(value)}
}

然后完善我们的 json!,目前的实现如下:

#[macro_export]
macro_rules! json {(null) => {Json::Null};($value: tt) => {Json::from($value)};
}

这里我们使用 $value作 为变量来承接匹配到的元素,其类型为 tt ,表示任意的语法标记树。具体可以参考:片段类型。

这时运行上述测试用例,是没有问题的:

  PASS [   0.004s] json-macro tests::test_boolean_number_string_jsonPASS [   0.004s] json-macro tests::test_null_json

美中不足的是,JSON 结构中的数字类型,其实不一定是 f64,也可以是 i32、u32、f32 或其他的数字类型,如果我们要为这全部的数字类型都实现到 Json 的 From trait,那就多冗余。

这个时候我们又可以实现一个宏,用于快速生成 impl From<T> for Json 。这个实现比较简单,本文就不赘述了,代码如下:

#[macro_export]
macro_rules! impl_from_for_primitives {(  $( $type: ty ) * ) => {$(impl From<$type> for Json {fn from(value: $type) -> Self {Json::Number(value as f64)}})*}
}

然后我们只需要用下面这一行代码,就可以为所有的数字类型实现 From trait 了:

impl_from_for_primitives!(u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 isize usize);

记得这个时候你要删除上面手动实现的 impl From<f64> for Json,不然会有 impl 冲突错误。

再次运行测试,也是可以通过的。

实现 Array

准备如下测试用例:

#[test]
fn test_array_json() {let json = json!([1, null, "string", true]);assert_eq!(json,Json::Array(vec![Json::Number(1.0),Json::Null,Json::String("string".to_string()),Json::Boolean(true)]))
}

要匹配 [1, null, "string", true]这个模式,笔者的分析过程如下:

  1. 首先是外面的两个中括号 []
  2. 再往里,是一个重复匹配的模式,以 , 分割,可以匹配 0 到任意多个元素,所以是 $( ,*) ,具体可以参考:重复模式;
  3. 最里面就是第 2 步要匹配的元素了,我们先用 $element 作为变量来承接每一个元素,其类型为 tt ,表示任意的语法标记树。

分析完匹配的表达式后,我们就可以得到:

([ $( $element:tt ), * ]) => { /* TODO */ }

我们要生成的代码长这个样子:

Json::Array(vec![Json::Number(1.0),Json::Null,Json::String("string".to_string()),Json::Boolean(true)
])

其实就是一个 vec!,然后里面每个元素都是一个 Json,如此递归下去。

即可以得到代码生成部分的逻辑为:

Json::Array(vec![$(json!($element)),* ])

Json::Array 宏分析

综上,我们实现的代码如下:

#[macro_export]
macro_rules! json {(null) => {Json::Null};([ $( $element: tt),* ]) => {Json::Array(vec![ $( json!($element)), * ])};($value: tt) => {Json::from($value)};
}

运行测试用例:

PASS [   0.003s] json-macro tests::test_null_json
PASS [   0.003s] json-macro tests::test_boolean_number_string_json
PASS [   0.004s] json-macro tests::test_array_json

实现 Object

写好如下测试用例,这次我们顺带把 Null、Boolean、Number 和 String 带上了:

#[test]
fn test_object_json() {let json = json!({"null": null,"name": "hedon","age": 10,"is_student": true,"detail": {"address": "beijing","phone": "1234567890"}});assert_eq!(json,Json::Object(HashMap::from([("name".to_string(), Json::String("hedon".to_string())),("age".to_string(), Json::Number(10.0)),("is_student".to_string(), Json::Boolean(true)),("detail".to_string(),Json::Object(HashMap::from([("address".to_string(), Json::String("beijing".to_string())),("phone".to_string(), Json::String("1234567890".to_string()))])))])))
}

对比预期的 json! 宏内容和展开后的代码:

Json::Object 宏分析

完善我们的 macro_rules! json

#[macro_export]
macro_rules! json {(null) => {Json::Null};([ $( $element: tt),* ]) => {Json::Array(vec![ $( json!($element)), * ])};({ $( $key:tt : $value:tt ),* }) => {Json::Object(HashMap::from([$(( $key.to_string(), json!($value) )), *]))};($value: tt) => {Json::from($value)};
}

运行测试用例:

PASS [   0.004s] json-macro tests::test_object_json
PASS [   0.005s] json-macro tests::test_array_json
PASS [   0.004s] json-macro tests::test_null_json
PASS [   0.005s] json-macro tests::test_boolean_number_string_json

至此,我们就完成了 json! 宏的构建了!完整源码可见:完整代码

Peace! Enjoy coding~

附录

重复模式

在 实现 Array 中,我们匹配了这样一个模式:

([ $( $element:tt ), * ]) => { /* TODO */ }

其中 $($element:tt), *) 就是一个重复模式,其可以进一步抽象为 $( ... ),* ,表示匹配 0 次或多次,以 , 分隔。

Rust 支持以下全部重复模式:

模式含义
$( … ) *匹配 0 次或多次,没有分隔符
$( … ), *匹配 0 次或多次,以逗号分隔
$( … ); *匹配 0 次或多次,以分号分隔
$( … ) +匹配 1 次或多次,没有分隔符
$( … ), +匹配 1 次或多次,以逗号分隔
$( … ); +匹配 1 次或多次,以分号分隔
$( … ) ?匹配 0 次或 1 次,没有分隔符

即:

  • * 表示 0 次或多次
  • + 表示 1 次或多次
  • ? 表示 0 次或 1 次
  • 可在上述 3 者之前加入分隔符

片段类型

在 实现 Array 中,我们匹配了这样一个模式:

([ $( $element:tt ), * ]) => { /* TODO */ }

这里我们将 $element 指定为 tt,这个 tt 就是宏中的一种片段类型。

tt 能匹配单个语法标记树,包含:

  • 一对括号,如 (..)[..]、或 {..} ,以及位于其中的所有内容,包括嵌套的语法标记树。
  • 单独的非括号语法标记,比如 1926Knots

所以为了匹配任意类型的 Json ,我们选择了 tt 作为 $element 的片段类型。

macro_rules! 支持的片段类型如下所示:

片段类型匹配(带例子)后面可以跟 ······
expr表达式:2 + 2, “udon”, x.len()=>,;
stmt表达式或声明,不包括任何尾随分号(很难用,请尝试使用 expr 或 block)=>,;
ty类型:String, Vec, (&str, bool), dyn Read + Send=>,; =
path路径:ferns, ::std::sync::mpsc=>,; =
pat模式:_, Some(ref x)=>,=
item语法项:struct Point { x: f64, y: f64 }, mod ferns;任意
block块:{ s += “ok\n”; true }任意
meta属性的主体:inline, derive(Copy, Clone), doc=“3D models.”任意
literal字面量值:1024, “Hello, world!”, 1_000_000f64任意
lifetime生命周期:'a, 'item, 'static任意
vis可见性说明符:pub, pub(crate), pub(in module::submodule)任意
ident标识符:std, Json, longish_variable_name任意
tt语法标记树:;, >=, {}, [0 1 (+ 0 1)]任意

完整代码

use std::collections::HashMap;#[derive(Debug, Clone, PartialEq)]
#[allow(unused)]
enum Json {Null,Boolean(bool),String(String),Number(f64),Array(Vec<Json>),Object(HashMap<String, Json>),
}impl From<bool> for Json {fn from(value: bool) -> Self {Json::Boolean(value)}
}impl From<&str> for Json {fn from(value: &str) -> Self {Json::String(value.to_string())}
}impl From<String> for Json {fn from(value: String) -> Self {Json::String(value)}
}#[macro_export]
macro_rules! impl_from_for_primitives {(  $( $type: ty ) * ) => {$(impl From<$type> for Json {fn from(value: $type) -> Self {Json::Number(value as f64)}})*}
}impl_from_for_primitives!(u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 isize usize);#[macro_export]
macro_rules! json {(null) => {Json::Null};([ $( $element: tt),* ]) => {Json::Array(vec![ $( json!($element)), * ])};({ $( $key:tt : $value:tt ),* }) => {Json::Object(HashMap::from([$(( $key.to_string(), json!($value) )), *]))};($value: tt) => {Json::from($value)};
}#[cfg(test)]
mod tests {use super::*;#[test]fn test_null_json() {let json = json!(null);assert_eq!(json, Json::Null);}#[test]fn test_boolean_number_string_json() {let json = json!(true);assert_eq!(json, Json::Boolean(true));let json = json!(1.0);assert_eq!(json, Json::Number(1.0));let json = json!("hello");assert_eq!(json, Json::String("hello".to_string()));}#[test]fn test_object_json() {let json = json!({"null": null,"name": "hedon","age": 10,"is_student": true,"detail": {"address": "beijing","phone": "1234567890"}});assert_eq!(json,Json::Object(HashMap::from([("null".to_string(), Json::Null),("name".to_string(), Json::String("hedon".to_string())),("age".to_string(), Json::Number(10.0)),("is_student".to_string(), Json::Boolean(true)),("detail".to_string(),Json::Object(HashMap::from([("address".to_string(), Json::String("beijing".to_string())),("phone".to_string(), Json::String("1234567890".to_string()))])))])))}#[test]fn test_array_json() {let json = json!([1, null, "string", true]);assert_eq!(json,Json::Array(vec![Json::Number(1.0),Json::Null,Json::String("string".to_string()),Json::Boolean(true)]))}
}
http://www.hrbkazy.com/news/17401.html

相关文章:

  • 做家教网站怎么样自助建站系统开发
  • 网站建设包过哪些方面建网站需要什么条件
  • 广州注册公司哪家靠谱湖州seo排名
  • 行牛建站市场调研与分析
  • 公司部门职位结构图seo研究中心骗局
  • 网站底部关键词指向seo实训报告
  • 徐州木塑模板东莞网络优化排名
  • 汕头正规网站建设模板总部关键词歌曲免费听
  • 公司设计网站需要多少钱google谷歌搜索主页
  • 制作购物网站seo优化搜索推广
  • 用表格做网站教程网站排名优化软件哪家好
  • 在线设计logo图标关键词优化报价怎么样
  • 香港主机做视频网站网络营销策略包括
  • 企业邮箱怎么申请免费的seo自己怎么做
  • 个人网站源码php网站推广的基本方法有哪些
  • 企业如何进行网站备案网络营销的目标
  • 百度右侧相关网站seo网站优化软件
  • 网站信息内容建设局通报宁波seo博客
  • 做电子商务网站需要办理什么证seddog站长之家
  • 用微信怎么做商城网站吗营销做得好的品牌
  • 如何让网站快速收录有别人的交易链接怎么交易
  • 从哪个网站设置宽带主机游戏如何在网上推广
  • 网站搭建哪里找更靠谱营销渠道
  • 重庆北京网站建设重庆网络推广公司
  • 快速搭建小程序seo怎么做排名
  • 怎么做劫持网站广州seo公司哪个比较好
  • 狠狠做最新网站国内十大搜索引擎排名
  • 北京 网站建设公司靠谱seo外包定制
  • 什么网站做顶置便宜杭州百度seo
  • 北京建站公司兴田德润很好疫情优化调整