diff --git a/Cargo.toml b/Cargo.toml index 203d286..10f8fc7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,4 +18,5 @@ hmac-sha512 = "1.1.5" md-5 = "0.10.5" rand = "0.8.5" sha1 = "0.10.5" +thiserror = "1.0.40" uuid = { version = "1.4.0", features = ["v4", "fast-rng"] } diff --git a/README.md b/README.md index 5099d04..9a49b13 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Rust 中可以使用的常用辅助功能工具箱。主要配备以下功能: - 验证码生成器 - [ ] 随机验证码生成算法 - 序列化算法 - - [ ] Base64 算法 - - [ ] Hex 直转 + - [x] Base64 算法 + - [x] Hex 直转 本工具箱仅可支持于 Rust 程序中使用,可以编译为`rlib`或者`dylib`。 diff --git a/src/serialize/mod.rs b/src/serialize/mod.rs index e69de29..d917b95 100644 --- a/src/serialize/mod.rs +++ b/src/serialize/mod.rs @@ -0,0 +1,56 @@ +use base64::Engine; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum HexSerializeError { + #[error("Invalid hex char: {0}")] + InvalidHexChar(#[from] hex::FromHexError), +} + +#[derive(Debug, Error)] +pub enum Base64SerializeError { + #[error("Cannot encode Base64 slice: {0}")] + EncodeFailed(#[from] base64::EncodeSliceError), + #[error("Cannot decode Base64 string: {0}")] + DecodeFailed(#[from] base64::DecodeError), +} + +/// 将指定可以转换为字节数组的内容以十六进制字符串的形式输出。 +pub fn to_hex>(input: T) -> String { + hex::encode(input) +} + +/// 将十六进制字符串转换为字节数组,如果字符串中存在非十六进制字符,则返回错误。 +pub fn from_hex(input: &str) -> Result, HexSerializeError> { + hex::decode(input).map_err(|e| e.into()) +} + +/// 将给定的可以转换为字节数组的内容以Base64编码的字符串形式输出。 +pub fn to_base64_str>(input: T) -> String { + base64::prelude::BASE64_STANDARD.encode(input) +} + +/// 将给定的可以转换为字节数组的内容以Base64编码的字节数组形式输出。 +pub fn to_base64_vec>(input: T) -> Result, Base64SerializeError> { + let mut buf = Vec::new(); + base64::prelude::BASE64_STANDARD + .encode_slice(input.as_ref(), &mut buf) + .map_err(|e| Base64SerializeError::EncodeFailed(e))?; + Ok(buf) +} + +/// 将给定的Base64编码的字符串转换为字节数组,如果字符串中存在不能被识别的内容,则返回错误。 +pub fn from_base64_str(input: &str) -> Result, Base64SerializeError> { + base64::prelude::BASE64_STANDARD + .decode(input) + .map_err(|e| e.into()) +} + +/// 将给定的Base64编码的字节数组转换为原始字节数组,如果字节数组中存在不能被识别转换的内容,则返回错误。 +pub fn from_base64_vec>(input: T) -> Result, Base64SerializeError> { + let mut buf = Vec::new(); + base64::prelude::BASE64_STANDARD + .decode_vec(input.as_ref(), &mut buf) + .map_err(|e| Base64SerializeError::DecodeFailed(e))?; + Ok(buf) +} diff --git a/tests/serialize.rs b/tests/serialize.rs new file mode 100644 index 0000000..4cc9faf --- /dev/null +++ b/tests/serialize.rs @@ -0,0 +1,39 @@ +#[cfg(test)] +mod hex { + #[test] + fn encode_hex() { + let input = vec![0x01, 0x02, 0x03, 0x04, 0x0f, 0xff]; + let output = rs_toolbox::serialize::to_hex(input); + assert_eq!(output, "010203040fff"); + } + + #[test] + fn decode_hex() { + let input = "010203040fff"; + let output = match rs_toolbox::serialize::from_hex(input) { + Ok(v) => v, + Err(e) => panic!("Error: {:?}", e), + }; + assert_eq!(output, vec![0x01, 0x02, 0x03, 0x04, 0x0f, 0xff]); + } +} + +#[cfg(test)] +mod base64 { + #[test] + fn encode_base64_str() { + let input = "hello"; + let output = rs_toolbox::serialize::to_base64_str(input); + assert_eq!(output, "aGVsbG8="); + } + + #[test] + fn decode_base64_str() { + let input = "aGVsbG8="; + let output = match rs_toolbox::serialize::from_base64_str(input) { + Ok(v) => String::from_utf8(v).unwrap(), + Err(e) => panic!("Error: {:?}", e), + }; + assert_eq!(output, "hello"); + } +}