5个不稳定版本

0.3.1 2022年2月27日
0.3.0 2022年2月27日
0.1.1 2022年2月27日
0.1.0 2022年2月26日
0.0.1 2022年2月24日

解析器实现中排名2640

MIT授权

19KB
132

UDV

无歧义分隔值。类似于CSV,但一致、无歧义、可预测。

描述

使用前导分隔符和简单的字符转义,允许简单且无歧义地引入单元和记录,无歧义地声明头部,无歧义地连接文档,能够区分0字段和1个空字段,以及能够使用任意二进制数据。

这是编码无关的,但分隔符必须是单个码点。显然的规范表示是utf-8和二进制,但任何编码都是可能的。

EBNF如下,其中全部大写值各自是一个可配置的单码点分隔符

stream = {garbage}, { message, {garbage} }, ENDSTREAM;
garbage = (* - (MESSAGE | HEADER | ENDSTREAM) )
message = [header], MESSAGE, { record }, ENDMESSAGE;
header = HEADER, units;
record = RECORD, units;
units = { UNIT, unit };
unit = { (* - control) | (ESCAPE, *) };
control = ENDSTREAM | HEADER | MESSAGE | ENDMESSAGE | RECORD | UNIT | ESCAPE;

默认分隔符

HEADER = "#";
MESSAGE = ">";
ENDMESSAGE = "<";
RECORD = ? ASCII newline ?;
UNIT = ",";
ESCAPE = "\";
ENDSTREAM = "!";

大多数情况下,这是一个以前缀为导向的格式。两个例外是ENDMESSAGE和ENDSTREAM分隔符。ENDMESSAGE分隔符允许在不插入换行符的情况下编辑文本UDV消息文件,而不会引起问题(因为这种格式的目的是无歧义,文件末尾的换行符必须被视为最后一个单元的一部分,或者引入一个空记录)。ENDSTREAM分隔符允许UDV数据不依赖于预先知道长度或依赖于流中缓冲区的物理几何形状。这是明确的,要求任何UDV消息中的ENDSTREAM码点必须显式转义,允许任何UDV解析器在任意位置无修改地解析UDV流。这也可以用来在文件末尾嵌入UDV流,并将UDV偏移量放在ENDSTREAM之后,以便可以从尾部数据定位开始位置。

示例,使用默认分隔符

带有头部和两个记录的单个消息

#,id,name,value>
,1,taylor,developer
,2,namewith\,comma,valuewith\
newline<

没有头部和两个记录的单个消息

>
,1,taylor,developer
,2,namewith\,comma,valuewith\
newline<

带有头部但没有记录的单个消息

#,id,name,value><

带有头部和一个空记录的单个消息

#,id,name,value>
<

带有空单元的头部,以及所有空单元的记录

#,id,name,,value>
,,,,<

最短的有效消息

><

没有头部和一个具有一个空单元的记录的单个消息

>
,<

没有头部,一个记录有一个空单元,一个记录有零个空单元,一个记录有一个空单元,一个记录有两个空单元

>

,
,,<

将所有前面的示例连接为消息流,以ENDSTREAM字符分隔结束

这利用了任何数量的垃圾数据都可能出现在任何 MESSAGE、HEADER 或 ENDSTREAM 字符之前的事实,允许尾部换行不会引起问题。

#,id,name,value>
,1,taylor,developer
,2,namewith\,comma,valuewith\
newline<
>
,1,taylor,developer
,2,namewith\,comma,valuewith\
newline<
#,id,name,value><
#,id,name,value>
<
#,id,name,,value>
,,,,<
><
>
,<
>

,
,,<
!

最短的有效流

!

相对于 CSV 的优势

  • 标题被明确分隔,因此永远不会对第一行是否构成标题产生猜测。
  • 解析非常简单且明确。没有像 CSV 那样的问题,需要确定换行符是否属于值的一部分,或者值周围的引号是否属于值的一部分,或者如何在值内部转义逗号和引号。
  • 可以区分没有记录的消息、没有单位的记录的消息以及有一个空单位的消息。
  • 带有或没有标题的多个文档可以连接到同一个流中,并且可以无损失地解析。由于消息周围垃圾数据的规则,通常可以天真地连接消息文件,只要它们的结尾没有 ENDSTREAM。
  • 结束流 ENDSTREAM 允许 UDV 流嵌入更多数据中,并且可以使用其起始码点指针无问题地解析。
  • 在二进制编码中,甚至可以无问题地嵌入二进制数据。还可以使用以下规则使用 C0 控制代码将自描述的二进制消息流嵌入其中
HEADER = SOH;
MESSAGE = STX;
ENDMESSAGE = ETX;
RECORD = RS;
UNIT = US;
ESCAPE = ESC;
ENDSTREAM = EOT;

如果你有一个主要是字符串消息的流,这些规则可以帮助将其序列化到尽可能紧凑的流中,同时尽可能少地进行转义。还有一个 C0-utf8 模式,在保持有效的 utf-8 的同时完成这项工作。

缺点

  • 为了使格式明确而做出的妥协可能会使其手读和手写变得有些笨拙,尤其是在管理许多消息的流时。
  • 因为字符串不是长度前缀,解析字符串必须逐字符进行,并且转义序列可能会干扰无复制读取。与其他二进制格式相比,这是一个缺点,而不是 CSV 或其他面向文本的格式。

依赖关系

~1MB
~19K SLoC