#unic #unicode #iteration #utilities #unicode-text

无需 std unic-char-range

UNIC — Unicode 字符工具 — 字符范围和迭代

4 个版本 (重大更改)

0.9.0 2019年3月3日
0.8.0 2019年1月2日
0.7.0 2018年2月7日
0.6.0 2017年9月22日

#72国际化(i18n)

Download history 99407/week @ 2024-03-14 104760/week @ 2024-03-21 121341/week @ 2024-03-28 104958/week @ 2024-04-04 105525/week @ 2024-04-11 106573/week @ 2024-04-18 101094/week @ 2024-04-25 112831/week @ 2024-05-02 109696/week @ 2024-05-09 124120/week @ 2024-05-16 125649/week @ 2024-05-23 121103/week @ 2024-05-30 128593/week @ 2024-06-06 131804/week @ 2024-06-13 126358/week @ 2024-06-20 108401/week @ 2024-06-27

516,588 每月下载量
用于 1,044 个 crate(直接使用20个)

MIT/Apache

24KB
353

UNIC:为 Rust 开发的 Unicode 和国际化 crate

UNIC-logo

Travis Rust-1.45+ Unicode-10.0.0 Release Crates.io Documentation Gitter

https://github.com/open-i18n/rust-unic

UNIC 是一个开发 Rust 编程语言组件的项目,以提供高质量且易于使用的 Unicode 和国际化数据及算法的 crate。换句话说,它就像是 Rust 的 ICU,完全用 Rust 编写,大部分在 safe 模式下,但在可能的情况下也受益于 unsafe 模式的性能提升。

请参阅 UNIC 更新日志 了解最新发布详情。

项目目标

UNIC 的目标是提供对 Unicode 和国际化功能所有级别的访问,从 Unicode 字符属性开始,到处理文本的 Unicode 算法,再到基于 Unicode Common Locale Data Repository(CLDR)的更高级(基于区域设置)的过程。

其他标准和最佳实践,如 IETF RFCs,根据需要实现,或满足共同需求。

项目状态

目前 UNIC 正在积极开发中:API 在 master 分支上频繁更新,每个 0.x 发布之间都可能发生 API 破坏。请参阅 公开问题 了解计划更改。

我们预计将在 2018 年发布 1.0 版本,之后维护稳定的 API,前几年可能每年进行一到两次 API 更新。

设计目标

  1. UNIC 的主要目标是提供易于使用的 API 来提供可靠的函数。因此,添加的新组件可能不会针对性能进行很好的优化,但将有足够的测试来显示符合标准,以及示例来展示用户如何使用它们来满足常见需求。

  2. UNIC组件的下一个主要目标是性能和低二进制及内存占用。特别是,优化ASCII和其他常见情况下的运行时,将鼓励适应,而无需担心减缓常规的开发流程。

  3. 在可能的情况下,组件保证提供一致的数据和算法。跨组件测试用于捕捉实现之间的任何不一致性,而不会减缓开发流程。

组件及其组织

UNIC 组件 具有层次结构组织,从unic根开始,包含主要组件。每个主要组件反过来可以包含一些次要组件

主要组件的API是为库的最终用户设计的,预计将被广泛文档化,并附带代码示例。

与主要组件相反,次要组件作为高级组件的数据和算法提供者,其API预计将更高效,并且可能提供多种访问数据的方式。

UNIC超级包

unic超级包是所有UNIC(主要)组件的集合,提供了一种方便的方式来访问所有功能,当需要所有或许多功能时,而不是逐个导入组件。此包确保所有导入的组件在算法和数据上都是兼容的。

主要代码示例和跨组件集成测试是在此包下实现的。

