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 个月下载量

MIT/Apache

160KB
2.5K SLoC

cj_ascii

Rust Dependency Review Crate API

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