EdgeAIG's picture
download
raw
6.68 kB
/**
* Encodes and decodes MessagePack frames in Effect channels.
*
* MessagePack is a compact binary serialization format for protocols and
* storage layers that expect bytes instead of JSON text, such as RPC
* transports, socket streams, caches, or database columns. This module includes
* raw channel helpers for values whose shape is already agreed on, and
* schema-based helpers for validating and transforming values at the boundary.
*
* @since 4.0.0
*/
import { Packr, Unpackr } from "msgpackr";
import * as Msgpackr from "msgpackr";
import * as Arr from "../../Array.js";
import * as Channel from "../../Channel.js";
import * as ChannelSchema from "../../ChannelSchema.js";
import * as Data from "../../Data.js";
import * as Effect from "../../Effect.js";
import { dual } from "../../Function.js";
import * as Option from "../../Option.js";
import * as Predicate from "../../Predicate.js";
import * as Schema from "../../Schema.js";
import * as SchemaIssue from "../../SchemaIssue.js";
import * as SchemaTransformation from "../../SchemaTransformation.js";
const MsgPackErrorTypeId = "~effect/encoding/MsgPack/MsgPackError";
/**
* Error raised when MessagePack encoding or decoding fails.
*
* **Details**
*
* The `kind` field identifies whether the failure happened while packing or
* unpacking, and `cause` preserves the original error.
*
* @category errors
* @since 4.0.0
*/
export class MsgPackError extends /*#__PURE__*/Data.TaggedError("MsgPackError") {
/**
* Marks this value as a MessagePack encoding or decoding error for runtime guards.
*
* @since 4.0.0
*/
[MsgPackErrorTypeId] = MsgPackErrorTypeId;
/**
* Uses the failed MessagePack operation as the public message.
*
* @since 4.0.0
*/
get message() {
return this.kind;
}
}
/**
* Creates a channel that encodes non-empty chunks of values as MessagePack byte
* arrays.
*
* **Details**
*
* The channel fails with `MsgPackError` when any value cannot be packed.
*
* @category constructors
* @since 4.0.0
*/
export const encode = () => Channel.fromTransform((upstream, _scope) => Effect.sync(() => {
const packr = new Packr();
return Effect.flatMap(upstream, chunk => {
try {
return Effect.succeed(Arr.map(chunk, item => packr.pack(item)));
} catch (cause) {
return Effect.fail(new MsgPackError({
kind: "Pack",
cause
}));
}
});
}));
/**
* Creates a MessagePack encoder channel for values of a schema.
*
* **Details**
*
* Values are first encoded with the schema and then packed as MessagePack bytes,
* so the channel can fail with either schema errors or `MsgPackError`.
*
* @category constructors
* @since 4.0.0
*/
export const encodeSchema = schema => () => Channel.pipeTo(ChannelSchema.encode(schema)(), encode());
/**
* Creates a channel that decodes MessagePack byte chunks into values.
*
* **Details**
*
* Incomplete frames are buffered across chunks, and invalid MessagePack data
* fails with `MsgPackError`.
*
* @category constructors
* @since 4.0.0
*/
export const decode = () => Channel.fromTransform((upstream, _scope) => Effect.sync(() => {
const unpackr = new Unpackr();
let incomplete = undefined;
return Effect.flatMap(upstream, function loop(chunk) {
const out = Arr.empty();
for (let i = 0; i < chunk.length; i++) {
let buf = chunk[i];
if (incomplete !== undefined) {
const prev = buf;
buf = new Uint8Array(incomplete.length + buf.length);
buf.set(incomplete);
buf.set(prev, incomplete.length);
incomplete = undefined;
}
try {
out.push(...unpackr.unpackMultiple(buf));
} catch (cause) {
const error = cause;
if (error.incomplete) {
incomplete = buf.subarray(error.lastPosition);
if (error.values) {
out.push(...error.values);
}
} else {
return Effect.fail(new MsgPackError({
kind: "Unpack",
cause
}));
}
}
}
return Arr.isReadonlyArrayNonEmpty(out) ? Effect.succeed(out) : Effect.flatMap(upstream, loop);
});
}));
/**
* Creates a MessagePack decoder channel for values of a schema.
*
* **Details**
*
* The channel unpacks bytes into unknown values and then decodes each value with
* the schema.
*
* @category constructors
* @since 4.0.0
*/
export const decodeSchema = schema => () => Channel.pipeTo(decode(), ChannelSchema.decodeUnknown(schema)());
/**
* Wraps a bidirectional byte channel with MessagePack encoding and decoding.
*
* **Details**
*
* Outgoing values are packed as MessagePack bytes before reaching the wrapped
* channel, and incoming bytes are unpacked into values.
*
* @category combinators
* @since 4.0.0
*/
export const duplex = self => encode().pipe(Channel.pipeTo(self), Channel.pipeTo(decode()));
/**
* Wraps a bidirectional byte channel with schema-aware MessagePack encoding and
* decoding.
*
* **Details**
*
* Values sent to the wrapped channel are encoded with `inputSchema` and packed
* as MessagePack bytes; bytes received from it are unpacked and decoded with
* `outputSchema`.
*
* @category combinators
* @since 4.0.0
*/
export const duplexSchema = /*#__PURE__*/dual(2, (self, options) => ChannelSchema.duplexUnknown(duplex(self), options));
/**
* Schema for decoding MessagePack bytes into values and encoding values back to
* MessagePack bytes.
*
* **Details**
*
* MessagePack codec failures are converted to `InvalidValue` schema issues.
*
* @category schemas
* @since 4.0.0
*/
export const transformation = /*#__PURE__*/SchemaTransformation.transformOrFail({
decode(e, _options) {
try {
return Effect.succeed(Msgpackr.decode(e));
} catch (cause) {
return Effect.fail(new SchemaIssue.InvalidValue(Option.some(e), {
message: Predicate.hasProperty(cause, "message") ? String(cause.message) : String(cause)
}));
}
},
encode(t, _options) {
try {
return Effect.succeed(Msgpackr.encode(t));
} catch (cause) {
return Effect.fail(new SchemaIssue.InvalidValue(Option.some(t), {
message: Predicate.hasProperty(cause, "message") ? String(cause.message) : String(cause)
}));
}
}
});
/**
* Builds a schema that stores values as MessagePack bytes.
*
* **Details**
*
* The resulting schema decodes `Uint8Array` payloads with MessagePack and the
* provided schema, and encodes values back to MessagePack bytes.
*
* @category schemas
* @since 4.0.0
*/
export const schema = schema => Schema.Uint8Array.pipe(Schema.decodeTo(schema, transformation));
//# sourceMappingURL=Msgpack.js.map

Xet Storage Details

Size:
6.68 kB
·
Xet hash:
05bba9b8473862e36dc3a6486de5284ff38c8ef098ac93e99d8540cbd7fd1815

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.