3个版本 (重大变更)

0.9.0 2019年3月3日
0.8.0 2019年1月2日
0.7.0 2018年2月7日

#472文本处理

Download history • Rust 包仓库 23048/week @ 2024-04-20 • Rust 包仓库 21068/week @ 2024-04-27 • Rust 包仓库 21817/week @ 2024-05-04 • Rust 包仓库 25281/week @ 2024-05-11 • Rust 包仓库 33676/week @ 2024-05-18 • Rust 包仓库 25864/week @ 2024-05-25 • Rust 包仓库 24186/week @ 2024-06-01 • Rust 包仓库 28107/week @ 2024-06-08 • Rust 包仓库 25369/week @ 2024-06-15 • Rust 包仓库 26485/week @ 2024-06-22 • Rust 包仓库 25048/week @ 2024-06-29 • Rust 包仓库 25727/week @ 2024-07-06 • Rust 包仓库 22877/week @ 2024-07-13 • Rust 包仓库 23594/week @ 2024-07-20 • Rust 包仓库 27596/week @ 2024-07-27 • Rust 包仓库 27376/week @ 2024-08-03 • Rust 包仓库

105,878 每月下载量
192 个crate中使用 (直接使用7个)

MIT/Apache

85KB
1K SLoC

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通用区域数据存储库(CLDR)的更高级(基于区域设置)过程。

其他标准和最佳实践,如IETF RFC,根据Unicode/CLDR组件的需求或普遍需求也得到实现。

项目状态

目前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 数据版本。违反这一假设可能导致不一致和难以发现的错误。在合并的仓库中,可以在开发过程中以及跨组件(集成)测试中达到更好的完整性。

  • 按需付费。小型组件(基本包),仅依赖它们需要的组件,允许用户仅引入他们在项目中消费的部分。

  • 共享引导。大量扩展 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 — UCD — 标识符属性

unic 的一部分:为 Rust 提供的 Unicode 和国际化包。

是广泛用于 UAX31 Unicode 标识符和模式语法 的 UCD 属性的访问器。

功能

  • xid(默认):XID_StartXID_Continue 属性。

  • id(可选):ID_StartID_Continue 属性。注意:在大多数情况下,您应该优先使用 XID 属性,因为它们在 NFKC 规范化下是一致的。

  • pattern(可选):Pattern_SyntaxPattern_White_Space 属性。

依赖项