rust 1.27.2编译通过。算法很烂,其中一些 变量的生存周期和所有权转移之类都还不完全明确。先记录下来。
吐槽一下,为啥代码样式没有rust的
// base64code
use std::string::String;
use std::collections::HashMap;
// 模块形式就要注释这句,如果是bin执行模式 编译就放开这句
// fn main() {
// println!("Hello, world!");
// // base64测试
// base64_test();
// }
pub fn base64_test(){
let source_txt = String::from("asdfd流啊荒野大34242344frer34如werr3r登革热广告1");
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(""); // 结果变量
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<[u8;3]> = Vec::new(); // 存放u8;3的队列
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_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 数组
//
result.push(b64_to_char(a4[0])); // 这里后面都是根据对照表提取字符然后存入转换结果
result.push(b64_to_char(a4[1]));
if b_len == i + 1 { // 结尾处理
if a4[2] == 0u8 {
result.push('='); // 结尾处要独立处理 = 号的问题
} else{
result.push(b64_to_char(a4[2]));
}
if a4[3] == 0u8 {
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 解码 算法很烂,还有巨大优化空间
pub fn base64decode(code: &String) -> String {
let mut u8_vec:Vec<u8> = Vec::new(); // 结果队列,byte队列,到字符串还要转换一下
let mut num_array:[u8;4] = [0;4]; // 单个 u8;4数组
let mut num_vec:Vec<[u8;4]> = Vec::new(); // u8;4数组队列
let chars = code.chars(); // base64编码字符队列
let len = code.len(); // base64编码长度
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数组队列长度
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 {
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<u8, char> = [(0, 'A')].iter().cloned().collect();
// str类型 b64对照表
const B64_STR:&'static str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";