5 个版本
0.2.0 | 2023 年 7 月 9 日 |
---|---|
0.1.5 | 2023 年 7 月 8 日 |
0.1.4 | 2023 年 7 月 6 日 |
0.1.3 | 2023 年 7 月 4 日 |
0.1.2 | 2023 年 7 月 4 日 |
#1530 in 编码
30 个月下载量
160KB
2.5K SLoC
cj_ascii
Rust 中处理 ASCII 字符串的库
AsciiString 是一个类似于 String 的结构体,用于处理 ASCII 和扩展 ASCII 字符。
因为它接受扩展 ASCII,所以接受所有 u8 值。
主要功能
* TryFrom traits have been implemented for string types.
* push/pop push_front/pop_front have been implemented for both char and u8.
* u8 (ascii ordinals) can be accessed by index and updated directly.
* Concatenation of char, u8, &str and AsciiString is supported (will panic if char/string is not valid ASCII).
* Iterators for both u8 and char.
* raw bytes via as_bytes() and as_bytes_mut(), where the bytes are guaranteed to be valid ASCII (one byte = one char).
* stream support via AsciiStreamReader and AsciiStreamWriter (included in this crate).
* async stream support via AsciiStreamReaderAsync and AsciiStreamWriterAsync (included in this crate).
示例
基本示例
fn main() {
use cj_ascii::prelude::*;
let mut astring = AsciiString::try_from("This is a test").unwrap();
let mut astring2 = AsciiString::with_capacity(14);
astring2 += "This";
astring2 += " is";
astring2 += " a";
astring2 += " test";
assert_eq!(astring, astring2);
}
char、u8、&str 和 AsciiString 的连接。
fn main() {
use cj_ascii::prelude::*;
let mut astring = AsciiString::new();
astring += 'A';
astring += 66;
astring += "C";
astring += "DEF";
let astring2 = AsciiString::from(&astring);
astring += astring2;
assert_eq!(&astring.to_string(), "ABCDEFABCDEF");
}
索引
fn main() {
use cj_ascii::prelude::*;
let mut astring = AsciiString::new();
astring += 'A';
astring += 66;
astring += "C";
astring += "DEF";
assert_eq!(astring[0], 'A'.ascii_ord_unchecked());
assert_eq!(astring[1].to_ascii_char(), 'B');
assert_eq!(astring[2], 67);
assert_eq!(astring[3], 68);
assert_eq!(astring[4], 69);
assert_eq!(astring[5], 70);
}
索引可变
fn main() {
use cj_ascii::prelude::*;
let mut astring = AsciiString::new();
astring += "ABCDEF";
astring[0] = 71;
astring[1] = 'H'.ascii_ord_unchecked();
astring[2] = 73;
astring[3] = 74;
astring[4] = 75;
astring[5] = 76;
assert_eq!(astring[0], 'G'.ascii_ord_unchecked());
assert_eq!(astring.to_string(), "GHIJKL");
}
迭代
- 使用 iter() 迭代原始字节。
fn main() {
use cj_ascii::prelude::*;
let mut astring = AsciiString::new();
astring += "ABCDEF";
let mut iter = astring.iter();
assert_eq!(iter.next(), Some(&65));
assert_eq!(iter.next(), Some(&66));
assert_eq!(iter.next(), Some(&67));
assert_eq!(iter.next(), Some(&68));
assert_eq!(iter.next(), Some(&69));
assert_eq!(iter.next(), Some(&70));
assert_eq!(iter.next(), None);
// or
let mut iter = astring.iter();
assert_eq!(iter.next(), Some(&'A'.ascii_ord_unchecked()));
assert_eq!(iter.next(), Some(&'B'.ascii_ord_unchecked()));
assert_eq!(iter.next(), Some(&'C'.ascii_ord_unchecked()));
assert_eq!(iter.next(), Some(&'D'.ascii_ord_unchecked()));
assert_eq!(iter.next(), Some(&'E'.ascii_ord_unchecked()));
assert_eq!(iter.next(), Some(&'F'.ascii_ord_unchecked()));
assert_eq!(iter.next(), None);
}
迭代可变
- 使用 iter_mut() 迭代和修改原始字节。
fn main() {
use cj_ascii::prelude::*;
let mut astring = AsciiString::new();
astring += "ABCDEF";
let mut iter = astring.iter_mut();
for c in iter {
*c = *c + 1;
}
assert_eq!(astring.to_string(), "BCDEFG");
}
迭代 ASCII
- 使用 iter_ascii() 作为字符迭代。
fn main() {
use cj_ascii::prelude::*;
let mut astring = AsciiString::new();
astring += "ABCDEF";
let mut iter = astring.iter_ascii();
assert_eq!(iter.next(), Some('A'));
assert_eq!(iter.next(), Some('B'));
assert_eq!(iter.next(), Some('C'));
assert_eq!(iter.next(), Some('D'));
assert_eq!(iter.next(), Some('E'));
assert_eq!(iter.next(), Some('F'));
assert_eq!(iter.next(), None);
}
迭代 ASCII 组
- AsciiGroup 是一个枚举,表示 ASCII 字符的不同类别。
- 可打印控制字符 - 可打印的控制 ASCII 字符。
- 不可打印控制字符 - 不可打印的控制 ASCII 字符。
- 可打印 - 可打印的 ASCII 字符(空格到波浪号)。
- 扩展 - 扩展 ASCII 范围内的 ASCII 字符(序号 128 到 255)。
fn main() {
use cj_ascii::prelude::*;
let astring = AsciiString::try_from("Hello World!").unwrap();
for x in astring.iter_ascii_group() {
match x {
AsciiGroup::PrintableCtrl(_) => println!("PrintableCtrl: {}", x.as_char()),
AsciiGroup::Printable(_) => println!("PrintableAscii: {}", x.as_char()),
AsciiGroup::NonPrintableCtrl(_) => println!("NonPrintableCtrl: {}", x.as_byte()),
AsciiGroup::Extended(_) => println!("Extended: {}", x.as_byte()),
}
}
}
推入 (char 或 u8)
- u8 值将被原样推入且永远不会失败。
- char 值如果不是 ASCII,将触发 panic。
fn main() {
use cj_ascii::prelude::*;
let mut astring = AsciiString::new();
astring.push('A');
astring.push(66);
astring.push('C');
astring.push('D');
assert_eq!(astring.to_string(), "ABCD");
astring.push_front('Z');
astring.push_front(89);
astring.push_front('X');
assert_eq!(astring.to_string(), "XYZABCD");
}
尝试推入 (char 或 u8)
fn main() {
use cj_ascii::prelude::*;
let mut astring = AsciiString::new();
astring.try_push('A').unwrap();
astring.try_push(66).unwrap();
astring.try_push('C').unwrap();
astring.try_push('D').unwrap();
assert!(astring.try_push('€').is_err());
assert_eq!(astring.to_string(), "ABCD");
let mut astring = AsciiString::new();
astring.try_push_front('A').unwrap();
astring.try_push_front(66).unwrap();
astring.try_push_front('C').unwrap();
astring.try_push_front('D').unwrap();
assert!(astring.try_push_front('€').is_err());
assert_eq!(astring.to_string(), "DCBA");
}
推入 str
- 如果知道字符串只包含 ascii,请使用 push_str。
- 如果字符串包含非 ascii 字符,push_str 将触发 panic。
fn main() {
use cj_ascii::prelude::*;
let mut astring = AsciiString::new();
astring.push_str("ABC");
astring.push_str("DEF");
assert_eq!(astring.to_string(), "ABCDEF");
}
推入 str 有损
- push_str_lossy 将用空格替换非 ascii 字符。
fn main() {
use cj_ascii::prelude::*;
let mut astring = AsciiString::new();
astring.push_str_lossy("ABCD");
astring.push_str_lossy("€");
assert_eq!(astring.to_string(), "ABCD ");
}
无效 ASCII
- 如果字符串包含非 ascii 字符,try_from 将返回错误。
fn main() {
use cj_ascii::prelude::*;
let string = "ABC€";
let result = AsciiString::try_from(string);
assert!(result.is_err());
}
流
- 读取器
fn main() {
use cj_ascii::prelude::*;
use std::io::Cursor;
let mut reader = AsciiStreamReader::new(
Cursor::new(
[84, 104, 105, 115, 32, 105, 115, 32, 116, 101, 115, 116, 32, 49, 10, 84,
104, 105, 115, 32, 105, 115, 32, 116, 101, 115, 116, 32, 50, 13, 10, 84,
104, 105, 115, 32, 105, 115, 32, 116, 101, 115, 116, 32, 51]
)
);
let mut astring = AsciiString::new();
while reader.read_line(&mut astring).is_success() {
println!("{}", astring);
}
}
- 写入器
fn main() {
use cj_ascii::prelude::*;
let mut writer = AsciiStreamWriter::new(Vec::new());
let mut astring = AsciiString::new();
astring += "The beginning.";
writer.write_line(&astring).unwrap();
astring.clear();
astring += "The middle.";
writer.write_line(&astring).unwrap();
astring.clear();
astring += "The end.";
writer.write(&astring).unwrap();
let result = writer.flush();
assert!(result.is_ok());
let vec = writer.into_inner().unwrap();
assert_eq!(vec,
[84, 104, 101, 32, 98, 101, 103, 105, 110, 110, 105, 110, 103,
46, 10, 84, 104, 101, 32, 109, 105, 100, 100, 108, 101, 46,
10, 84, 104, 101, 32, 101, 110, 100, 46]
);
let result = AsciiString::from(vec);
assert_eq!(result.to_string(),"The beginning.\nThe middle.\nThe end.");
}
异步流
- 读取器
async fn read_example() {
use cj_ascii::prelude::*;
use futures::io::Cursor;
let mut stream = AsciiStreamReaderAsync::new(Cursor::new(b"abc\r\ndef\r\nghi"));
let mut buf = AsciiString::new();
while stream.read_line(&mut buf).await.is_success() {
println!("{}", buf);
}
}
// tokio example
async fn read_example_tokio() {
use cj_ascii::prelude::*;
use tokio_util::compat::*;
let file_name = "C:/Temp/EnglishWords/words_ansi.txt";
let file = tokio::fs::File::open(file_name).await.unwrap();
let mut stream = AsciiStreamReaderAsync::new(file.compat());
let mut line = AsciiString::new();
while stream.read_line(&mut line).await.is_success() {
println!("{}", line);
}
}
- 写入器
async fn write_example() {
use cj_ascii::prelude::*;
use futures::io::Cursor;
let mut stream = AsciiStreamWriterAsync::new(Cursor::new(Vec::new()));
let mut buf = AsciiString::new();
buf += "abc";
stream.write_line(&buf).await.unwrap();
buf.clear();
buf += "def";
stream.write_line(&buf).await.unwrap();
buf.clear();
buf += "ghi";
stream.write(&buf).await.unwrap();
stream.flush().await.unwrap();
let result = stream.into_inner();
assert_eq!(result.into_inner(), [97, 98, 99, 10, 100, 101, 102, 10, 103, 104, 105]);
}
// tokio example
async fn write_example_tokio() {
use cj_ascii::prelude::*;
use tokio_util::compat::*;
let file_name = "C:/Temp/Test/words_ansi_out.txt";
let file = tokio::fs::File::create(file_name).await.unwrap();
let mut stream = AsciiStreamWriterAsync::new(file.compat());
let mut line = AsciiString::new();
line += "abc";
stream.write_line(&line).await.unwrap();
line.clear();
line += "def";
stream.write_line(&line).await.unwrap();
line.clear();
line += "ghi";
stream.write(&line).await.unwrap();
stream.flush().await.unwrap();
}
依赖项
~0–300KB