主要组件

  • unic-char:Unicode字符工具。Crates.io

  • unic-ucd:Unicode字符数据库(《UAX#44》)。Crates.io

  • unic-bidi:Unicode双向算法(《UAX#9》)。Crates.io

  • unic-normal:Unicode规范化形式(《UAX#15》)。Crates.io

  • unic-segment:Unicode文本分割算法(《UAX#29》)。Crates.io

  • unic-idna:Unicode IDNA兼容性处理(《UTS#46》)。Crates.io

  • unic-emoji:Unicode表情符号(《UTS#51》)。Crates.io

应用

代码组织:合并的仓库

拥有这些组件的合并仓库的一些原因包括

  • 更快开发。实现新的Unicode/i18n组件通常需要依赖其他(较低级别)组件,而这些组件可能需要调整——如暴露新的API、修复错误等——这些都可以在更少的周期和更短的时间内进行开发、测试和审查。

  • 实现完整性。对其他组件的多个依赖意味着这些组件在某种程度上需要相互协调。许多由较小部分组成的Unicode算法假定算法的所有部分都使用相同的Unicode数据版本。违反这个假设可能会导致不一致和难以捕捉的错误。在组合仓库中,在开发过程中以及跨组件(集成)测试中,可以达到更好的完整性。

  • 按需付费。小型组件(基本crate),仅跨依赖它们所需的组件,允许用户只将他们在项目中使用的内容引入。

  • 共享引导。大量扩展Unicode/i18n功能依赖于将源Unicode/地区数据转换为目的地编程语言的规范格式。在组合仓库中,更容易维护这些引导工具,扩大覆盖范围,并使用更高效的数据结构。

文档

如何使用UNIC

Cargo.toml

[dependencies]
unic = "0.9.0"  # This has Unicode 10.0.0 data and algorithms

和在main.rs

extern crate unic;

use unic::ucd::common::is_alphanumeric;
use unic::bidi::BidiInfo;
use unic::normal::StrNormalForm;
use unic::segment::{GraphemeIndices, Graphemes, WordBoundIndices, WordBounds, Words};
use unic::ucd::normal::compose;
use unic::ucd::{is_cased, Age, BidiClass, CharAge, CharBidiClass, StrBidiClass, UnicodeVersion};

fn main() {

    // Age

    assert_eq!(Age::of('A').unwrap().actual(), UnicodeVersion { major: 1, minor: 1, micro: 0 });
    assert_eq!(Age::of('\u{A0000}'), None);
    assert_eq!(
        Age::of('\u{10FFFF}').unwrap().actual(),
        UnicodeVersion { major: 2, minor: 0, micro: 0 }
    );

    if let Some(age) = '🦊'.age() {
        assert_eq!(age.actual().major, 9);
        assert_eq!(age.actual().minor, 0);
        assert_eq!(age.actual().micro, 0);
    }

    // Bidi

    let text = concat![
        "א",
        "ב",
        "ג",
        "a",
        "b",
        "c",
    ];

    assert!(!text.has_bidi_explicit());
    assert!(text.has_rtl());
    assert!(text.has_ltr());

    assert_eq!(text.chars().nth(0).unwrap().bidi_class(), BidiClass::RightToLeft);
    assert!(!text.chars().nth(0).unwrap().is_ltr());
    assert!(text.chars().nth(0).unwrap().is_rtl());

    assert_eq!(text.chars().nth(3).unwrap().bidi_class(), BidiClass::LeftToRight);
    assert!(text.chars().nth(3).unwrap().is_ltr());
    assert!(!text.chars().nth(3).unwrap().is_rtl());

    let bidi_info = BidiInfo::new(text, None);
    assert_eq!(bidi_info.paragraphs.len(), 1);

    let para = &bidi_info.paragraphs[0];
    assert_eq!(para.level.number(), 1);
    assert_eq!(para.level.is_rtl(), true);

    let line = para.range.clone();
    let display = bidi_info.reorder_line(para, line);
    assert_eq!(
        display,
        concat![
            "a",
            "b",
            "c",
            "ג",
            "ב",
            "א",
        ]
    );

    // Case

    assert_eq!(is_cased('A'), true);
    assert_eq!(is_cased('א'), false);

    // Normalization

    assert_eq!(compose('A', '\u{030A}'), Some('Å'));

    let s = "ÅΩ";
    let c = s.nfc().collect::<String>();
    assert_eq!(c, "ÅΩ");

    // Segmentation

    assert_eq!(
        Graphemes::new("a\u{310}e\u{301}o\u{308}\u{332}").collect::<Vec<&str>>(),
        &["a\u{310}", "e\u{301}", "o\u{308}\u{332}"]
    );

    assert_eq!(
        Graphemes::new("a\r\nb🇺🇳🇮🇨").collect::<Vec<&str>>(),
        &["a", "\r\n", "b", "🇺🇳", "🇮🇨"]
    );

    assert_eq!(
        GraphemeIndices::new("a̐éö̲\r\n").collect::<Vec<(usize, &str)>>(),
        &[(0, ""), (3, ""), (6, "ö̲"), (11, "\r\n")]
    );

    assert_eq!(
        Words::new(
            "The quick (\"brown\") fox can't jump 32.3 feet, right?",
            |s: &&str| s.chars().any(is_alphanumeric),
        ).collect::<Vec<&str>>(),
        &["The", "quick", "brown", "fox", "can't", "jump", "32.3", "feet", "right"]
    );

    assert_eq!(
        WordBounds::new("The quick (\"brown\")  fox").collect::<Vec<&str>>(),
        &["The", " ", "quick", " ", "(", "\"", "brown", "\"", ")", " ", " ", "fox"]
    );

    assert_eq!(
        WordBoundIndices::new("Brr, it's 29.3°F!").collect::<Vec<(usize, &str)>>(),
        &[
            (0, "Brr"),
            (3, ","),
            (4, " "),
            (5, "it's"),
            (9, " "),
            (10, "29.3"),
            (14, "°"),
            (16, "F"),
            (17, "!")
        ]
    );
}

您可以在examplestests目录下找到更多示例。(随着UNIC的扩展,还将添加更多内容...)

许可

许可方式为以下之一

任选其一。

贡献

除非您明确说明,否则根据Apache-2.0许可定义的,您提交的任何旨在包含在作品中的贡献,将按上述方式双重许可,不附加任何额外条款或条件。

行为准则

UNIC项目遵循Rust行为准则。您可以在CODE_OF_CONDUCT.md中找到一份副本,或在https://rust-lang.net.cn/conduct.html在线查看。


lib.rs:

UNIC — Unicode字符工具 — 字符范围

一种简单控制字符范围迭代的方法。

示例

#[macro_use] extern crate unic_char_range;

for character in chars!('a'..='z') {
    // character is each character in the lowercase english alphabet in order
}

for character in chars!(..) {
    // character is every valid char from lowest codepoint to highest
}

功能

这些功能默认不包含;它们依赖于不稳定的Rust功能门。

依赖关系

~0–265KB