6 个版本 (3 个稳定)
使用旧的 Rust 2015
1.1.0 | 2020年2月1日 |
---|---|
1.0.1 | 2019年10月11日 |
1.0.0 | 2018年6月11日 |
0.2.0 | 2018年1月9日 |
0.1.0 | 2017年11月7日 |
#677 in 文本处理
每月139次下载
用于 11 个 Crates (8 个直接)
51KB
1.5K SLoC
soft-ascii-string
soft-ascii-string 提供了 char、str 和 string 包装器,增加了 "is-ascii" 软约束。
由于这是一个软约束,它可以被违反,而违反通常是一个错误,但它 不会 引入任何安全问题。在这点上,soft-ascii-string 与例如 ascii 不同,ascii 使用硬约束,违反约束会破坏 Rust 的安全性,并可能引入未定义的行为。
Soft-ascii-string 适用于许多地方(例如外部库)输出应该是 ASCII 的字符串,你不想遍历以确保它们是 ASCII,但你也不想使用 unsafe 转换,因为这会要求使用 ascii crate。
如果你想在安全级别上确保字符串是 ASCII,这个 crate 并不一定适合你,你可能需要考虑在这种情况下使用 ascii。
文档可以在 docs.rs 上查看。
示例
extern crate soft_ascii_string;
use soft_ascii_string::{SoftAsciiChar, SoftAsciiStr, SoftAsciiString};
fn main() {
// encoder_stub should encode all non-ascii chars
// but it's a complex external dependency so we do
// not want to rely on it on a safety level
let mut ascii = SoftAsciiString::from_unchecked(external::encoder_stub("magic↓"));
// we know ":" is ascii so no unnecessary checks here
ascii.push(SoftAsciiChar::from_unchecked(':'));
// we know "abcde" is ascii so no unnecessary checks here
ascii.push_str(SoftAsciiStr::from_unchecked("abcde"));
// lets assume we got this from somewhere
let other_input = "other string";
let part = SoftAsciiStr::from_str(other_input)
.expect("other_input should have been ascii");
ascii.push_str(part);
let mut clone = SoftAsciiString::with_capacity(ascii.len());
// the chars(), char_indices() operators return a
// iterator returning SoftAsciiChars
for ch in ascii.chars() {
clone.push(ch);
}
// we do all kind of cost transformations
// without having to revalidate that it is
// ascii as long as we do not want to rely on it
internal::costy_transformations(&mut ascii);
// when running unsafe code we really do not want a bug
// which introduced non ascii code to introduce unsafety
// so we can just validate if it really is ascii.
// On the other hand as long as we do not need a 100% guarantee
// for security reason we do not need to call revalidate.
match ascii.revalidate_soft_constraint() {
Ok(ascii) => {
unsafe {external::requires_ascii(ascii.as_bytes())}
},
Err(err) => panic!("non-ascii content in ascii string")
}
}
mod internal {
use soft_ascii_string::SoftAsciiString;
pub fn costy_transformations(s: &mut SoftAsciiString) {
let s2 = s.clone();
s.insert_str(0, &*s2)
}
}
mod external {
// lets assume this is an external function only working with ascii
pub unsafe fn requires_ascii(b: &[u8]) {}
// lets assume this is more complex and
// from a external dependency, we assume
// it returns ascii, but what if there is
// a bug
pub fn encoder_stub(s: &str) -> String {
let mut out = String::with_capacity(s.len());
for ch in s.chars() {
if ' ' <= ch && ch <= '~' {
out.push(ch)
} else { out.push('?') }
}
out
}
}
错误处理
extern crate soft_ascii_string;
use soft_ascii_string::{SoftAsciiChar, SoftAsciiStr, SoftAsciiString};
fn main() {
let non_ascii_input: String = "←↓↓↓".into();
match SoftAsciiString::from_string(non_ascii_input) {
Ok(ok_value) => panic!("the string should not have been ascii"),
Err(err) => {
let original_source: String = err.into_source();
println!("the input was: {:?}", original_source)
}
}
}
许可协议
根据您选择以下其中一项许可协议
- Apache License,版本 2.0,(LICENSE-APACHE 或 http://www.apache.org/licenses/LICENSE-2.0)
- MIT 许可协议 (LICENSE-MIT 或 http://opensource.org/licenses/MIT)
任选其一。
贡献
除非您明确声明,否则根据 Apache-2.0 许可协议定义,您有意提交的任何贡献,都将按照上述方式双重许可,不附加任何额外条款或条件。
变更日志
v1.0
- 向
SoftAsciiChar
、SoftAsciiStr
、SoftAsciiString
添加了from_unchecked
- 弃用了
from_char_unchecked
、from_str_unchecked
、from_string_unchecked
- 向