Sign in

    moonttl

    MoonTTL is a high-performance RDF parsing and serialization library for MoonBit.

    nquads
    rdf
    Download zip
    Author
    Version
    0.2.2
    License
    Apache-2.0
    Last updated
    2 months ago
    Downloads
    400

    #MoonTTL

    MoonTTL 是一个使用 MoonBit 语言编写的高性能 RDF 解析与序列化库。本项目参考自 Rust 生态中的优秀库 Oxttl,旨在为 MoonBit 生态提供一套标准化、轻量级的语义网数据处理引擎。

    #特性

    • 多格式支持:完整支持 Turtle, TriG, N-Triples, N-Quads 和 N3 格式的解析与序列化(目前仅支持 N-Quads 格式)。
    • RDF 1.2 兼容:全面支持最新的 RDF 1.2 国际标准规范。
    • 高性能:基于状态机的词法分析器设计,提供高效的解析性能。
    • 轻量级:专注于核心解析功能,保持依赖最小化。

    #安装

    确保你的环境中已经安装了 MoonBit 工具链。

    在你的 moon.mod.json 中添加依赖:

    { "name": "your_username/your_project", "deps": [ "thy1016/moonttl" ] }

    #命令行工具

    #从字符串解析

    moon run src/cmd/main -- "<http://example.org/s> <http://example.org/p> <http://example.org/o> ."

    #从文件解析

    echo '<http://example.org/s> <http://example.org/p> <http://example.org/o> .' > test.nq moon run src/cmd/main -- -f test.nq

    #详细输出模式

    moon run src/cmd/main -- -v -f test.nq

    #命令行选项

    • -f, --file <path> - 指定输入文件路径
    • -v, --verbose - 启用详细输出模式
    • <input> - 直接输入 N-Quads 格式的字符串

    #N-Quads 格式说明

    N-Quads 是一种简洁的 RDF 四元组格式,每行一个语句:

    .

    其中 graph 部分可选,默认为默认图。

    示例:

    <http://example.org/s> <http://example.org/p> <http://example.org/o> .

    #示例代码

    let content = "<http://example.org/s> <http://example.org/p> <http://example.org/o> .\n"
    let data = @utf8.encode(content).to_array()

    let lexer = @lib.Lexer::Lexer(
    @lib.RdfLexer::RdfLexer(@lib.RdfMode::NTriples, false, []),
    data,
    true,
    @lib.MIN_BUFFER_SIZE,
    @lib.MAX_BUFFER_SIZE,
    Some(b"#"),
    0,
    0,
    )

    let logger = @lib.make_console_logger()

    let machine = @lib.NQuadsRecognizer::{
    current_state: @lib.NQuadsState::ExpectSubject,
    stack: [@lib.NQuadsState::ExpectSubject],
    emit_quad: false,
    temp_literal: None,
    lenient: false,
    debug_logger: logger,
    last_range: @lib.Range::default(),
    errors: [],
    }

    let context = @lib.RdfContext::NQuadsRecognizerContext(@lib.NQuadsRecognizerContext::{
    with_graph_name: true,
    lexer_options: { base_iri: None },
    })

    let generic_machine = @lib.GenericStateMachine::GenericStateMachine(
    machine,
    context,
    debug_logger=logger,
    )
    let parser = @lib.Parser::{
    lexer,
    engine: generic_machine,
    context,
    errors: [],
    }


    for ;; {
    match parser.parse_next() {
    Some(Ok(quad)) => println("Parsed: \{quad}")
    Some(Err(e)) => println("Error: \{e}")
    None => break
    }
    }

    #项目结构

    src/ ├── lexer_*.mbt # 词法分析器 ├── parser_*.mbt # 语法分析器 ├── iri.mbt # IRI 处理 ├── literal.mbt # 字面量处理 ├── langtag.mbt # 语言标签处理 └── tests/ # 测试文件

    #Examples

    #解析 N-Quads 文件

    运行示例程序:

    moon run src/examples/nquads
    输出示例:

    Written N-Quads content to: ./example.nq Parsing N-Quads file... [1] Quad<http://example.org/s1, http://example.org/p1, http://example.org/o1> [2] Quad<http://example.org/s2, http://example.org/p2, http://example.org/o2> [3] Quad<http://example.org/s3, http://example.org/p3, http://example.org/o3> [4] Error: InvalidTurtleToken - Unexpected end of input turtle .

    === Summary === Total quads parsed: 3

    该示例展示了:
    • 从字符串创建 N-Quads 内容并写入文件
    • 从文件读取并解析为二进制数据
    • 使用词法分析器和状态机解析 RDF 四元组
    • 错误处理和结果汇总

    #许可证声明

    W3C 测试套件中的测试文件在以下两种许可证下分发,使用时由被许可方二选一:

    • W3C 3-clause BSD License — 允许修改和集成到开发工具中,但禁止对修改后的测试断言性能声明或规范一致性。
    • W3C Test Suite License — 要求测试文件保持未修改状态,方可对外发布性能声明。

    本项目在开发测试和 CI 回归测试中采用 BSD 许可证 使用这些测试用例,并根据项目需求对测试框架进行了适配包装。如需了解 完整版权条款,请参阅 W3C Test Suites Licenses 官方页面。

    #测试覆盖范围

    当前 W3C 测试套件的覆盖情况:

    测试类别 总数 通过 状态 ━━━━━━━━━━━━━━━━━━ ━━━━━━ ━━━━━━ ━━━━━━━━━━━━━ N-Quads 正向测试 45 45 ✅ 全部通过 ────────────────── ────── ────── ───────────── N-Quads 负向测试 12 12 ✅ 全部通过 ────────────────── ────── ────── ───────────── 语法边界测试 8 8 ✅ 全部通过

    #性能基准

    #基准测试环境

    项目 版本/说明 ━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CPU Intel/AMD (测试环境) ────────── ──────────────────────────── 内存 8GB+ ────────── ──────────────────────────── 测试文件 1000 条 N-Quads (约 100KB)

    #性能对比

    实现 解析时间 每秒解析 每条耗时 ━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━ ━━━━━━━━━━━ ━━━━━━━━━━━ MoonTTL (MoonBit) 1.76 ms 568,612 0.0018 ms ──────────────────── ────────── ─────────── ─────────── Oxigraph (Rust) 2.00 ms 500,000 0.0020 ms ──────────────────── ────────── ─────────── ─────────── rdflib (Python) 17.89 ms 55,900 0.0179 ms ──────────────────── ────────── ─────────── ─────────── Apache Jena (Java) 2,734 ms 36,576 0.0273 ms ──────────────────── ────────── ─────────── ─────────── no-brain-scan (C) 0.16 ms 6,250,000 0.0002 ms ### MoonTTL 性能分析 === MoonBit 解析 test_1000.nq === 文件: test_1000.nq 文件大小: 103670 bytes === 性能数据 === Lexer: 515.532 µs (5000 tokens) ParserE: 575.14 µs (1000 quads) 验证: 1448.353 µs (1000 quads, 0 errors) 物化: 310.314 µs (1000 quads, 0 errors) === 总计 === 总时间: 1.76 ms 三元组数量: 1000 每秒解析: 568,612 每三元组: 0.0018 ms

    #运行基准测试

    cd src/benchmark ./run_all.sh

    #性能优化特性

    • 零拷贝设计:词法分析器基于字节数组切片,避免不必要的内存分配
    • 状态机驱动:使用有限状态机进行语法解析,保证 O(n) 时间复杂度
    • 前瞻解析:减少函数调用开销
    • 批量物化:验证和物化分离,支持批量处理
    • 错误恢复:遇到错误自动跳过当前行,继续解析后续内容

    #贡献指南

    欢迎贡献代码、报告问题或提出建议!

    1. Fork 本仓库
    2. 创建您的特性分支 (git checkout -b feature/amazing-feature)
    3. 提交您的更改 (git commit -m 'Add some amazing feature')
    4. 推送到分支 (git push origin feature/amazing-feature)
    5. 开启一个 Pull Request

    #开发环境设置

    #克隆仓库

    git clone https://github.com/thy1016/moonttl.git cd moonttl

    #安装依赖

    moon update

    #运行测试

    moon test

    #构建项目

    moon build

    #许可证

    本项目采用以下许可证:

    • Apache License, Version 2.0, (LICENSE-APACHE or <http://www.apache.org/licenses/LICENSE-2.0>)

    您可自行选择适用的许可证。

    #贡献

    除非您另有明确声明,否则您有意提交给 MoonTTL 的任何贡献(按 Apache-2.0 许可证的定义)均应按上述方式双重许可,不附加任何其他条款或条件。

    Predicate

    type Predicate = ArrayView[Byte]

    Predicate = BytesView(只能是 IRI)

    Ref

    using @moonbitlang/core/ref { type Ref }

    A simple mutable reference type that allows you to store and modify a value of any type.

    test {
    let x = @ref.Ref(42)
    @test.assert_eq(x.val, 42)
    x.val = 100
    @test.assert_eq(x.val, 100)
    }

    Span

    type Span = (Int, Int)

    TagSpan

    type TagSpan = (Int, Int)

    子标签位置,左闭右开 [start, end)

    DebugLogger

    pub trait DebugLogger {
    fn info(Self, String) -> Unit
    fn error(Self, String) -> Unit
    fn warn(Self, String) -> Unit
    }

    ErrOut

    pub trait ErrOut {
    fn message(self : Self) -> String
    fn err_kind(self : Self) -> String
    }

    IriError

    pub(all) suberror IriError {
    NoScheme(Int)
    InvalidScheme(Char, Int)
    InvalidCharacter(Char, Int)
    InvalidPath(Int)
    InvalidAuthority(String)
    InvalidPercentEncoding(Int)
    UnexpectedEnd(Int)
    } derive(
    Debug
    )

    impl Show for IriError
    impl ErrOut for IriError

    IriError::position

    fn IriError::position(self : IriError) -> Int

    ParseError

    pub(all) suberror ParseError {
    StructSyntaxErr(String, Int, (Int, Int))
    SyntaxErr(String, (Int, Int))
    ValidationErr(String)
    IriErr(String)
    } derive(
    Debug
    )

    NQuadsEngine 错误类型(包含位置信息)
    impl Show for ParseError

    ParseError::to_span

    fn ParseError::to_span(err : ParseError) -> (Int, Int)

    TagParseErr

    pub(all) suberror TagParseErr {
    EmptyTag
    EmptySubtag
    InvalidLanguageLength
    ForbiddenChar
    TooManyExtlangs
    InvalidSubtag((Int, Int), StringView)
    EmptyExtension
    EmptyPrivateUse
    InvalidVariant
    InvalidPrivateUsePrefix
    } derive(
    Debug
    )

    impl Show for TagParseErr

    BaseDirection

    pub(all) enum BaseDirection {
    Ltr
    Rtl
    } derive(Eq, Hash, ToJson,
    Debug
    )

    ConsoleLogger

    type ConsoleLogger

    Extension

    pub struct Extension {
    ident : (Int, Int)
    subtags : Array[(Int, Int)]
    } derive(Eq,
    Debug
    )

    扩展 (单字符标识符 + 多个子标签) 例如: u-nu-hanidec → ident='u', subtags=["nu", "hanidec"]
    impl Show for Extension

    ExtensionIter

    pub struct ExtensionIter {
    tag : StringView
    extensions : Array[Extension]
    index : Int
    }

    ExtensionIter::to_array

    fn ExtensionIter::to_array(self : ExtensionIter) -> Array[(StringView, Array[StringView])]

    转换为数组

    GraphName

    pub(all) enum GraphName {
    None
    Iri(ArrayView[Byte])
    } derive(Eq,
    Debug
    )

    图名

    Iri

    pub(all) struct Iri {
    scheme : StringView
    authority : StringView
    path : StringView
    query : StringView
    fragment : StringView
    } derive(Default, Eq,
    Debug
    )

    Iri::Iri

    fn Iri::Iri(scheme : StringView, authority : StringView, path : StringView, query : StringView, fragment : StringView) -> Iri

    Iri::into_string

    fn Iri::into_string(self : Iri) -> String

    序列化为字符串

    Iri::relativize

    fn Iri::relativize(self : Iri, target : Iri) -> Result[Iri, ParseError]

    计算相对 IRI

    Iri::resolve

    fn Iri::resolve(self : Iri, ref_iri : BytesView, remove_dot_segments? : Bool) -> Result[Iri, ParseError]

    合并 base IRI 和参考 IRI (RFC 3986 5.2.2)

    Iri::resolve_unchecked

    fn Iri::resolve_unchecked(self : Iri, ref_iri : BytesView, remove_dot_segments? : Bool) -> Iri

    合并 IRI,忽略错误

    IriSpan

    pub(all) struct IriSpan {
    scheme : (Int, Int)
    authority : (Int, Int)
    path : (Int, Int)
    query : (Int, Int)
    fragment : (Int, Int)
    pos : Int
    } derive(Default, Eq)

    LanguageTag

    pub struct LanguageTag {
    tag : StringView
    state : TagState
    } derive(Eq,
    Debug
    )

    语言标签 (RFC 5646 / BCP 47) 结构: language ["-" extlang] ["-" script] ["-" region] *("-" variant) *("-" extension) ["-" privateuse]
    impl Show for LanguageTag

    LanguageTag::extended_language

    fn LanguageTag::extended_language(self : LanguageTag) -> StringView?

    扩展语言(完整字符串,如 "cmn-hans",不含前缀 "-")

    LanguageTag::extended_language_subtags

    fn LanguageTag::extended_language_subtags(self : LanguageTag) -> Array[StringView]

    扩展语言子标签列表

    LanguageTag::extension_subtags

    fn LanguageTag::extension_subtags(self : LanguageTag) -> ExtensionIter

    LanguageTag::extensions

    fn LanguageTag::extensions(self : LanguageTag) -> ExtensionIter

    扩展迭代器

    LanguageTag::full_language

    fn LanguageTag::full_language(self : LanguageTag) -> StringView

    主语言 + 扩展语言(完整)

    LanguageTag::has_extensions

    fn LanguageTag::has_extensions(self : LanguageTag) -> Bool

    是否有扩展

    LanguageTag::has_private_use

    fn LanguageTag::has_private_use(self : LanguageTag) -> Bool

    是否有私有使用

    LanguageTag::parse

    fn LanguageTag::parse(tag : StringView) -> Result[LanguageTag, TagParseErr]

    解析语言标签

    LanguageTag::parse_and_normalize

    fn LanguageTag::parse_and_normalize(tag : StringView) -> Result[LanguageTag, TagParseErr]

    解析并归一化语言标签

    LanguageTag::primary_language

    fn LanguageTag::primary_language(self : LanguageTag) -> StringView

    主语言(原始格式) 主语言(原始格式)

    LanguageTag::private_use_subtags

    fn LanguageTag::private_use_subtags(self : LanguageTag) -> Array[StringView]

    私有使用子标签列表

    LanguageTag::region

    fn LanguageTag::region(self : LanguageTag) -> StringView?

    区域

    LanguageTag::script

    fn LanguageTag::script(self : LanguageTag) -> StringView?

    脚本

    LanguageTag::to_tagstr

    fn LanguageTag::to_tagstr(self : LanguageTag) -> String

    LanguageTag::variant_subtags

    fn LanguageTag::variant_subtags(self : LanguageTag) -> Array[StringView]

    变体子标签列表

    Lexerc

    pub(all) struct Lexerc {
    ptr :
    Ref
    [Void]
    data : FixedArray[Byte]
    offset : Int
    token_buf : FixedArray[Byte]
    }

    MoonBit 词法分析器

    Lexerc::data

    fn Lexerc::data(self : Lexerc) -> FixedArray[Byte]

    获取原始数据引用

    Lexerc::destroy

    fn Lexerc::destroy(self : Lexerc) -> Unit

    销毁词法分析器

    Lexerc::extract

    fn Lexerc::extract(self : Lexerc, span : (Int, Int)) -> String

    Lexerc::extract_iri

    fn Lexerc::extract_iri(self : Lexerc, token : Token) -> ArrayView[Byte]

    Lexerc::extract_literal

    fn Lexerc::extract_literal(self : Lexerc, token : Token) -> ArrayView[Byte]

    Lexerc::is_end

    fn Lexerc::is_end(self : Lexerc) -> Bool

    检查是否到达末尾

    Lexerc::new

    fn Lexerc::new(data : FixedArray[Byte]) -> Lexerc

    创建词法分析器

    Lexerc::next

    fn Lexerc::next(self : Lexerc) -> Token?

    获取下一个 Token

    Lexerc::position

    fn Lexerc::position(self : Lexerc) -> Int

    获取当前位置

    Lexerc::remaining

    fn Lexerc::remaining(self : Lexerc) -> Int

    获取剩余数据长度

    Lexerc::reset

    fn Lexerc::reset(self : Lexerc) -> Unit

    重置词法分析器

    Literal

    pub(all) struct Literal(LiteralContent) derive(Eq, Hash,
    Debug
    )

    RDF 字面量
    impl Show for Literal

    Literal::datatype

    fn Literal::datatype(self : Literal) -> NamedNodeRef

    获取数据类型

    Literal::destruct

    fn Literal::destruct(self : Literal) -> (StringView, NamedNode?, String?, BaseDirection?)

    分解为 (值, 数据类型, 语言, 方向)

    Literal::direction

    fn Literal::direction(self : Literal) -> BaseDirection?

    获取文本方向

    Literal::language

    fn Literal::language(self : Literal) -> String?

    获取语言标签

    Literal::new_directional_language_tagged_literal

    fn Literal::new_directional_language_tagged_literal(value : String, language : String, direction : BaseDirection) -> Result[Literal, TagParseErr]

    创建带方向的语言标签字面量 (验证语言标签)

    Literal::new_directional_language_tagged_literal_unchecked

    fn Literal::new_directional_language_tagged_literal_unchecked(value : StringView, language : LanguageTag, direction : BaseDirection) -> Literal

    创建带方向的语言标签字面量 (不验证)

    Literal::new_language_tagged_literal

    fn Literal::new_language_tagged_literal(value : String, language : String) -> Result[Literal, TagParseErr]

    创建语言标签字面量 (验证语言标签)

    Literal::new_language_tagged_literal_unchecked

    fn Literal::new_language_tagged_literal_unchecked(value : String, language : String) -> Literal

    创建语言标签字面量 (不验证)

    Literal::new_simple_literal

    fn Literal::new_simple_literal(value : String) -> Literal

    创建简单字面量

    Literal::new_simple_literal_unchecked

    fn Literal::new_simple_literal_unchecked(value : String) -> Literal

    创建简单字面量 (不验证)

    Literal::new_typed_literal_unchecked

    fn Literal::new_typed_literal_unchecked(value : String, datatype : NamedNodeRef) -> LiteralRef

    创建类型字面量 (优化: string 直接用 String 类型)

    Literal::value

    fn Literal::value(self : Literal) -> String

    获取字面量值

    LiteralContent

    pub(all) enum LiteralContent {
    String(String)
    LanguageTaggedString(value~ : String, language~ : String)
    DirectionalLanguageTaggedString(value~ : StringView, language~ : String, direction~ : BaseDirection)
    TypedLiteral(value~ : String, datatype~ : NamedNode)
    } derive(Eq, Hash,
    Debug
    )

    字面量内容

    LiteralRef

    pub(all) struct LiteralRef(LiteralRefContent) derive(Eq, Hash,
    Debug
    )

    字面量引用 (无所有权)
    impl Show for LiteralRef

    LiteralRef::as_value

    fn LiteralRef::as_value(self : LiteralRef) -> StringView

    获取字面量值

    LiteralRef::datatype

    fn LiteralRef::datatype(self : LiteralRef) -> NamedNodeRef

    获取数据类型

    LiteralRef::into_owned

    fn LiteralRef::into_owned(self : LiteralRef) -> Literal

    转_owned

    LiteralRefContent

    pub(all) enum LiteralRefContent {
    String(StringView)
    LanguageTaggedString(value~ : String, language~ : StringView)
    DirectionalLanguageTaggedString(value~ : StringView, language~ : StringView, direction~ : BaseDirection)
    TypedLiteral(value~ : String, datatype~ : NamedNodeRef)
    } derive(Eq, Hash,
    Debug
    )

    字面量引用内容

    MuteLogger

    type MuteLogger

    NQuadsEngine

    pub(all) struct NQuadsEngine {
    pending : PendingQuad
    lexer : Lexerc
    data : ArrayView[Byte]
    last_error : ((Int, Int), Int)?
    line : Int
    }

    NQuadsEngine - 直接对接 Lexerc,管理 PendingQuad 组装和错误收集

    NQuadsEngine::data

    fn NQuadsEngine::data(self : NQuadsEngine) -> ArrayView[Byte]

    获取原始数据

    NQuadsEngine::from_bytes

    fn NQuadsEngine::from_bytes(data : FixedArray[Byte]) -> NQuadsEngine

    从字节数组创建

    NQuadsEngine::new

    fn NQuadsEngine::new(lexer : Lexerc, data : ArrayView[Byte]) -> NQuadsEngine

    创建空 NQuadsEngine

    NQuadsEngine::next

    fn NQuadsEngine::next(self : NQuadsEngine) -> Result[PendingQuad, ParseError]?

    获取下一个三元组

    NamedNode

    pub(all) struct NamedNode {
    iri : String
    } derive(Default, Eq, Hash,
    Debug
    )

    IRI 节点 (拥有所有权)
    impl Show for NamedNode

    NamedNode::as_ref

    fn NamedNode::as_ref(self : NamedNode) -> NamedNodeRef

    as_ref

    NamedNode::new_unchecked

    fn NamedNode::new_unchecked(iri : StringView) -> NamedNodeRef

    创建 NamedNodeRef (不验证)

    NamedNodeRef

    pub(all) struct NamedNodeRef {
    iri : StringView
    } derive(Eq, Hash,
    Debug
    )

    IRI 引用

    NamedNodeRef::into_owned

    fn NamedNodeRef::into_owned(self : NamedNodeRef) -> NamedNode

    转_owned

    Object

    pub(all) enum Object {
    Iri(ArrayView[Byte])
    BNode(ArrayView[Byte])
    Literal(ArrayView[Byte])
    PrefName(ArrayView[Byte])
    } derive(Eq,
    Debug
    )

    宾语类型
    impl Show for Object

    PendingQuad

    pub struct PendingQuad {
    subj : (Int, Int)
    pred : (Int, Int)
    obj : (Int, Int)
    graph : (Int, Int)
    has_dot : Bool
    state : PendingState
    } derive(Eq,
    Debug
    )

    impl Show for PendingQuad

    PendingQuad::compute_span

    fn PendingQuad::compute_span(self : PendingQuad) -> (Int, Int)

    获取总 span

    PendingQuad::default

    fn PendingQuad::default() -> PendingQuad

    PendingQuad::is_complete

    fn PendingQuad::is_complete(self : PendingQuad) -> Bool

    检查是否完整

    PendingQuad::reset

    fn PendingQuad::reset(self : PendingQuad) -> Unit

    重置状态

    PendingState

    pub(all) enum PendingState {
    ExpectSubject
    ExpectPredicate
    ExpectObject
    ExpectDotOrGraph
    ExpectDot
    Complete
    } derive(Eq,
    Debug
    )

    Quad 组装状态机

    PrivateUse

    pub struct PrivateUse {
    prefix : (Int, Int)
    subtags : Array[(Int, Int)]
    } derive(Eq,
    Debug
    )

    私有使用 (x- 前缀 + 多个子标签) 例如: x-mycorp-private → prefix='x', subtags=["mycorp", "private"]
    impl Show for PrivateUse

    QuadEmit

    pub(all) struct QuadEmit {
    subject : Subject
    predicate : ArrayView[Byte]
    object : Object
    graph : GraphName
    } derive(Eq,
    Debug
    )

    N-Quads Quad
    impl Show for QuadEmit

    QuadSpan

    pub struct QuadSpan {
    subj : ArrayView[Byte]
    pred : ArrayView[Byte]
    obj : ArrayView[Byte]
    graph : ArrayView[Byte]?
    subj_type : TermType
    obj_type : TermType
    } derive(
    Debug
    )

    impl Show for QuadSpan

    Range

    pub(all) struct Range {
    start : Int
    end : Int
    } derive(Default, Eq,
    Debug
    )

    Range::Range

    fn Range::Range(start : Int, end : Int) -> Range

    Serializer

    pub struct Serializer {
    data : ArrayView[Byte]
    mode : StringView
    }

    N-Triples 序列化器

    Serializer::new

    fn Serializer::new(data : ArrayView[Byte], mode? : StringView) -> Serializer

    创建序列化器

    Serializer::serialize

    fn Serializer::serialize(self : Serializer, quad : QuadEmit) -> String

    序列化单个 Quad

    Serializer::serialize_all

    fn Serializer::serialize_all(self : Serializer, quads : Array[QuadEmit]) -> String

    批量序列化

    SliceParser

    pub struct SliceParser {
    engine : NQuadsEngine
    data : ArrayView[Byte]
    lenient : Bool
    errors : Array[ParseError]
    }

    SliceParser::lenient

    fn SliceParser::lenient(self : SliceParser) -> SliceParser

    链式调用设置宽松模式

    SliceParser::new

    fn SliceParser::new(engine : NQuadsEngine, data : ArrayView[Byte], lenient? : Bool) -> SliceParser

    SliceParser::next

    fn SliceParser::next(self : SliceParser) -> Result[QuadSpan, ParseError]?

    SliceParser::parse_all

    fn SliceParser::parse_all(self : SliceParser) -> (Array[QuadSpan], Array[ParseError])

    解析全部

    StepResult

    pub(all) enum StepResult {
    Continue
    Emit
    SkipLine
    SkipError((Int, Int))
    Error(ParseError)
    }

    解析步骤结果

    Subject

    pub(all) enum Subject {
    Iri(ArrayView[Byte])
    BNode(ArrayView[Byte])
    PrefName(ArrayView[Byte])
    } derive(Eq,
    Debug
    )

    主语类型
    impl Show for Subject

    TagState

    pub struct TagState {
    language : (Int, Int)
    extlang : (Int, Int)?
    script : (Int, Int)?
    region : (Int, Int)?
    variants : Array[(Int, Int)]
    extensions : Array[Extension]
    private_use : PrivateUse?
    is_grandfathered : Bool
    } derive(Eq,
    Debug
    )

    impl Show for TagState

    TermType

    pub(all) enum TermType {
    Iri
    BNode
    Literal
    PrefName
    Unknown
    } derive(Eq,
    Debug
    )

    impl Show for TermType

    Token

    pub(all) enum Token {
    Dot((Int, Int))
    Semicolon((Int, Int))
    Comma((Int, Int))
    Iri((Int, Int))
    Literal((Int, Int))
    BlankNode((Int, Int))
    PrefName((Int, Int))
    Unknown((Int, Int))
    EOF(Int)
    } derive(
    Debug
    )

    impl Show for Token

    Tokenfast

    pub(all) enum Tokenfast {
    IRI(Int, Int)
    Blank(Int, Int)
    Literal(Int, Int)
    Symbol(Byte, Int, Int)
    LineJump(Int, Int)
    EOF(Int)
    Error(Int, Int)
    } derive(
    Debug
    )

    impl Show for Tokenfast

    Tokenizer

    pub(all) struct Tokenizer {
    view : ArrayView[Byte]
    pos : Int
    len : Int
    }

    Tokenizer::current_pos

    fn Tokenizer::current_pos(self : Tokenizer) -> Int

    获取当前位置(用于错误报告)

    Tokenizer::extract

    fn Tokenizer::extract(self : Tokenizer, start : Int, end : Int) -> String

    从 Tokenfast 提取字符串

    Tokenizer::extract_iri

    fn Tokenizer::extract_iri(self : Tokenizer, token : Tokenfast) -> String

    从 Tokenfast 提取 IRI(去掉 <>)

    Tokenizer::new

    fn Tokenizer::new(view : ArrayView[Byte]) -> Tokenizer

    Tokenizer::tokenize

    fn Tokenizer::tokenize(self : Tokenizer) -> Array[Tokenfast]

    解析所有 Tokenfast

    Tokenizer::tokenize_with_capacity

    fn Tokenizer::tokenize_with_capacity(self : Tokenizer, estimated_count : Int) -> Array[Tokenfast]

    预分配 tokens 数组减少扩容

    Void

    type Void

    MAX_BUFFER_SIZE

    let MAX_BUFFER_SIZE : Int

    MIN_BUFFER_SIZE

    let MIN_BUFFER_SIZE : Int

    MIN_PARALLEL_CHUNK_SIZE

    let MIN_PARALLEL_CHUNK_SIZE : Int

    append_escaped_str

    fn append_escaped_str(f : StringBuilder, string : StringView) -> Unit

    转义 N-Triples 特殊字符

    array_to_view

    fn array_to_view(arr : ArrayView[Byte]) -> BytesView

    array_view_has_prefix

    fn array_view_has_prefix(data : ArrayView[Byte], prefix : Bytes) -> Bool

    array_view_memchr

    fn array_view_memchr(target : Byte, data : ArrayView[Byte]) -> Int?

    array_view_memchr2

    fn array_view_memchr2(c1 : Byte, c2 : Byte, data : ArrayView[Byte]) -> Int?

    end_offset

    fn end_offset(span : (Int, Int)) -> Int

    获取 span 的结束偏移

    find_newline_in_range

    fn find_newline_in_range(bytes : BytesView, start : Int, end : Int) -> Int?

    在指定范围内搜索换行符,返回换行符的绝对位置

    fn_remove_dot_segments

    fn fn_remove_dot_segments(path : StringView) -> StringView

    规范化路径: 处理 . 和 .. (RFC 3986 5.2.4)

    from_str_radix

    fn from_str_radix(s : String, radix : Int) -> Result[UInt, String]

    get_ntriples_file_chunks

    async fn get_ntriples_file_chunks(file :
    File
    , file_size : Int64, n_chunks : Int) -> Result[Array[(Int64, Int64)], String]

    get_ntriples_slice_chunks

    fn get_ntriples_slice_chunks(bytes : Array[Byte], n_chunks : Int) -> Array[(Int, Int)]

    get_turtle_slice_chunks

    fn get_turtle_slice_chunks(bytes : Array[Byte], n_chunks : Int) -> Array[(Int, Int)]

    iri_illegal_table

    let iri_illegal_table : FixedArray[Int]

    非法字符查表:索引为字节值 (0-255),值为 1 表示非法

    is_pchar

    fn is_pchar(c : Char) -> Bool

    is_unreserved

    fn is_unreserved(c : Char) -> Bool

    is_valid_hex_string

    fn is_valid_hex_string(hex : String) -> Bool

    lexer_create

    fn lexer_create(data : FixedArray[Byte], len : Int) ->
    Ref
    [Void]

    创建词法分析器

    lexer_destroy

    fn lexer_destroy(lexer :
    Ref
    [Void]) -> Unit

    销毁词法分析器

    lexer_next

    fn lexer_next(lexer :
    Ref
    [Void], token_buf : FixedArray[Byte]) -> Bool

    获取下一个 Token(写入 Bytes 缓冲区)

    make_console_logger

    fn make_console_logger() -> ConsoleLogger

    make_mute_logger

    fn make_mute_logger() -> MuteLogger

    materialize_all

    fn materialize_all(quads : Array[QuadSpan]) -> (Array[QuadEmit], Array[ParseError])

    批量物化(优化:减少函数调用开销)

    materialize_quad

    fn materialize_quad(quad : QuadSpan) -> Result[QuadEmit, ParseError]

    物化 Quad(批量优化)

    nquads_parser

    fn nquads_parser(input : FixedArray[Byte], lenient? : Bool) -> (Array[QuadSpan], Array[ParseError])

    nquads_serializer

    fn nquads_serializer(data : ArrayView[Byte], quads : Array[QuadEmit], mode? : StringView) -> String

    N-Quads 序列化辅助函数

    parse

    fn parse(view : BytesView) -> Result[Iri, ParseError]

    解析 IRI

    parse_duration

    fn parse_duration(s : String) -> Result[String, String]

    parse_iri

    fn parse_iri(data : BytesView, start : Int) -> Result[IriSpan, ParseError]

    主解析函数

    parse_unchecked

    fn parse_unchecked(view : BytesView) -> Iri

    解析 IRI,忽略错误

    parse_xsd_date

    fn parse_xsd_date(s : String) -> Result[String, String]

    rdf_alt

    let rdf_alt : NamedNodeRef

    rdf_any_uri

    let rdf_any_uri : NamedNodeRef

    rdf_bag

    let rdf_bag : NamedNodeRef

    rdf_base_64_binary

    let rdf_base_64_binary : NamedNodeRef

    rdf_boolean

    let rdf_boolean : NamedNodeRef

    rdf_byte

    let rdf_byte : NamedNodeRef

    rdf_class

    let rdf_class : NamedNodeRef

    rdf_comment

    let rdf_comment : NamedNodeRef

    rdf_container

    let rdf_container : NamedNodeRef

    rdf_container_membership_property

    let rdf_container_membership_property : NamedNodeRef

    rdf_datatype

    let rdf_datatype : NamedNodeRef

    rdf_date

    let rdf_date : NamedNodeRef

    rdf_date_time

    let rdf_date_time : NamedNodeRef

    rdf_date_time_stamp

    let rdf_date_time_stamp : NamedNodeRef

    rdf_day_time_duration

    let rdf_day_time_duration : NamedNodeRef

    rdf_decimal

    let rdf_decimal : NamedNodeRef

    rdf_dir_lang_string

    let rdf_dir_lang_string : NamedNodeRef

    rdf_domain

    let rdf_domain : NamedNodeRef

    rdf_double

    let rdf_double : NamedNodeRef

    rdf_duration

    let rdf_duration : NamedNodeRef

    rdf_first

    let rdf_first : NamedNodeRef

    rdf_float

    let rdf_float : NamedNodeRef

    rdf_g_day

    let rdf_g_day : NamedNodeRef

    rdf_g_month

    let rdf_g_month : NamedNodeRef

    rdf_g_month_day

    let rdf_g_month_day : NamedNodeRef

    rdf_g_year

    let rdf_g_year : NamedNodeRef

    rdf_g_year_month

    let rdf_g_year_month : NamedNodeRef

    rdf_hex_binary

    let rdf_hex_binary : NamedNodeRef

    rdf_html

    let rdf_html : NamedNodeRef

    rdf_int

    let rdf_int : NamedNodeRef

    rdf_integer

    let rdf_integer : NamedNodeRef

    rdf_is_defined_by

    let rdf_is_defined_by : NamedNodeRef

    rdf_json

    let rdf_json : NamedNodeRef

    rdf_label

    let rdf_label : NamedNodeRef

    rdf_lang_string

    let rdf_lang_string : NamedNodeRef

    rdf_language

    let rdf_language : NamedNodeRef

    rdf_list

    let rdf_list : NamedNodeRef

    rdf_literal

    let rdf_literal : NamedNodeRef

    rdf_long

    let rdf_long : NamedNodeRef

    rdf_member

    let rdf_member : NamedNodeRef

    rdf_name

    let rdf_name : NamedNodeRef

    rdf_nc_name

    let rdf_nc_name : NamedNodeRef

    rdf_negative_integer

    let rdf_negative_integer : NamedNodeRef

    rdf_nil

    let rdf_nil : NamedNodeRef

    rdf_nmtoken

    let rdf_nmtoken : NamedNodeRef

    rdf_non_negative_integer

    let rdf_non_negative_integer : NamedNodeRef

    rdf_non_positive_integer

    let rdf_non_positive_integer : NamedNodeRef

    rdf_normalized_string

    let rdf_normalized_string : NamedNodeRef

    rdf_object

    let rdf_object : NamedNodeRef

    rdf_positive_integer

    let rdf_positive_integer : NamedNodeRef

    rdf_predicate

    let rdf_predicate : NamedNodeRef

    rdf_property

    let rdf_property : NamedNodeRef

    rdf_range

    let rdf_range : NamedNodeRef

    rdf_reifies

    let rdf_reifies : NamedNodeRef

    rdf_resource

    let rdf_resource : NamedNodeRef

    rdf_rest

    let rdf_rest : NamedNodeRef

    rdf_see_also

    let rdf_see_also : NamedNodeRef

    rdf_seq

    let rdf_seq : NamedNodeRef

    rdf_short

    let rdf_short : NamedNodeRef

    rdf_statement

    let rdf_statement : NamedNodeRef

    rdf_string

    let rdf_string : NamedNodeRef

    rdf_sub_class_of

    let rdf_sub_class_of : NamedNodeRef

    rdf_sub_property_of

    let rdf_sub_property_of : NamedNodeRef

    rdf_subject

    let rdf_subject : NamedNodeRef

    rdf_time

    let rdf_time : NamedNodeRef

    rdf_token

    let rdf_token : NamedNodeRef

    rdf_type

    let rdf_type : NamedNodeRef

    rdf_unsigned_byte

    let rdf_unsigned_byte : NamedNodeRef

    rdf_unsigned_int

    let rdf_unsigned_int : NamedNodeRef

    rdf_unsigned_long

    let rdf_unsigned_long : NamedNodeRef

    rdf_unsigned_short

    let rdf_unsigned_short : NamedNodeRef

    rdf_value

    let rdf_value : NamedNodeRef

    rdf_wkt_literal

    let rdf_wkt_literal : NamedNodeRef

    rdf_xml_literal

    let rdf_xml_literal : NamedNodeRef

    rdf_year_month_duration

    let rdf_year_month_duration : NamedNodeRef

    remove_dot_segments_from_array

    fn remove_dot_segments_from_array(segments : Array[String]) -> Array[String]