二度云自助建站系统,怎么注册公司公众号微信号,网站tdk建设,三五互联网站建设怎么样本文就一个做了三四天的小程序讲第一次学用RUST的感受#xff0c;内附代码。
了角语言
从一些渠道听说了R#xff0c;这个字母挺魔性#xff0c;那个文章说C和R的团体已经上升到了宗教崇拜的高度#xff0c;然后#xff0c;我觉得必 有过人之处#xff0c;大约10年没碰…本文就一个做了三四天的小程序讲第一次学用RUST的感受内附代码。
了角语言
从一些渠道听说了R这个字母挺魔性那个文章说C和R的团体已经上升到了宗教崇拜的高度然后我觉得必 有过人之处大约10年没碰C只知皮毛。于是想要去学一下R这样简写是为了方便凑合看。粗粗一打听这语言是系统的平台通吃androidarmx86.苹果安装起来也十分方便curl一段代码就行。除了win下要用VStuty。正好我上次pythonexe化的进候安装上了。所以大约10分就安好了拿出helloworldcargo buildcargo run也能通过了。后来发现R在文档和库管理这一块是不是要比C这几十年的老 将好很多呢虽然很久没用C不知道发展了没有感叹时代真是进步太大了。R的学习资料网上有太多电子版网页搜索查询方便库文档规范也自动 这种方便性真是让人爽快不说别的了还是挺推荐一学的。
任务
以前有一个模拟访问网页的python全套代码就在里面就剩下要了解R的语法和库就能完成任务了。于是了解reqwest是模仿request来的就用它了。结果它总是aynsc方法看着头大怕是掌握不住于是就找到了reqwestblocking这就顺利多了。还是习惯老方法。不过完成了任务就可以尝试新的了。剩下的是cookies。好在目前的版本一步启用
use reqwest::blocking::Client;
let client Client::builder().cookie_store(true).build()?;这就具备第一个轮子了。在登陆密码的以后来了一个成功地址做下一步的引导结果因为这个地址没有mut而初始化成了空。造成下一步成功后也无法更新。这就让后面的所有请求是失败的。我一开始一直在怀疑cookie不能跨域fun。因为在一个fun里是好的。为此还找了cookiestore的本地文件json在实现。结果还是一样。直到后来找到了真实原因是一个变量可变的声明
建立图形界面调查对比后使用slint。提交reqwest分form.和json数据cookie保存登陆状态取回response并且regex分析结果解析json结果。更新界面状态使用两个线程一个交互web server结果保存在全局变量一个刷新全局变量到界面状态。编码用户密码以方便登陆用户明文到AES和MD5加密然后post去后台。
按部就班
老实的看了几个小时的教程参数变量引用数组字符串。发现这个言语会劲量发现错的直到按他要求来才能通过当然所有语言都这样。但是还是挺喜欢他的味道。和jspython形成鲜明的对比。 fn要用什么参数传回什么类型都要提前说好。而且ResultOption这样的东西 这样的字符。都有自己的用处。接下了学了要用到的regex。就像reqwest、它要实现的功能都是老的只有工具是新的。而且说心里它跨平台在鸿蒙也是能跑的而且资源这么多多好。regex r#“”#这是原始字符。以前那些提取基本是照样出来的。
图形界面
捎带又了角一个新的slint框架他是跨语言的有自己的slint文件进行窗口程序的布局。安装也像R一样又无声又快只是我没在vscode上找到可拖放的插件。 在线的倒是有一个。用了半天时间放了两个输入一个状态一个计数按钮。 这是从它的githubexample下载来的。cargo buildcargo run。 一下就打开了。想像有一天在鸿蒙也hell world一下。但是真想不到有什么像样的任务要做。 它的in- out变量可以在main中set get。在完成了后台以后这里有一个小难点。就是状态的适时刷新。 Cargo.toml
[package]
name slint-rust-template
version 0.1.0
edition 2021# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html[dependencies]
slint 1.7.2
reqwest { version 0.12.7, features [json, cookies,blocking,gzip] }
tokio {version 1 ,features [full] }
regex 1.10.6
#recode_rs1.0.6
encoding_rs0.8.34
serde { version 1.0, features [derive] }
serde_json 1.0main.rs
// Prevent console window in addition to Slint window in Windows release builds when, e.g., starting the app via file manager. Ignored on other platforms.
#![cfg_attr(not(debug_assertions), windows_subsystem windows)]
mod wjc;
use slint::Weak;
use wjc::kkuser;
use std::error::Error;
use std::sync::MutexGuard;
//use reqwest::Client;
use reqwest::blocking::Client;
use std::{thread, time::Duration};
use reqwest;
use regex::Regex;
use std::collections::HashMap;
slint::include_modules!();fn main() - Result(), Boxdyn Error {let ui AppWindow::new()?;let handle_weak ui.as_weak();let thread std::thread::spawn(move || {//更新状态loop{handle_weak.upgrade_in_event_loop(move |handle|{ unsafe { handle.set_counter(kkuser::progbar);handle.set_status(kkuser::thestat.unwrap().into());}});thread::sleep(Duration::from_millis(500));}});ui.on_request_increase_value({let ui_handle ui.as_weak();move || {let ui ui_handle.unwrap();ui.set_counter(ui.get_counter() 0.01);kkuser::test( );}});ui.run()?;Ok(())
}
感受一下另一个主文件 appwindow.slint export component AppWindow inherits Window {in-out property float counter: 0.42;in-out property string user: ;in-out property string status: ;in-out property string pass: ;callback request-increase-value();preferred-width: 600px;VerticalBox {Text {text: 用户;}LineEdit{text root.user;placeholder-text:;}Text {text: 密码;}LineEdit{text root.pass;placeholder-text: ;}ProgressIndicator {preferred-width: 100%;height: 25px;progress counter;}Text {text: 状态: \{root.status}用户: \{root.user}密码: \{root.pass};}Button {text: 登陆;clicked {root.request-increase-value();}}}
}完成上线
前面的reqwest中的cookie解决以后用了一天折腾regex把以前定义的两三个提取请求再实现了一把。 又细细看了几个regex演示。学不来学不会 这玩意真是和R语言一样太复杂了。我只是按照旧方式实现了。然后任务做成了长时的。界面就在转圈。于是在改成后才thread前。我试着让任务和界面通信。把ui传递给网页处理程序。结果总是不行。然后找了共享全局变量的办法static mut 。这一串下来把全局变量从main移动到了reqwest主程序的模块。让它处一个独立thread、去完成上线。上main里的ui独立运行一个loop。长久的2秒取一个全局变量set给一个界面元素。到于slint 里的todolist。model这一类的代码看得一头雾水。有点早。 在main.rs下建立wjc文件夹作为mod在练习。建立两个文件一个 mod.rs
pub mod kkuser;
pub mod jscrypto;kkuser.rs
use reqwest::blocking::Client;
use reqwest;
use regex::Regex;
use std::{collections::HashMap, fmt::format};
use std::error::Error;
use reqwest::{cookie::Jar, Url};
use serde::{Deserialize, Serialize};
use std::{thread, time::Duration};
use serde_json::json;
// 共享状态
pub static mut thestat: Option str Some();
pub static mut progbar:f320.001;
pub struct KKUser {active: bool,username: String,passwd: String,client: Client,}
pub fn build_kkuser(username: String, passwd: String) - ResultKKUser,Boxdyn Error{let client Client::builder().cookie_store(true).build()?;let ret KKUser {active: false,username,passwd,client,};Ok(ret)}
impl KKUser {fn getloginurl(self)-ResultString,Boxdyn Error{let re Regex::new(r#form_login_true action(.?)#).unwrap();let ret self.client.get(BURL).send()?.text_with_charset(GBK)?;let capre.captures(*ret).unwrap() ; println!({:?},cap[1]);let idString::from(cap[1]);Ok(id)}pub fn login(self )-Resultbool,Boxdyn Error {let idself.getloginurl().unwrap(); // let checkself.getloginurl(client).unwrap();let var_name format!({BURL}{id});let mut map HashMap::new();map.insert(u_dlcode, self.username.as_str());map.insert(p_dlcode, self.passwd.as_str());let ret:String self.client.post(var_name).form(map).send()?.text_with_charset(GBK)?;println!({ret}\n);assert_eq!(true,ret.contains(home));Ok(ret.to_string().contains(home))}}
pub fn test() - Result(), Boxdyn Error {let handle std::thread::spawn(||{let u build_kkuser(V/JNlfP3SBG8tUJW5tIAoUogWKJ6StCzwbt4zzm4.to_string(), E1Kf42cdpAwXknHXIy6eqIDhtQj85wCqwer6nUTzw.to_string()).unwrap(); let ru.login().unwrap() ;let eeformat!({r});u.v_jiaru().unwrap();//更新全局变量用时间较长。u.v_ksxx( ).unwrap() ;Ok(())}设置密码
这个网站的密码和用户名是AES-MD5,加密的串。算法是js实现 的、为模拟用的是现在加密过的为了真实使用还需要有自己的加密算法。由于是浏览器 的算法我就算是web从服务器来一个询问都是做不到的。为此大学AES一天24小时。也考虑从rust访问js脚本和语句。用了两个库都是失败的。虽然有声称可用的。我想他会加大程序 的体积和依赖外部环境。失去灵动能力。无耐rust本身一大堆的半成品。从中总算发现一个现成的实现。其实是发现了两个一个不含ZeroPading。是js正用的。另一个倒是含有。我算过了大概的一致参数却不能得到一致结果。后来就想改写js到rust。https://www.codeconvert.ai/free-converter 它会转换js到R代码在折腾了快一半的时候深感难。后来看AES的文章说算法和参数一样就会有一样的结果。我就又回头比对参数。从cha数组 u8数组分析第个参数是传过去的什么值。 型号浏览器devtool。看起js的内容那太方便。才知道刚好差不多。而rust最终给的 [u8] 不是最后js得到的js最后很像BASE64最后证明真是完成后的长充40-43用parase解码成bytest、长度刚好32bits。这和rust取得的结果也挺像的。于是base64处理过。js和R终于成功会合。另外就md5是套在密码外然后给AES处理的。于是这就好办了。R有很标准的MD5. 有一个点是处理出的结果还是 [u8].可以直接做AES的输入。但是要是拿来用就又不对了。 感谢js的直观。它的md5得到的u8的十六进制小写字符串。然后给了AES。这就好了R结果又安装了个小库 只为了转成十六进制。看来语言全靠外挂怪不得可以跑嵌入式400K内存的板子。 我猜也许AI可以做到很多我还是纯靠搜索了。 在Cargo.toml加入
[dependencies]aes0.8.4block-padding 0.3.3cbc0.1.2 base640.22.1hex-literal0.4.1 md-5 0.10.6data-encoding 2.6.0在wjc目录建立新文件jscrypto.rs 在同目录下的kkuser.rs添加use super::jscrypto ;以使用其功能
//前端js使用crypto-js对数据进行AES加密
//function js_encrypt(text){
//var key CryptoJS.enc.Latin1.parse(1E785CMD585LLS4S);//为了避免补位直接用16位的秘钥
// var iv CryptoJS.enc.Latin1.parse(1234431890129056);//16位初始向量
// var encrypted CryptoJS.AES.encrypt(text, key, {
// iv: iv,// mode:CryptoJS.mode.CBC,
// padding:CryptoJS.pad.ZeroPadding
//use std::char;
use block_padding::*;
use data_encoding::{HEXLOWER, DecodeError};
use std::error::Error;
use base64::prelude::*;use md5::{Md5, Digest};
use aes::cipher::{ BlockEncryptMut, KeyIvInit};
type Aes128CbcEnc cbc::Encryptoraes::Aes128;pub fn cry_AES(input: str) - ResultString, Boxdyn Error {let mut key *b1E785CMD585LLS4S; let mut iv*b1234431890129056;let mut buf [0u8; 48];let pt_len input.len();buf[..pt_len].copy_from_slice(input.as_bytes());let ct Aes128CbcEnc::new(key.into(), iv.into()).encrypt_padded_mut::ZeroPadding(mut buf, pt_len).unwrap();let bstr BASE64_STANDARD.encode(ct);Ok(bstr)}
pub fn test() {let mut key *b1E785CMD585LLS4S; let mut iv*b1234431890129056;let ct cry_AES(username);println!({:?},ct.unwrap());let mut hasher Md5::new();hasher.update(bpasswd);let mdu8 hasher.finalize();let encoded HEXLOWER.encode(mdu8);println!({:?}, cry_AES(encoded.as_str()).unwrap() );}fn main (){test();
}整理完毕
至此完成生成的程序10M上下一个前台窗口一个后台任务。点一下动一下。我是在苹果Mac上开发的它 的虚拟机是一个win11 X64拷贝工程前删除了target目录才让移动的不然动不了。也不知道累积到了几百M、 拷贝过去cargo build cargo build --release 都是干一会就好本来也没啥内容。 把结果运行一下。换个目录再运行一下。感觉还是蛮爽的。
去年做过一个python jupyter下的相似程序。它在server上运行是python在wedget编程后而传给celery任务。我觉得也挺好的有容了再提交一篇。