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小作品【自用别吐我】相关推荐

  1. 一些Base64编码/解码及数据压缩/解压方面的知识

    一.Base64编码/解码 一般用到的是Delphi自带的单元EncdDecd,当然还有第三方提供的单元或控件,其中我所接触到的认为比较好的有Indy的TIdMimeEncode / TIdMimeD ...

  2. Delphi Base64编码/解码及ZLib压缩/解压

    最近在写的程序与SOAP相关,所以用到了一些Base64编码/解码及数据压缩/解压方面的知识. 在这里来作一些总结: 一.Base64编码/解码 一般用到的是Delphi自带的单元EncdDecd,当 ...

  3. delphi Base64编码/解码及数据压缩/解压知识

    一.Base64编码/解码 一般用到的是Delphi自带的单元EncdDecd,当然还有第三方提供的单元或控件,其中我所接触到的认为比较好的有Indy的TIdMimeEncode / TIdMimeD ...

  4. openssl算法 —— 利用openssl进行BASE64编码解码、md5/sha1摘要、AES/DES3加密解密

    openssl 加密字符串的方法: 一.利用openssl命令进行BASE64编码解码(base64 encode/decode): 1. BASE64编码命令 对字符串'abc'进行base64编码 ...

  5. Java Base64 编码解码方案总结

    转载自  Java Base64 编码解码方案总结 Base64是一种能将任意Binary资料用64种字元组合成字串的方法,而这个Binary资料和字串资料彼此之间是可以互相转换的,十分方便.在实际应 ...

  6. 原来浏览器原生支持JS Base64编码解码

    原来浏览器原生支持JS Base64编码解码 转载来源:https://www.zhangxinxu.com/wordpress/2018/08/js-base64-atob-btoa-encode- ...

  7. js base64 编码解码

    js base64 编码解码 encode decode,可以直接使用 function Base64() {// private property_keyStr = "ABCDEFGHIJ ...

  8. python使用base64编码解码数据

    python使用base64编码解码数据 base64模块是用来作base64编码解码,常用于小型数据的传输.编码后的数据是一个字符串,其包括a-z.A-Z.0-9./.+共64个字符,即可用6个字节 ...

  9. java svgbase64转byte_java 图片进行base64 编码解码

    java 图片进行base64 编码解码 刘振兴 代码分享 2017年06月07日 10555 2条评论 import sun.misc.BASE64Decoder; import sun.misc. ...

最新文章

  1. 在Ubuntu 16.0.4.5 LTS上安装python 2.7版本的cv2模块
  2. 正则表达式之?、(?:pattern)、(?!pattern)、(?=pattern)理解及应用
  3. Index Condition Pushdown Optimization
  4. 源码下编译APK,却是总是提示,找不到符号:SystemProperties 。。。
  5. Entity Framework 使用注意:Where查询条件中用到的关联实体不需要Include
  6. 【Makefile】
  7. C语言#include还有些你不知道的事
  8. 【vue2.0进阶】案例:用Vuex实现一个简单的计算器
  9. 举牌人表情包使用nodejs实现
  10. 使用python下载一些链接的软件包
  11. 表格送货单自动编号vba_制作仓库入库单,自动登记商品数据,这段代码只需三步搞定...
  12. html调用一般处理程序方法,Web的初步篇:前台(HTML)和后台(一般处理程序)...
  13. SQL Server 软件环境安装与配置
  14. 2019年复旦计算机专硕考研经验总结
  15. script加密解密工具下载
  16. mysql过载保护_浅谈过载保护
  17. 《三国演义》之二 十常侍乱政
  18. 淘宝订单详情(插旗)API操作 API 返回值说明
  19. 遭遇svchoct.exe,vonine.exe,HBKernel32.sys,ssdtti.sys,System.exe,ublhbztl.sys等2
  20. SHT-31温湿度传感器资料整理

热门文章

  1. Mysql分表创建索引
  2. python-每日一练-抽取某本书的前50条短评内容并计算评分的平均值
  3. nginx启动停止重启
  4. XP下自己动手重装IE6.0的3种方法(建议第三种,原创)
  5. Flash Builder4.7 更新Air SDK及FlashPlayer
  6. python的range函数
  7. Discuz3.X可以放广告的地方积累
  8. nginx 重定向地址
  9. mysql8.0安装及配置超详细教程_系统城教你mysql8.0安装与配置教程
  10. 3D线光谱共焦传感器在半导体如何检测