信封编码c
形状信件的独立、无依赖的编码器 { env, body? }。 。 。 .
整个问题:信息是 信封 (结构路由/控制) 元数据)加一 任择机构 (opaque octets) (英语). 编码器只编码 频道编码中的信封 身体通过字节表示 从未解码或检查这就是让尸体成为编码的原因,或者 已封存/ 加密, 编码器费用为零 .
它对WebSockets,队列,或运输一无所知. 这是纯洁的
encode编号 :decode 双人 这个 Codec 形状是鸭子类型,与什么兼容
可靠连接的运输预期—— 但这里没有输入这样的库.
- 运行时间道克:0.
cbor-x财务报告和审定财务报表pino是可选的同伴依赖关系, 懒得说 软件包完全没有安装(只有JSON). - 阿宝 (单位:千美元)
bun test, (中文(简体) ),bun运行时间).
它所支持的东西
执行和涵盖以下所有项目: bun test (51个测试):
- 信封的两个信道编码 - JSON(强制基线,UTF-8)
JSON文本)和CBOR(RFC 8949,通过
cbor-x) (中文(简体) ). - 不透明体,字节取出. JSON携带一具小身体作为基座64或,
带外模式,作为长度/
contentType仅标出文字. CBOR 载有 作为二进制正体 本地未标记的字节字符串 - 无 base64 税解码 返回每个模式中的确切输入八分点;解码器从不剖析正文. - 1字节二进制歧视者 (单位:千美元)
0x01信封数 /0x02原始块, ,在任何登记册之前解决 解码后接收器就不再试镜了. - 通过模式 - 将一个任意的不透明框架包裹为下体 默认信封,因此解码器可以备份原始字节的传输.
- 未信任输入的硬化解码 -- 解码前的大小盖,最大巢穴
深度、 最大收藏大小、 重复键拒绝和 (CBOR) 拒绝
无限期长度和标记(无标记->类即时). 每一次失败都是
类型
CodecError从不漏出一掷一绞. - 编码谈判 优先排序和版本意识;对等者 当地不同的订单仍然一致,没有往返.
- 可注入式记录 - 默认沉默;
console或可选pino。 。 。 .
安装
bun add @claudewerk/envelope-codec
bun add cbor-x # optional: enables the CBOR channel
bun add pino # optional: structured logging
使用量
import { jsonCodec, cborCodec, negotiate, codecFor } from '@claudewerk/envelope-codec';
const enc = negotiate(['cbor', 'json'], theirAdvertised); // 'cbor' | 'json'
const codec = codecFor(enc);
const wire = codec.encode({
env: { to: 'node-7', kind: 'sync', seq: 9 },
body: new Uint8Array([0xde, 0xad, 0xbe, 0xef]), // opaque octets
contentType: 'application/octet-stream',
});
const msg = codec.decode(wire);
// msg.env -> { to: 'node-7', kind: 'sync', seq: 9 } (opaque object, not interpreted)
// msg.body -> Uint8Array [0xde,0xad,0xbe,0xef] (exact input bytes, untouched)
// msg.contentType -> 'application/octet-stream'
编码接口
interface Codec {
encoding: 'json' | 'cbor';
encode(msg: { env: object; body?: Uint8Array; contentType?: string }): Uint8Array | string;
decode(data: Uint8Array | string): { env: object; body?: Uint8Array; contentType?: string; bodyBytes?: number };
}
jsonCodec(opts?): Codec;
cborCodec(opts?): Codec; // throws CodecError('CBOR_UNAVAILABLE') if cbor-x is absent
negotiate(ours: string[], theirs: string[]): 'json' | 'cbor';
codecFor(encoding, opts?): Codec;
选项( 双解码器 ) : { maxBytes, limits: { maxDepth, maxItems }, log, passthrough }。 。 。 .
jsonCodec 还要 { oob } (出带正文下.
单位 通过模式 (单位:千美元)passthrough: true(中文(简体) ) encode() 也接受原始数据
Uint8Array。见 通过模式。 。 。 .
线条格式
这个 env 是不透明的 -- 解码器从不读取其字段。 两个频道串行
同一个带密钥的逻辑线对象 env选项 contentType,则
每个频道携带的可选身体不同.
JSON频道(强制性基线)
信封是UTF-8 JSON文本:
{
"env": { "...": "..." },
"contentType": "application/octet-stream",
"body": "<base64 of the opaque body>"
}
二进制车身内置为 基础64 下级 body基数64 绕行
精确的octets,所以解码还原它们不变;字节从不解析.
带外模式 (单位:千美元)jsonCodec({ oob: true }): 无字节被内嵌; 只有 a
描述器被放出,身体在侧道上行走.
{ "env": { "...": "..." }, "contentType": "video/mp4", "bodyBytes": 1048576 }
解码后返回 { env, contentType, bodyBytes } 没有 body。 。 。 .
CBOR频道(RFC 8949,可选)
这个信封是CBOR 地图二进制是 本地 CBOR 字节字符串 (主要类型2)- 无基数64税数字 :
map(2) {
"env" => map(...) ; the opaque envelope
"body" => bytes(N) ; major type 2, untagged -- the opaque body
}
; "contentType" => text ; present when set
字节字符串未标记( 标题) 0x40 | len),所以是一个平地字节
字符串,不是标记/类型阵列值.
二元框架歧视者(1字节)
在二进制模式( CBOR) 中, 调用者可以将信封信息与原始不透明连接开 块(如批量转移)。 单人 首字节 区分它们和它们 在任何解码前都解决了,所以接收者从来不是试验方:
歧视登记 (由此软件包所拥有; 编组协议必须
)),在其中停留. 此编码器只释放和消耗 0x01编号 :0x02;其余为:
保留这样高的地层可以添加帧而无需再重新指派这两个.
| 字节 | 类 | 含义 |
|---|---|---|
0x00 | 保留 | 永远不要发射 |
0x01 | 信封 | 编码 { env, body? } |
0x02 | 块 | 原始/不公开字节,从未解码 |
0x03..0x0f | 控制 | 为协议控制框架保留 |
0x10..0xff | 应用程序 | 应用程序定义 |
frameType(bytes) 路径中只有此编码器拥有的两个字节( 返回)
'envelope'编号 :'chunk'掷出 BAD_FRAME (否则). frameClass(byte)
对照登记册对任意字节进行分类(reserved编号 :envelope编号 :chunk编号 :
control编号 :application)为高层自有路由.
import { framed, frameType, encodeChunk, decodeChunk } from '@claudewerk/envelope-codec';
const codec = framed(cborCodec()); // encode() now prepends 0x01
const wire = codec.encode({ env, body });
// receiver: route on the discriminator, THEN decode -- no trial parse
switch (frameType(wire)) {
case 'envelope': return codec.decode(wire);
case 'chunk': return handleRaw(decodeChunk(wire));
}
设计说明:Spec说"把它作为选择".
frameType()+ 键framed()是一个刻意的改进 -- -- 歧视者必须解决 解码前的接收器,解码时间选项无法做到这一点 已经承诺进行剖析。 因此,跑步是一个单独的,预解码步骤.
硬化解码( 不信任输入)
每条解码路径都会执行限制,并将任何失败变为已键入
CodecError (从不漏出一掷一吊):
| 警卫 | 贾森 | 边境保护局 | CodecError.code |
|---|---|---|---|
| 解码前的大小封顶 | ✓ | ✓ | TOO_LARGE |
| 最大筑巢深度 | ✓ | ✓ | TOO_DEEP |
| 每集最大项 | ✓ | ✓ | TOO_MANY_ITEMS |
| 重复密钥被拒绝 | ✓ | ✓ | DUP_KEY |
| 无限期拒绝 | - 说吧 | ✓ | INDEFINITE_LENGTH |
| 标记被拒绝( 无类 ) | - 说吧 | ✓ | UNSUPPORTED |
| 输入格式错误 | ✓ | ✓ | MALFORMED |
CBOR输入在结构上被手写通行证所扫描(cbor-scan.js在此之前
cbor-x 所以任何攻击者控制的形状 都不会被瞬间改变
标记地图到类。 JSON是扫描之前 JSON.parse 捕捉深度和
复制密钥, 哪个 JSON.parse 一个人不能.
默认 : maxBytes = 16 MiB, (中文(简体) ), maxDepth = 64, (中文(简体) ), maxItems = 100000通过
页:1 limits 编号 : maxBytes 选项.
通过模式
支持框架为 ARBIRARY 字节的运输( 尚未)
{ env, body }),启用 passthrough。 。 。 . encode() 并接受一个原始的
Uint8Array 把它包成一个默认的封口,所以不要
每个相框必须是一个信封才能流出解码器.
const codec = cborCodec({ passthrough: true }); // or an env object: { passthrough: { src: 'transport' } }
codec.encode(new Uint8Array([1, 2, 3])); // -> encodes { env: {}, body: <those bytes> }
codec.encode({ env: { k: 1 }, body }); // normal messages still work
const { env, body } = codec.decode(wire); // body is the exact opaque frame back
无 passthrough,将原始字节输入 encode() 是一个 CodecError
(单位:千美元)MALFORMED() -- 需要发送信息.
谈判
优先排序和版本意识,所以两个对等者与 不同当地 订单仍然同意 不往返。 。 。 .
negotiate(ours, theirs) // -> 'json' | 'cbor'
- 光学
PREFERENCE = ['cbor', 'json'](最受欢迎的先) 此软件包并导出. - 广告编码是道具
name[/version](例如:.'cbor/1'; 匹配为 以 名称。 。 。 . - 结果 = 首名
PREFERENCE双方广告, 提供量cbor只有在cbor-x这里有 oper dep . - JSON是永远可以利用的后退.
negotiate(['json', 'cbor'], ['cbor', 'json']) // -> 'cbor' (order-independent)
negotiate(['cbor/1'], ['cbor/2']) // -> 'cbor' (version-agnostic match)
negotiate(['cbor'], ['json']) // -> 'json'
日志
可注射 Logger (单位:千美元)debug/info/warn/error;默认沉默. consoleLogger
财务报告和审定财务报表 pinoLogger() (懒惰,可选) pino页:1 将任何对象与
四种方法为: { log }。 。 。 .
许可证
麻省理工学院