rust里mp5a4_Rust base64 编码解码 首个rust小作品【自用别吐我】
202003 rust 1.42.0编译通过。升级为单线程加管道,想必效率会高一些。
20191114,rust 1.39 编译通过,增加了注释,有些所有权的东西算是理解了
rust 1.27.2编译通过。算法很烂,其中一些 变量的生存周期和所有权转移之类都还不完全明确。先记录下来。
吐槽一下,为啥代码样式没有rust的
/*
base64code
202003 升级了编码和解码两个方法,单线程加管道,在老代码的后面。想必效率会提高一些。
*/
use std::collections::HashMap;
use std::string::String;
//-------------
use std::sync::mpsc;
use std::thread;
//use std::sync::Mutex;
use std::sync::{Arc, Mutex};
use std::time::Duration;
// 模块形式就要注释这句,如果是bin执行模式 编译就放开这句
// fn main() {
// println!("Hello, world!");
// // base64测试
// base64_test();
// }
// base64测试方法
pub fn base64_test() {
let source_txt = String::from("愤怒是魔鬼");
println!("原文:{:?}", source_txt);
let b64 = base64encode(&source_txt);
println!("原文转换base64 utf-8编码: {:?}", b64);
let sb64 = base64decode(&b64);
println!("base64编码再转换原文 utf-8编码: {:?}", sb64);
}
/// rust 1.27.2编译通过,但是有警告好像
/// base64 编码 算法很烂,还有巨大优化空间
/// 输入一个 字符串 地址 ,这里是&借用,不获取所有权。 返回一个字符串,将所有权返出函数体外
pub fn base64encode(code: &String) -> String {
let mut result = String::from(""); // 用于存储 结果变量,所以是 mut可变的
let bytes = code.as_bytes(); // utf-8转换的byte数组,数据基准
let len = bytes.len(); // 数组长度
let mut byte_array: [u8; 3] = [0; 3]; // u8;3单个数组,转换过程中用于存储
let mut byte_vec: Vec = Vec::new(); // 存放u8;3的队列
// 这一段整体含义是 将byte数组每3个一组拆分,然后放入 Vec
for (i, &item) in bytes.iter().enumerate() {
// 循环byte数组
let y = i % 3; // 获得余数 数组角标
byte_array[y] = item; // byte拷贝值存入 u8;3 数组//不用clone()也没问题
if y == 2 || i == (len - 1) {
// 存到一组结尾,和总结尾时
// println!(" push {:?}", &byte_array);
// 这里是将 byte_array 拷贝进入 byte_vec。 不是引用进去从而不必考虑所有权问题。
byte_vec.push(byte_array); // 整体拷贝u8;3数组到 转换队列中,这里没用clone(),居然也行!
byte_array = [0; 3]; // 重置u8;3数组
}
}
//println!(" byte_vec == {:?}", byte_vec); // 打印一下,可以不打印
let b_len = byte_vec.len(); // u8;3数组队列长度。决定了转换循环次数
// 下面这一段就是 转换 主体 过程 ,具体的字节位移在 后面的函数里面
for (i, &item) in byte_vec.iter().enumerate() {
// 循环u8;3 队列 vector
let a4 = trans_a4(&item); // 转换 u8;4 数组,将 u8;3 转换成 u8;4
// 转换成 u8;4 后 先处理前两位,将对应的字符串提取出来
result.push(b64_to_char(a4[0])); // 这里后面都是根据对照表提取字符然后存入转换结果
result.push(b64_to_char(a4[1])); // b64_to_char 内部将字符拷贝值 传出函数返回给 result。 result有字符所有权
if b_len == i + 1 {
// 结尾处理 最后一位 (最后组,可能有最多两个位置是0)
if a4[2] == 0u8 {
// 值为0 用等号填充,非零就正常填充
result.push('='); // 结尾处要独立处理 = 号的问题
} else {
result.push(b64_to_char(a4[2]));
}
if a4[3] == 0u8 {
// 也是 值为0 用等号填充,非零就正常填充
result.push('=');
} else {
result.push(b64_to_char(a4[3]));
}
} else {
// 非结尾处理
result.push(b64_to_char(a4[2]));
result.push(b64_to_char(a4[3]));
}
}
result
}
/// base64 解码 算法很烂,还有巨大优化空间
/// 解码,将base64 转换 为原有的utf-8字符串
pub fn base64decode(code: &String) -> String {
let mut u8_vec: Vec = Vec::new(); // 结果队列,byte队列.用于存储字符串的utf8字节组,到字符串还要转换一下
let mut num_array: [u8; 4] = [0; 4]; // 单个 u8;4数组
let mut num_vec: Vec = Vec::new(); // u8;4数组队列
let chars = code.chars(); // base64编码字符队列
let len = code.len(); // base64编码长度
// 这一段 含义 将 base64字符串 字符转换为 u8;4 数组,字符转换角标
for (i, item) in chars.enumerate() {
// 循环此编码字符队列
let y = i % 4; // 用余数分组,每4个为一组
if item == '=' {
// 单独处理=号结尾
num_array[y] = 0u8;
} else {
let n = b64_to_num(item); // 将字符对应的编号找到!注意这里传入=在对照表是找不到的,所以在前面处理了=符号
num_array[y] = n; // 拷贝值存入数组,是不是要拷贝值?不确定。变量归属和声明周期还不熟(不clone也行呢)
}
if y == 3 || i == (len - 1) {
// 分组结尾 和 整个队列结尾单独处理
// 这里是克隆进去的,所有权一并带入了
num_vec.push(num_array); // 将u8;4数组拷贝到 队列中// 不拷贝(clone)也行
}
}
//println!(" num_vec == {:?}", num_vec); // 打印中间结果,可以不打印
let n_len = num_vec.len(); // 计算u8;4数组队列长度
// 下面这一段 将 u8;4 缩成 u8;3
for (i, &item) in num_vec.iter().enumerate() {
// 开始循环u8;4数组队列
let a3 = trans_a3(&item); //反向转换 将u8;4数组转换成u8;3数组
u8_vec.push(a3[0]); //将u8;3数组存储到中间byte队列中
if i == n_len - 1 {
// 单独处理结尾的情况
if a3[1] != 0u8 {
// 不等于0 继续push
u8_vec.push(a3[1]);
}
if a3[2] != 0u8 {
u8_vec.push(a3[2]);
}
} else {
u8_vec.push(a3[1]);
u8_vec.push(a3[2]);
}
}
let result = String::from_utf8(u8_vec).unwrap(); // 这里将u8;3队列转换成utf-8字符串
result
}
/// 这是个样本方法,摘抄来参考的 base64没用到此方法
pub fn first_word(s: &String) -> usize {
let bytes = s.as_bytes();
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return i;
}
}
s.len()
}
/// u8;3 数组转换 u8;4数组
pub fn trans_a4(a3: &[u8; 3]) -> [u8; 4] {
// 就是3位8byte,转换成4位6byte组
let mut a4: [u8; 4] = [0; 4];
a4[0] = a3[0] >> 2; //0右移2位
a4[1] = (a3[0] << 6) >> 2 | a3[1] >> 4; //0左移6位再右移2位和1右移4位组合
a4[2] = (a3[1] << 4) >> 2 | a3[2] >> 6; //1左移4位再右移2位和2右移6位组合
a4[3] = (a3[2] << 2) >> 2; //2左移2位再右移2位//其实可以直接将左两位异或0b00
a4
}
/// u8;4 数组转换 u8;3数组
pub fn trans_a3(a4: &[u8; 4]) -> [u8; 3] {
// 就是4位6byte,转换成3位8byte组
let mut a3: [u8; 3] = [0; 3];
a3[0] = a4[0] << 2 | a4[1] >> 4; //0左移2位组合1右移4位
a3[1] = a4[1] << 4 | a4[2] >> 2; //1左移4位组合2右移2位
a3[2] = a4[2] << 6 | a4[3]; //2左移6位组合3全部
a3
}
/// 用key 获取char
pub fn b64_to_char(key: u8) -> char {
// 下面这段程序用B64_ARY当作查询基准 也可以运行
// let mut c:char = ' ';
// for pat in B64_ARY.iter() {
// if pat.0 == key {
// c = pat.1;
// break;
// }
// }
// c
// 下面是用 B64_STR 做基准查询 str.get 方法没用上,以后研究
let mut c: char = '-';
let mut i: u64 = 0;
for pat in B64_STR.chars() {
if i == key as u64 {
c = pat;
break;
}
i += 1;
}
c
}
/// 用char 获取 key编号
pub fn b64_to_num(key: char) -> u8 {
// 下面这段程序用B64_ARY当作查询基准 也可以运行
// let mut n:u8 = 0;
// for pat in B64_ARY.iter() {
// if pat.1 == key {
// n = pat.0;
// break;
// }
// }
// n
// 下面是用 B64_STR 做基准查询
if key == '=' {
//如果查询= 直接返回0
return 0 as u8;
}
let n = B64_STR.find(key).unwrap();
n as u8
}
// 元祖数组类型 b64对照表
const B64_ARY: [(u8, char); 64] = [
(0, 'A'),
(1, 'B'),
(2, 'C'),
(3, 'D'),
(4, 'E'),
(5, 'F'),
(6, 'G'),
(7, 'H'),
(8, 'I'),
(9, 'J'),
(10, 'K'),
(11, 'L'),
(12, 'M'),
(13, 'N'),
(14, 'O'),
(15, 'P'),
(16, 'Q'),
(17, 'R'),
(18, 'S'),
(19, 'T'),
(20, 'U'),
(21, 'V'),
(22, 'W'),
(23, 'X'),
(24, 'Y'),
(25, 'Z'),
(26, 'a'),
(27, 'b'),
(28, 'c'),
(29, 'd'),
(30, 'e'),
(31, 'f'),
(32, 'g'),
(33, 'h'),
(34, 'i'),
(35, 'j'),
(36, 'k'),
(37, 'l'),
(38, 'm'),
(39, 'n'),
(40, 'o'),
(41, 'p'),
(42, 'q'),
(43, 'r'),
(44, 's'),
(45, 't'),
(46, 'u'),
(47, 'v'),
(48, 'w'),
(49, 'x'),
(50, 'y'),
(51, 'z'),
(52, '0'),
(53, '1'),
(54, '2'),
(55, '3'),
(56, '4'),
(57, '5'),
(58, '6'),
(59, '7'),
(60, '8'),
(61, '9'),
(62, '+'),
(63, '/'),
];
// const B64_MAP:HashMap = [(0, 'A')].iter().cloned().collect();
// str类型 b64对照表
const B64_STR: &'static str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
//=====================================================================
/// base64测试方法
pub fn base64_thread_test() {
let big_str: String = String::from("愤怒是魔鬼");
println!("原文:{:?}", big_str);
let amt_str = Arc::new(String::from(big_str));
let enbase64_res = base64encode_thread(amt_str);
println!(" EN BASE64 RESULT : {:?}", enbase64_res);
//let str2: String = String::from(big_str.clone());
//let b64_res = myb64::base64encode(&str2);
//println!(" base64 result: {:?}", b64_res);
let code_str = Arc::new(String::from(enbase64_res));
let debase64_res = base64decode_thread(code_str);
println!(" DE BASE64 RESULT : {:?}", debase64_res);
}
/// base64编码 线程+通道版本
///
/// # Examples
///
/// ```
/// let big_str: String = String::from("愤怒是魔鬼...");
/// let amt_str = Arc::new(Mutex::new(String::from(big_str)));
/// let enbase64_res = base64encode_2(amt_str);
/// println!(" EN BASE64 RESULT : {:?}", enbase64_res);
/// ```
pub fn base64encode_thread(soustr: Arc) -> String {
let (tx, rx) = mpsc::channel(); // 创建 数据 通道,用于传递
//let sc = soustr.clone(); // 可以不用拷贝
thread::spawn(move || {
// 线程,将输入参数移动到线程内部
let mut idx: usize = 0; // 循环位移标记
let mut byte_array: [u8; 3] = [0; 3]; // u8;3数组 三位数组
let bb = soustr; //Arc::try_unwrap(soustr).unwrap(); // 锁定 并使用
let mut peek = bb.bytes().peekable(); // 获取一个可窥视的对象,必须是可修改的,用于观察结果
for val in bb.bytes() {
// 迭代
let idx_i = idx % 3; // 计算索引除以3 余数
//println!(" {:?} : {:?}", idx_i, val); // 打印日志
byte_array[idx_i] = val; // 装数据,每3个装一组,不足的用0代替装满
if idx_i == 2 || peek.peek() == None {
// 检查3间断和结尾,发送数据
tx.send(byte_array).unwrap(); // 向通道发送数据(应该是拷贝发送的)
byte_array = [0; 3]; // 重置 数据,准备下一次装
}
//thread::sleep(Duration::from_secs(1));
idx += 1; // 索引号加1
}
});
let mut result: String = String::from(""); // 声明可修改的结果
for received in rx {
// 迭代接收通道
//println!("thread_borrow Got: {:?}", received);
let a4 = trans_a4(&received); // 接收值转换 u8;4数组
//println!(" a4 = {:?}", a4);
result.push(b64_to_char(a4[0])); // 这里后面都是根据对照表提取字符然后存入转换结果
result.push(b64_to_char(a4[1])); // b64_to_char 内部将字符拷贝值 传出函数返回给 result。 result有字符所有权
// 结尾处理 最后一位 (最后组,可能有最多两个位置是0)
if a4[2] == 0u8 {
// 值为0 用等号填充,非零就正常填充
result.push('='); // 结尾处要独立处理 = 号的问题
} else {
result.push(b64_to_char(a4[2]));
}
if a4[3] == 0u8 {
// 也是 值为0 用等号填充,非零就正常填充
result.push('=');
} else {
result.push(b64_to_char(a4[3]));
}
// if a4[2] == 0 || a4[3] == 0 { // 如果出现后两位 或者最后一位 是0,就表明是最后一组了。或者可以用迭代peek来处理
// } else {
// // 非结尾处理
// result.push(b64_to_char(a4[2]));
// result.push(b64_to_char(a4[3]));
// }
}
result
}
/// base64解码 线程+通道版本
///
/// # Examples
///
/// ```
/// let big_str: String = String::from("愤怒是魔鬼...");
/// let code_str = Arc::new(Mutex::new(String::from(enbase64_res)));
/// let debase64_res = base64decode_thread(code_str);
/// println!(" DE BASE64 RESULT : {:?}", debase64_res);
/// ```
pub fn base64decode_thread(soustr: Arc) -> String {
let (tx, rx) = mpsc::channel(); // 创建通道
// let sc = soustr.clone();
thread::spawn(move || {
// 启动线程,闭包 捕获 数据
let mut idx: usize = 0; // 循环索引号
let mut num_array: [u8; 4] = [0; 4]; // u8;4数组
let lock_char_array = soustr; // Arc::try_unwrap(soustr).unwrap(); // 锁定
let mut peek = lock_char_array.chars().peekable(); // 可窥视,用于检查结尾
for c in lock_char_array.chars() {
// 迭代base64字符
let idx_i = idx % 4; // 每4分组
//println!(" {:?} : {:?}", idx_i, val);
if c == '=' {
// =就是 0u8
num_array[idx_i] = 0u8;
} else {
num_array[idx_i] = b64_to_num(c); // 不是=就转成标号送入数组
}
if idx_i == 3 || peek.peek() == None {
// 检查结尾
tx.send(num_array).unwrap(); // 发送到通道
num_array = [0; 4]; // 重置u8;4数组
}
//thread::sleep(Duration::from_secs(1));
idx += 1;
}
});
let mut u8_vec: Vec = Vec::new();
for received in rx {
//println!("thread_borrow Got: {:?}", received);
let a3 = trans_a3(&received); //反向转换 将u8;4数组转换成u8;3数组
u8_vec.push(a3[0]); //将u8;3数组存储到中间byte队列中
if a3[1] != 0u8 {
// 不等于0 继续push
u8_vec.push(a3[1]);
}
if a3[2] != 0u8 {
u8_vec.push(a3[2]);
}
}
let result = String::from_utf8(u8_vec).unwrap(); // 这里将u8;3队列转换成utf-8字符串
result
}
rust里mp5a4_Rust base64 编码解码 首个rust小作品【自用别吐我】相关推荐
- 一些Base64编码/解码及数据压缩/解压方面的知识
一.Base64编码/解码 一般用到的是Delphi自带的单元EncdDecd,当然还有第三方提供的单元或控件,其中我所接触到的认为比较好的有Indy的TIdMimeEncode / TIdMimeD ...
- Delphi Base64编码/解码及ZLib压缩/解压
最近在写的程序与SOAP相关,所以用到了一些Base64编码/解码及数据压缩/解压方面的知识. 在这里来作一些总结: 一.Base64编码/解码 一般用到的是Delphi自带的单元EncdDecd,当 ...
- delphi Base64编码/解码及数据压缩/解压知识
一.Base64编码/解码 一般用到的是Delphi自带的单元EncdDecd,当然还有第三方提供的单元或控件,其中我所接触到的认为比较好的有Indy的TIdMimeEncode / TIdMimeD ...
- openssl算法 —— 利用openssl进行BASE64编码解码、md5/sha1摘要、AES/DES3加密解密
openssl 加密字符串的方法: 一.利用openssl命令进行BASE64编码解码(base64 encode/decode): 1. BASE64编码命令 对字符串'abc'进行base64编码 ...
- Java Base64 编码解码方案总结
转载自 Java Base64 编码解码方案总结 Base64是一种能将任意Binary资料用64种字元组合成字串的方法,而这个Binary资料和字串资料彼此之间是可以互相转换的,十分方便.在实际应 ...
- 原来浏览器原生支持JS Base64编码解码
原来浏览器原生支持JS Base64编码解码 转载来源:https://www.zhangxinxu.com/wordpress/2018/08/js-base64-atob-btoa-encode- ...
- js base64 编码解码
js base64 编码解码 encode decode,可以直接使用 function Base64() {// private property_keyStr = "ABCDEFGHIJ ...
- python使用base64编码解码数据
python使用base64编码解码数据 base64模块是用来作base64编码解码,常用于小型数据的传输.编码后的数据是一个字符串,其包括a-z.A-Z.0-9./.+共64个字符,即可用6个字节 ...
- java svgbase64转byte_java 图片进行base64 编码解码
java 图片进行base64 编码解码 刘振兴 代码分享 2017年06月07日 10555 2条评论 import sun.misc.BASE64Decoder; import sun.misc. ...
最新文章
- 在Ubuntu 16.0.4.5 LTS上安装python 2.7版本的cv2模块
- 正则表达式之?、(?:pattern)、(?!pattern)、(?=pattern)理解及应用
- Index Condition Pushdown Optimization
- 源码下编译APK,却是总是提示,找不到符号:SystemProperties 。。。
- Entity Framework 使用注意:Where查询条件中用到的关联实体不需要Include
- 【Makefile】
- C语言#include还有些你不知道的事
- 【vue2.0进阶】案例:用Vuex实现一个简单的计算器
- 举牌人表情包使用nodejs实现
- 使用python下载一些链接的软件包
- 表格送货单自动编号vba_制作仓库入库单,自动登记商品数据,这段代码只需三步搞定...
- html调用一般处理程序方法,Web的初步篇:前台(HTML)和后台(一般处理程序)...
- SQL Server 软件环境安装与配置
- 2019年复旦计算机专硕考研经验总结
- script加密解密工具下载
- mysql过载保护_浅谈过载保护
- 《三国演义》之二 十常侍乱政
- 淘宝订单详情(插旗)API操作 API 返回值说明
- 遭遇svchoct.exe,vonine.exe,HBKernel32.sys,ssdtti.sys,System.exe,ublhbztl.sys等2
- SHT-31温湿度传感器资料整理