@sachitv/avro-typescript 0.4.2 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/avro_reader_sync.d.ts +48 -0
- package/esm/avro_reader_sync.js +79 -0
- package/esm/avro_writer_sync.d.ts +28 -0
- package/esm/avro_writer_sync.js +63 -0
- package/esm/internal/collections/circular_buffer.d.ts +4 -3
- package/esm/internal/collections/circular_buffer.js +8 -6
- package/esm/mod.d.ts +17 -0
- package/esm/mod.js +11 -0
- package/esm/schemas/base_type.d.ts +8 -0
- package/esm/schemas/base_type.js +21 -0
- package/esm/schemas/complex/array_type.d.ts +31 -10
- package/esm/schemas/complex/array_type.js +129 -39
- package/esm/schemas/complex/enum_type.d.ts +24 -7
- package/esm/schemas/complex/enum_type.js +61 -15
- package/esm/schemas/complex/fixed_type.d.ts +27 -12
- package/esm/schemas/complex/fixed_type.js +40 -27
- package/esm/schemas/complex/map_type.d.ts +31 -10
- package/esm/schemas/complex/map_type.js +88 -47
- package/esm/schemas/complex/named_type.d.ts +1 -1
- package/esm/schemas/complex/named_type.js +2 -2
- package/esm/schemas/complex/record_field.d.ts +62 -0
- package/esm/schemas/complex/record_field.js +112 -0
- package/esm/schemas/complex/record_resolver.d.ts +45 -0
- package/esm/schemas/complex/record_resolver.js +92 -0
- package/esm/schemas/complex/record_type.d.ts +45 -70
- package/esm/schemas/complex/record_type.js +158 -213
- package/esm/schemas/complex/record_writer_cache.d.ts +44 -0
- package/esm/schemas/complex/record_writer_cache.js +141 -0
- package/esm/schemas/complex/record_writer_strategy.d.ts +123 -0
- package/esm/schemas/complex/record_writer_strategy.js +309 -0
- package/esm/schemas/complex/union_type.d.ts +23 -11
- package/esm/schemas/complex/union_type.js +77 -29
- package/esm/schemas/logical/decimal_logical_type.d.ts +1 -1
- package/esm/schemas/logical/decimal_logical_type.js +2 -2
- package/esm/schemas/logical/duration_logical_type.d.ts +1 -1
- package/esm/schemas/logical/duration_logical_type.js +2 -2
- package/esm/schemas/logical/logical_type.d.ts +27 -9
- package/esm/schemas/logical/logical_type.js +50 -17
- package/esm/schemas/logical/temporal_logical_types.d.ts +9 -9
- package/esm/schemas/logical/temporal_logical_types.js +18 -18
- package/esm/schemas/logical/uuid_logical_type.d.ts +1 -1
- package/esm/schemas/logical/uuid_logical_type.js +2 -2
- package/esm/schemas/primitive/boolean_type.d.ts +15 -4
- package/esm/schemas/primitive/boolean_type.js +22 -7
- package/esm/schemas/primitive/bytes_type.d.ts +16 -5
- package/esm/schemas/primitive/bytes_type.js +31 -16
- package/esm/schemas/primitive/double_type.d.ts +13 -2
- package/esm/schemas/primitive/double_type.js +34 -5
- package/esm/schemas/primitive/fixed_size_base_type.d.ts +11 -7
- package/esm/schemas/primitive/fixed_size_base_type.js +14 -14
- package/esm/schemas/primitive/float_type.d.ts +11 -2
- package/esm/schemas/primitive/float_type.js +26 -5
- package/esm/schemas/primitive/int_type.d.ts +17 -6
- package/esm/schemas/primitive/int_type.js +26 -17
- package/esm/schemas/primitive/long_type.d.ts +16 -5
- package/esm/schemas/primitive/long_type.js +30 -16
- package/esm/schemas/primitive/null_type.d.ts +15 -4
- package/esm/schemas/primitive/null_type.js +20 -7
- package/esm/schemas/primitive/primitive_type.d.ts +2 -0
- package/esm/schemas/primitive/primitive_type.js +4 -0
- package/esm/schemas/primitive/string_type.d.ts +17 -6
- package/esm/schemas/primitive/string_type.js +33 -18
- package/esm/schemas/resolver.d.ts +6 -0
- package/esm/schemas/type.d.ts +64 -4
- package/esm/schemas/type.js +97 -0
- package/esm/serialization/avro_file_parser_sync.d.ts +34 -0
- package/esm/serialization/avro_file_parser_sync.js +160 -0
- package/esm/serialization/avro_file_writer_sync.d.ts +47 -0
- package/esm/serialization/avro_file_writer_sync.js +211 -0
- package/esm/serialization/buffers/blob_readable_buffer.d.ts +4 -3
- package/esm/serialization/buffers/blob_readable_buffer.js +20 -6
- package/esm/serialization/buffers/buffer.d.ts +6 -1
- package/esm/serialization/buffers/buffer.js +3 -0
- package/esm/serialization/buffers/buffer_error.d.ts +28 -0
- package/esm/serialization/buffers/buffer_error.js +70 -0
- package/esm/serialization/buffers/buffer_sync.d.ts +51 -0
- package/esm/serialization/buffers/buffer_sync.js +4 -0
- package/esm/serialization/buffers/in_memory_buffer.d.ts +1 -0
- package/esm/serialization/buffers/in_memory_buffer.js +7 -5
- package/esm/serialization/buffers/in_memory_buffer_sync.d.ts +133 -0
- package/esm/serialization/buffers/in_memory_buffer_sync.js +259 -0
- package/esm/serialization/counting_writable_tap.d.ts +45 -0
- package/esm/serialization/counting_writable_tap.js +90 -0
- package/esm/serialization/counting_writable_tap_sync.d.ts +46 -0
- package/esm/serialization/counting_writable_tap_sync.js +87 -0
- package/esm/serialization/decoders/decoder_null_sync.d.ts +12 -0
- package/esm/serialization/decoders/decoder_null_sync.js +13 -0
- package/esm/serialization/decoders/decoder_sync.d.ts +15 -0
- package/esm/serialization/decoders/decoder_sync.js +1 -0
- package/esm/serialization/encoders/encoder_null_sync.d.ts +12 -0
- package/esm/serialization/encoders/encoder_null_sync.js +13 -0
- package/esm/serialization/encoders/encoder_sync.d.ts +15 -0
- package/esm/serialization/encoders/encoder_sync.js +1 -0
- package/esm/serialization/streams/fixed_size_stream_readable_buffer_adapter.d.ts +3 -2
- package/esm/serialization/streams/fixed_size_stream_readable_buffer_adapter.js +19 -9
- package/esm/serialization/streams/fixed_size_stream_reader_sync.d.ts +25 -0
- package/esm/serialization/streams/fixed_size_stream_reader_sync.js +63 -0
- package/esm/serialization/streams/fixed_size_stream_writer_sync.d.ts +45 -0
- package/esm/serialization/streams/fixed_size_stream_writer_sync.js +98 -0
- package/esm/serialization/streams/forward_only_stream_readable_buffer_adapter.d.ts +5 -3
- package/esm/serialization/streams/forward_only_stream_readable_buffer_adapter.js +18 -8
- package/esm/serialization/streams/stream_readable_buffer_adapter.d.ts +3 -2
- package/esm/serialization/streams/stream_readable_buffer_adapter.js +19 -6
- package/esm/serialization/streams/stream_readable_buffer_adapter_sync.d.ts +36 -0
- package/esm/serialization/streams/stream_readable_buffer_adapter_sync.js +93 -0
- package/esm/serialization/streams/stream_writable_buffer_adapter_sync.d.ts +45 -0
- package/esm/serialization/streams/stream_writable_buffer_adapter_sync.js +78 -0
- package/esm/serialization/streams/streams_sync.d.ts +36 -0
- package/esm/serialization/streams/streams_sync.js +4 -0
- package/esm/serialization/tap.d.ts +15 -32
- package/esm/serialization/tap.js +45 -134
- package/esm/serialization/tap_sync.d.ts +240 -0
- package/esm/serialization/tap_sync.js +545 -0
- package/esm/serialization/text_encoding.d.ts +16 -0
- package/esm/serialization/text_encoding.js +48 -1
- package/esm/type/create_type.d.ts +20 -0
- package/esm/type/create_type.js +49 -28
- package/package.json +1 -1
- package/esm/serialization/manipulate_bytes.d.ts +0 -6
- package/esm/serialization/manipulate_bytes.js +0 -13
- package/esm/serialization/read_uint_le.d.ts +0 -4
- package/esm/serialization/read_uint_le.js +0 -14
package/esm/schemas/type.js
CHANGED
|
@@ -1,6 +1,103 @@
|
|
|
1
|
+
import { WritableTap, } from "../serialization/tap.js";
|
|
2
|
+
import { SyncWritableTap, } from "../serialization/tap_sync.js";
|
|
3
|
+
import { CountingWritableTap } from "../serialization/counting_writable_tap.js";
|
|
4
|
+
import { SyncCountingWritableTap } from "../serialization/counting_writable_tap_sync.js";
|
|
5
|
+
import { throwInvalidError } from "./error.js";
|
|
1
6
|
/**
|
|
2
7
|
* Pure abstract base class for all Avro schema types.
|
|
3
8
|
* Provides the common interface for serialization, deserialization, validation, and cloning.
|
|
4
9
|
*/
|
|
5
10
|
export class Type {
|
|
11
|
+
/** Creates a new Type instance. */
|
|
12
|
+
constructor(validate = true) {
|
|
13
|
+
/** Controls whether write operations validate values before serialization. */
|
|
14
|
+
Object.defineProperty(this, "validateWrites", {
|
|
15
|
+
enumerable: true,
|
|
16
|
+
configurable: true,
|
|
17
|
+
writable: true,
|
|
18
|
+
value: void 0
|
|
19
|
+
});
|
|
20
|
+
this.validateWrites = validate;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Serializes a value into an ArrayBuffer using the schema.
|
|
24
|
+
* @param value The value to serialize.
|
|
25
|
+
* @returns The serialized ArrayBuffer.
|
|
26
|
+
*/
|
|
27
|
+
async toBuffer(value) {
|
|
28
|
+
if (this.validateWrites) {
|
|
29
|
+
this.check(value, throwInvalidError, []);
|
|
30
|
+
}
|
|
31
|
+
const sizeHint = this.byteLength(value);
|
|
32
|
+
if (sizeHint !== undefined) {
|
|
33
|
+
const buffer = new ArrayBuffer(assertValidSize(sizeHint));
|
|
34
|
+
const tap = new WritableTap(buffer);
|
|
35
|
+
await this.writeUnchecked(tap, value);
|
|
36
|
+
return buffer;
|
|
37
|
+
}
|
|
38
|
+
const countingTap = new CountingWritableTap();
|
|
39
|
+
await this.writeUnchecked(countingTap, value);
|
|
40
|
+
const buffer = new ArrayBuffer(countingTap.getPos());
|
|
41
|
+
const tap = new WritableTap(buffer);
|
|
42
|
+
await this.writeUnchecked(tap, value);
|
|
43
|
+
return buffer;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Writes a value to the tap. Must be implemented by subclasses.
|
|
47
|
+
* @param tap The tap to write to.
|
|
48
|
+
* @param value The value to write.
|
|
49
|
+
*/
|
|
50
|
+
async write(tap, value) {
|
|
51
|
+
if (this.validateWrites) {
|
|
52
|
+
this.check(value, throwInvalidError, []);
|
|
53
|
+
}
|
|
54
|
+
await this.writeUnchecked(tap, value);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Serializes a value into an ArrayBuffer synchronously using the schema.
|
|
58
|
+
* @param value The value to serialize.
|
|
59
|
+
* @returns The serialized ArrayBuffer.
|
|
60
|
+
*/
|
|
61
|
+
toSyncBuffer(value) {
|
|
62
|
+
if (this.validateWrites) {
|
|
63
|
+
this.check(value, throwInvalidError, []);
|
|
64
|
+
}
|
|
65
|
+
const sizeHint = this.byteLength(value);
|
|
66
|
+
if (sizeHint !== undefined) {
|
|
67
|
+
const buffer = new ArrayBuffer(assertValidSize(sizeHint));
|
|
68
|
+
const tap = new SyncWritableTap(buffer);
|
|
69
|
+
this.writeSyncUnchecked(tap, value);
|
|
70
|
+
return buffer;
|
|
71
|
+
}
|
|
72
|
+
const countingTap = new SyncCountingWritableTap();
|
|
73
|
+
this.writeSyncUnchecked(countingTap, value);
|
|
74
|
+
const buffer = new ArrayBuffer(countingTap.getPos());
|
|
75
|
+
const tap = new SyncWritableTap(buffer);
|
|
76
|
+
this.writeSyncUnchecked(tap, value);
|
|
77
|
+
return buffer;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Writes a value to the sync tap. Must be implemented by subclasses.
|
|
81
|
+
* @param tap The sync tap to write to.
|
|
82
|
+
* @param value The value to write.
|
|
83
|
+
*/
|
|
84
|
+
writeSync(tap, value) {
|
|
85
|
+
if (this.validateWrites) {
|
|
86
|
+
this.check(value, throwInvalidError, []);
|
|
87
|
+
}
|
|
88
|
+
this.writeSyncUnchecked(tap, value);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Returns the encoded byte length for the value when it is cheap to compute.
|
|
92
|
+
* Override in types with fixed or easily derived sizes to skip counting taps.
|
|
93
|
+
*/
|
|
94
|
+
byteLength(_value) {
|
|
95
|
+
return undefined;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function assertValidSize(size) {
|
|
99
|
+
if (!Number.isFinite(size) || !Number.isInteger(size) || size < 0) {
|
|
100
|
+
throw new RangeError(`Invalid byte length: ${size}`);
|
|
101
|
+
}
|
|
102
|
+
return size;
|
|
6
103
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { ParsedAvroHeader } from "./avro_file_parser.js";
|
|
2
|
+
import type { ISyncReadable } from "./buffers/buffer_sync.js";
|
|
3
|
+
import type { SyncDecoderRegistry } from "./decoders/decoder_sync.js";
|
|
4
|
+
/**
|
|
5
|
+
* Options for configuring the synchronous Avro file parser.
|
|
6
|
+
*/
|
|
7
|
+
export interface SyncAvroFileParserOptions {
|
|
8
|
+
/** Optional reader schema used when resolving writer data to a different schema. */
|
|
9
|
+
readerSchema?: unknown;
|
|
10
|
+
/** Custom codec decoders. Cannot include "null" as it is built-in. */
|
|
11
|
+
decoders?: SyncDecoderRegistry;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Parser for Avro object container files that operates purely synchronously.
|
|
15
|
+
* It mirrors {@link AvroFileParser} but leverages {@link SyncReadableTap} and
|
|
16
|
+
* {@link ISyncReadable} buffers so callers can avoid async control flow.
|
|
17
|
+
*/
|
|
18
|
+
export declare class SyncAvroFileParser {
|
|
19
|
+
#private;
|
|
20
|
+
/**
|
|
21
|
+
* Creates a new synchronous Avro file parser.
|
|
22
|
+
* @param buffer The readable buffer containing the Avro container.
|
|
23
|
+
* @param options Configuration options including reader schema and decoders.
|
|
24
|
+
*/
|
|
25
|
+
constructor(buffer: ISyncReadable, options?: SyncAvroFileParserOptions);
|
|
26
|
+
/**
|
|
27
|
+
* Returns the parsed Avro header. Header parsing happens at most once.
|
|
28
|
+
*/
|
|
29
|
+
getHeader(): ParsedAvroHeader;
|
|
30
|
+
/**
|
|
31
|
+
* Iterates synchronously over every record contained in the Avro file.
|
|
32
|
+
*/
|
|
33
|
+
iterRecords(): IterableIterator<unknown>;
|
|
34
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
2
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
3
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
4
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
5
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
6
|
+
};
|
|
7
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
8
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
9
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
|
+
};
|
|
12
|
+
var _SyncAvroFileParser_instances, _SyncAvroFileParser_buffer, _SyncAvroFileParser_header, _SyncAvroFileParser_headerTap, _SyncAvroFileParser_readerSchema, _SyncAvroFileParser_readerType, _SyncAvroFileParser_resolver, _SyncAvroFileParser_customDecoders, _SyncAvroFileParser_builtInDecoders, _SyncAvroFileParser_parseHeader, _SyncAvroFileParser_getResolver, _SyncAvroFileParser_createReaderType, _SyncAvroFileParser_getDecoder;
|
|
13
|
+
import { createType } from "../type/create_type.js";
|
|
14
|
+
import { Type } from "../schemas/type.js";
|
|
15
|
+
import { BLOCK_TYPE, HEADER_TYPE, MAGIC_BYTES } from "./avro_constants.js";
|
|
16
|
+
import { NullDecoderSync } from "./decoders/decoder_null_sync.js";
|
|
17
|
+
import { SyncReadableTap } from "./tap_sync.js";
|
|
18
|
+
/**
|
|
19
|
+
* Parser for Avro object container files that operates purely synchronously.
|
|
20
|
+
* It mirrors {@link AvroFileParser} but leverages {@link SyncReadableTap} and
|
|
21
|
+
* {@link ISyncReadable} buffers so callers can avoid async control flow.
|
|
22
|
+
*/
|
|
23
|
+
export class SyncAvroFileParser {
|
|
24
|
+
/**
|
|
25
|
+
* Creates a new synchronous Avro file parser.
|
|
26
|
+
* @param buffer The readable buffer containing the Avro container.
|
|
27
|
+
* @param options Configuration options including reader schema and decoders.
|
|
28
|
+
*/
|
|
29
|
+
constructor(buffer, options) {
|
|
30
|
+
_SyncAvroFileParser_instances.add(this);
|
|
31
|
+
_SyncAvroFileParser_buffer.set(this, void 0);
|
|
32
|
+
_SyncAvroFileParser_header.set(this, void 0);
|
|
33
|
+
_SyncAvroFileParser_headerTap.set(this, void 0);
|
|
34
|
+
_SyncAvroFileParser_readerSchema.set(this, void 0);
|
|
35
|
+
_SyncAvroFileParser_readerType.set(this, void 0);
|
|
36
|
+
_SyncAvroFileParser_resolver.set(this, void 0);
|
|
37
|
+
_SyncAvroFileParser_customDecoders.set(this, void 0);
|
|
38
|
+
_SyncAvroFileParser_builtInDecoders.set(this, void 0);
|
|
39
|
+
__classPrivateFieldSet(this, _SyncAvroFileParser_buffer, buffer, "f");
|
|
40
|
+
__classPrivateFieldSet(this, _SyncAvroFileParser_readerSchema, options?.readerSchema, "f");
|
|
41
|
+
__classPrivateFieldSet(this, _SyncAvroFileParser_builtInDecoders, {
|
|
42
|
+
"null": new NullDecoderSync(),
|
|
43
|
+
}, "f");
|
|
44
|
+
const custom = options?.decoders ?? {};
|
|
45
|
+
for (const codec of Object.keys(custom)) {
|
|
46
|
+
if (codec in __classPrivateFieldGet(this, _SyncAvroFileParser_builtInDecoders, "f")) {
|
|
47
|
+
throw new Error(`Cannot override built-in decoder for codec: ${codec}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
__classPrivateFieldSet(this, _SyncAvroFileParser_customDecoders, { ...custom }, "f");
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Returns the parsed Avro header. Header parsing happens at most once.
|
|
54
|
+
*/
|
|
55
|
+
getHeader() {
|
|
56
|
+
const header = __classPrivateFieldGet(this, _SyncAvroFileParser_instances, "m", _SyncAvroFileParser_parseHeader).call(this);
|
|
57
|
+
return {
|
|
58
|
+
magic: header.magic,
|
|
59
|
+
meta: header.meta,
|
|
60
|
+
sync: header.sync,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Iterates synchronously over every record contained in the Avro file.
|
|
65
|
+
*/
|
|
66
|
+
*iterRecords() {
|
|
67
|
+
const header = __classPrivateFieldGet(this, _SyncAvroFileParser_instances, "m", _SyncAvroFileParser_parseHeader).call(this);
|
|
68
|
+
const { schemaType, meta } = header;
|
|
69
|
+
const resolver = __classPrivateFieldGet(this, _SyncAvroFileParser_instances, "m", _SyncAvroFileParser_getResolver).call(this, schemaType);
|
|
70
|
+
const codecBytes = meta.get("avro.codec");
|
|
71
|
+
const codec = (() => {
|
|
72
|
+
if (codecBytes === undefined) {
|
|
73
|
+
return "null";
|
|
74
|
+
}
|
|
75
|
+
const decoded = new TextDecoder().decode(codecBytes);
|
|
76
|
+
return decoded.length === 0 ? "null" : decoded;
|
|
77
|
+
})();
|
|
78
|
+
const decoder = __classPrivateFieldGet(this, _SyncAvroFileParser_instances, "m", _SyncAvroFileParser_getDecoder).call(this, codec);
|
|
79
|
+
const tap = __classPrivateFieldGet(this, _SyncAvroFileParser_headerTap, "f");
|
|
80
|
+
while (tap.canReadMore()) {
|
|
81
|
+
const block = BLOCK_TYPE.readSync(tap);
|
|
82
|
+
const decompressed = decoder.decode(block.data);
|
|
83
|
+
const arrayBuffer = new ArrayBuffer(decompressed.length);
|
|
84
|
+
new Uint8Array(arrayBuffer).set(decompressed);
|
|
85
|
+
const recordTap = new SyncReadableTap(arrayBuffer);
|
|
86
|
+
for (let i = 0n; i < block.count; i += 1n) {
|
|
87
|
+
const value = resolver
|
|
88
|
+
? resolver.readSync(recordTap)
|
|
89
|
+
: schemaType.readSync(recordTap);
|
|
90
|
+
yield value;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
_SyncAvroFileParser_buffer = new WeakMap(), _SyncAvroFileParser_header = new WeakMap(), _SyncAvroFileParser_headerTap = new WeakMap(), _SyncAvroFileParser_readerSchema = new WeakMap(), _SyncAvroFileParser_readerType = new WeakMap(), _SyncAvroFileParser_resolver = new WeakMap(), _SyncAvroFileParser_customDecoders = new WeakMap(), _SyncAvroFileParser_builtInDecoders = new WeakMap(), _SyncAvroFileParser_instances = new WeakSet(), _SyncAvroFileParser_parseHeader = function _SyncAvroFileParser_parseHeader() {
|
|
96
|
+
if (__classPrivateFieldGet(this, _SyncAvroFileParser_header, "f")) {
|
|
97
|
+
return __classPrivateFieldGet(this, _SyncAvroFileParser_header, "f");
|
|
98
|
+
}
|
|
99
|
+
const tap = new SyncReadableTap(__classPrivateFieldGet(this, _SyncAvroFileParser_buffer, "f"));
|
|
100
|
+
const header = HEADER_TYPE.readSync(tap);
|
|
101
|
+
const magic = header.magic;
|
|
102
|
+
for (let i = 0; i < MAGIC_BYTES.length; i++) {
|
|
103
|
+
if (magic[i] !== MAGIC_BYTES[i]) {
|
|
104
|
+
throw new Error("Invalid AVRO file: incorrect magic bytes");
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const meta = header.meta;
|
|
108
|
+
const schemaJson = meta.get("avro.schema");
|
|
109
|
+
if (!schemaJson) {
|
|
110
|
+
throw new Error("AVRO schema not found in metadata");
|
|
111
|
+
}
|
|
112
|
+
const schemaStr = new TextDecoder().decode(schemaJson);
|
|
113
|
+
const schemaType = createType(JSON.parse(schemaStr));
|
|
114
|
+
const codec = meta.get("avro.codec");
|
|
115
|
+
if (codec && codec.length > 0) {
|
|
116
|
+
const codecStr = new TextDecoder().decode(codec);
|
|
117
|
+
__classPrivateFieldGet(this, _SyncAvroFileParser_instances, "m", _SyncAvroFileParser_getDecoder).call(this, codecStr);
|
|
118
|
+
}
|
|
119
|
+
const sync = header.sync;
|
|
120
|
+
__classPrivateFieldSet(this, _SyncAvroFileParser_header, {
|
|
121
|
+
magic,
|
|
122
|
+
meta,
|
|
123
|
+
sync,
|
|
124
|
+
schemaType,
|
|
125
|
+
}, "f");
|
|
126
|
+
__classPrivateFieldSet(this, _SyncAvroFileParser_headerTap, tap, "f");
|
|
127
|
+
return __classPrivateFieldGet(this, _SyncAvroFileParser_header, "f");
|
|
128
|
+
}, _SyncAvroFileParser_getResolver = function _SyncAvroFileParser_getResolver(writerType) {
|
|
129
|
+
if (__classPrivateFieldGet(this, _SyncAvroFileParser_readerSchema, "f") === undefined || __classPrivateFieldGet(this, _SyncAvroFileParser_readerSchema, "f") === null) {
|
|
130
|
+
return undefined;
|
|
131
|
+
}
|
|
132
|
+
if (!__classPrivateFieldGet(this, _SyncAvroFileParser_readerType, "f")) {
|
|
133
|
+
__classPrivateFieldSet(this, _SyncAvroFileParser_readerType, __classPrivateFieldGet(this, _SyncAvroFileParser_instances, "m", _SyncAvroFileParser_createReaderType).call(this, __classPrivateFieldGet(this, _SyncAvroFileParser_readerSchema, "f")), "f");
|
|
134
|
+
}
|
|
135
|
+
if (!__classPrivateFieldGet(this, _SyncAvroFileParser_resolver, "f")) {
|
|
136
|
+
__classPrivateFieldSet(this, _SyncAvroFileParser_resolver, __classPrivateFieldGet(this, _SyncAvroFileParser_readerType, "f").createResolver(writerType), "f");
|
|
137
|
+
}
|
|
138
|
+
return __classPrivateFieldGet(this, _SyncAvroFileParser_resolver, "f");
|
|
139
|
+
}, _SyncAvroFileParser_createReaderType = function _SyncAvroFileParser_createReaderType(schema) {
|
|
140
|
+
if (schema instanceof Type) {
|
|
141
|
+
return schema;
|
|
142
|
+
}
|
|
143
|
+
if (typeof schema === "string") {
|
|
144
|
+
const trimmed = schema.trim();
|
|
145
|
+
if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
|
|
146
|
+
const parsed = JSON.parse(trimmed);
|
|
147
|
+
return createType(parsed);
|
|
148
|
+
}
|
|
149
|
+
return createType(schema);
|
|
150
|
+
}
|
|
151
|
+
return createType(schema);
|
|
152
|
+
}, _SyncAvroFileParser_getDecoder = function _SyncAvroFileParser_getDecoder(codec) {
|
|
153
|
+
if (codec in __classPrivateFieldGet(this, _SyncAvroFileParser_builtInDecoders, "f")) {
|
|
154
|
+
return __classPrivateFieldGet(this, _SyncAvroFileParser_builtInDecoders, "f")[codec];
|
|
155
|
+
}
|
|
156
|
+
if (codec in __classPrivateFieldGet(this, _SyncAvroFileParser_customDecoders, "f")) {
|
|
157
|
+
return __classPrivateFieldGet(this, _SyncAvroFileParser_customDecoders, "f")[codec];
|
|
158
|
+
}
|
|
159
|
+
throw new Error(`Unsupported codec: ${codec}. Provide a custom decoder.`);
|
|
160
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { type SchemaLike } from "../type/create_type.js";
|
|
2
|
+
import type { MetadataInit } from "./avro_file_writer.js";
|
|
3
|
+
import type { ISyncWritable } from "./buffers/buffer_sync.js";
|
|
4
|
+
import type { SyncEncoderRegistry } from "./encoders/encoder_sync.js";
|
|
5
|
+
/**
|
|
6
|
+
* Options accepted by {@link SyncAvroFileWriter}.
|
|
7
|
+
*/
|
|
8
|
+
export interface SyncAvroWriterOptions {
|
|
9
|
+
/** The Avro schema for records to be written. */
|
|
10
|
+
schema: SchemaLike;
|
|
11
|
+
/** The compression codec to use (default: "null"). */
|
|
12
|
+
codec?: string;
|
|
13
|
+
/** Target block size in bytes before flushing (default: 64000). */
|
|
14
|
+
blockSize?: number;
|
|
15
|
+
/** Custom 16-byte sync marker (defaults to random). */
|
|
16
|
+
syncMarker?: Uint8Array;
|
|
17
|
+
/** Additional user metadata to include in the header. */
|
|
18
|
+
metadata?: MetadataInit;
|
|
19
|
+
/** Custom codec encoders. */
|
|
20
|
+
encoders?: SyncEncoderRegistry;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Fully synchronous Avro container file writer.
|
|
24
|
+
* Mirrors {@link AvroFileWriter} but relies on {@link SyncWritableTap} so it
|
|
25
|
+
* can run where async primitives are unavailable.
|
|
26
|
+
*/
|
|
27
|
+
export declare class SyncAvroFileWriter {
|
|
28
|
+
#private;
|
|
29
|
+
/**
|
|
30
|
+
* Creates a new synchronous Avro file writer.
|
|
31
|
+
* @param buffer The writable buffer to write the Avro container to.
|
|
32
|
+
* @param options Configuration options including schema and codec.
|
|
33
|
+
*/
|
|
34
|
+
constructor(buffer: ISyncWritable, options: SyncAvroWriterOptions);
|
|
35
|
+
/**
|
|
36
|
+
* Appends a record to the pending block, flushing when the block size is met.
|
|
37
|
+
*/
|
|
38
|
+
append(record: unknown): void;
|
|
39
|
+
/**
|
|
40
|
+
* Flushes any pending data and prevents further writes.
|
|
41
|
+
*/
|
|
42
|
+
close(): void;
|
|
43
|
+
/**
|
|
44
|
+
* Forces pending data into a block immediately.
|
|
45
|
+
*/
|
|
46
|
+
flushBlock(): void;
|
|
47
|
+
}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
2
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
3
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
4
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
5
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
6
|
+
};
|
|
7
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
8
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
9
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
|
+
};
|
|
12
|
+
var _SyncAvroFileWriter_instances, _SyncAvroFileWriter_tap, _SyncAvroFileWriter_schemaType, _SyncAvroFileWriter_codec, _SyncAvroFileWriter_encoder, _SyncAvroFileWriter_blockSize, _SyncAvroFileWriter_syncMarker, _SyncAvroFileWriter_metadata, _SyncAvroFileWriter_pendingRecords, _SyncAvroFileWriter_pendingBytes, _SyncAvroFileWriter_pendingCount, _SyncAvroFileWriter_headerWritten, _SyncAvroFileWriter_closed, _SyncAvroFileWriter_builtInEncoders, _SyncAvroFileWriter_customEncoders, _SyncAvroFileWriter_ensureOpen, _SyncAvroFileWriter_ensureHeaderWritten, _SyncAvroFileWriter_writeHeader, _SyncAvroFileWriter_validateBlockSize, _SyncAvroFileWriter_initializeSyncMarker, _SyncAvroFileWriter_validateCustomEncoders, _SyncAvroFileWriter_resolveEncoder, _SyncAvroFileWriter_buildMetadata, _SyncAvroFileWriter_assertMetadataKey, _SyncAvroFileWriter_encodeRecord, _SyncAvroFileWriter_combinePending;
|
|
13
|
+
import { createType } from "../type/create_type.js";
|
|
14
|
+
import { BLOCK_TYPE, HEADER_TYPE, MAGIC_BYTES } from "./avro_constants.js";
|
|
15
|
+
import { NullEncoderSync } from "./encoders/encoder_null_sync.js";
|
|
16
|
+
import { encode as encodeString } from "./text_encoding.js";
|
|
17
|
+
import { SyncWritableTap } from "./tap_sync.js";
|
|
18
|
+
const DEFAULT_BLOCK_SIZE_BYTES = 64000;
|
|
19
|
+
const SYNC_MARKER_SIZE = 16;
|
|
20
|
+
const RESERVED_METADATA_KEYS = new Set(["avro.schema", "avro.codec"]);
|
|
21
|
+
/**
|
|
22
|
+
* Fully synchronous Avro container file writer.
|
|
23
|
+
* Mirrors {@link AvroFileWriter} but relies on {@link SyncWritableTap} so it
|
|
24
|
+
* can run where async primitives are unavailable.
|
|
25
|
+
*/
|
|
26
|
+
export class SyncAvroFileWriter {
|
|
27
|
+
/**
|
|
28
|
+
* Creates a new synchronous Avro file writer.
|
|
29
|
+
* @param buffer The writable buffer to write the Avro container to.
|
|
30
|
+
* @param options Configuration options including schema and codec.
|
|
31
|
+
*/
|
|
32
|
+
constructor(buffer, options) {
|
|
33
|
+
_SyncAvroFileWriter_instances.add(this);
|
|
34
|
+
_SyncAvroFileWriter_tap.set(this, void 0);
|
|
35
|
+
_SyncAvroFileWriter_schemaType.set(this, void 0);
|
|
36
|
+
_SyncAvroFileWriter_codec.set(this, void 0);
|
|
37
|
+
_SyncAvroFileWriter_encoder.set(this, void 0);
|
|
38
|
+
_SyncAvroFileWriter_blockSize.set(this, void 0);
|
|
39
|
+
_SyncAvroFileWriter_syncMarker.set(this, void 0);
|
|
40
|
+
_SyncAvroFileWriter_metadata.set(this, void 0);
|
|
41
|
+
_SyncAvroFileWriter_pendingRecords.set(this, []);
|
|
42
|
+
_SyncAvroFileWriter_pendingBytes.set(this, 0);
|
|
43
|
+
_SyncAvroFileWriter_pendingCount.set(this, 0);
|
|
44
|
+
_SyncAvroFileWriter_headerWritten.set(this, false);
|
|
45
|
+
_SyncAvroFileWriter_closed.set(this, false);
|
|
46
|
+
_SyncAvroFileWriter_builtInEncoders.set(this, void 0);
|
|
47
|
+
_SyncAvroFileWriter_customEncoders.set(this, void 0);
|
|
48
|
+
if (!options || !options.schema) {
|
|
49
|
+
throw new Error("Avro writer requires a schema.");
|
|
50
|
+
}
|
|
51
|
+
__classPrivateFieldSet(this, _SyncAvroFileWriter_tap, new SyncWritableTap(buffer), "f");
|
|
52
|
+
__classPrivateFieldSet(this, _SyncAvroFileWriter_schemaType, createType(options.schema), "f");
|
|
53
|
+
__classPrivateFieldSet(this, _SyncAvroFileWriter_codec, options.codec ?? "null", "f");
|
|
54
|
+
__classPrivateFieldSet(this, _SyncAvroFileWriter_blockSize, __classPrivateFieldGet(this, _SyncAvroFileWriter_instances, "m", _SyncAvroFileWriter_validateBlockSize).call(this, options.blockSize), "f");
|
|
55
|
+
__classPrivateFieldSet(this, _SyncAvroFileWriter_syncMarker, __classPrivateFieldGet(this, _SyncAvroFileWriter_instances, "m", _SyncAvroFileWriter_initializeSyncMarker).call(this, options.syncMarker), "f");
|
|
56
|
+
__classPrivateFieldSet(this, _SyncAvroFileWriter_builtInEncoders, {
|
|
57
|
+
"null": new NullEncoderSync(),
|
|
58
|
+
}, "f");
|
|
59
|
+
__classPrivateFieldSet(this, _SyncAvroFileWriter_customEncoders, __classPrivateFieldGet(this, _SyncAvroFileWriter_instances, "m", _SyncAvroFileWriter_validateCustomEncoders).call(this, options.encoders), "f");
|
|
60
|
+
__classPrivateFieldSet(this, _SyncAvroFileWriter_encoder, __classPrivateFieldGet(this, _SyncAvroFileWriter_instances, "m", _SyncAvroFileWriter_resolveEncoder).call(this, __classPrivateFieldGet(this, _SyncAvroFileWriter_codec, "f")), "f");
|
|
61
|
+
__classPrivateFieldSet(this, _SyncAvroFileWriter_metadata, __classPrivateFieldGet(this, _SyncAvroFileWriter_instances, "m", _SyncAvroFileWriter_buildMetadata).call(this, options.metadata), "f");
|
|
62
|
+
__classPrivateFieldGet(this, _SyncAvroFileWriter_metadata, "f").set("avro.schema", encodeString(JSON.stringify(__classPrivateFieldGet(this, _SyncAvroFileWriter_schemaType, "f").toJSON())));
|
|
63
|
+
if (__classPrivateFieldGet(this, _SyncAvroFileWriter_codec, "f") !== "null") {
|
|
64
|
+
__classPrivateFieldGet(this, _SyncAvroFileWriter_metadata, "f").set("avro.codec", encodeString(__classPrivateFieldGet(this, _SyncAvroFileWriter_codec, "f")));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Appends a record to the pending block, flushing when the block size is met.
|
|
69
|
+
*/
|
|
70
|
+
append(record) {
|
|
71
|
+
__classPrivateFieldGet(this, _SyncAvroFileWriter_instances, "m", _SyncAvroFileWriter_ensureOpen).call(this);
|
|
72
|
+
__classPrivateFieldGet(this, _SyncAvroFileWriter_instances, "m", _SyncAvroFileWriter_ensureHeaderWritten).call(this);
|
|
73
|
+
if (!__classPrivateFieldGet(this, _SyncAvroFileWriter_schemaType, "f").isValid(record)) {
|
|
74
|
+
throw new Error("Record does not conform to the schema.");
|
|
75
|
+
}
|
|
76
|
+
const recordBytes = __classPrivateFieldGet(this, _SyncAvroFileWriter_instances, "m", _SyncAvroFileWriter_encodeRecord).call(this, record);
|
|
77
|
+
__classPrivateFieldGet(this, _SyncAvroFileWriter_pendingRecords, "f").push(recordBytes);
|
|
78
|
+
__classPrivateFieldSet(this, _SyncAvroFileWriter_pendingBytes, __classPrivateFieldGet(this, _SyncAvroFileWriter_pendingBytes, "f") + recordBytes.length, "f");
|
|
79
|
+
__classPrivateFieldSet(this, _SyncAvroFileWriter_pendingCount, __classPrivateFieldGet(this, _SyncAvroFileWriter_pendingCount, "f") + 1, "f");
|
|
80
|
+
if (__classPrivateFieldGet(this, _SyncAvroFileWriter_pendingBytes, "f") >= __classPrivateFieldGet(this, _SyncAvroFileWriter_blockSize, "f")) {
|
|
81
|
+
this.flushBlock();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Flushes any pending data and prevents further writes.
|
|
86
|
+
*/
|
|
87
|
+
close() {
|
|
88
|
+
if (__classPrivateFieldGet(this, _SyncAvroFileWriter_closed, "f")) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
__classPrivateFieldGet(this, _SyncAvroFileWriter_instances, "m", _SyncAvroFileWriter_ensureHeaderWritten).call(this);
|
|
92
|
+
this.flushBlock();
|
|
93
|
+
__classPrivateFieldSet(this, _SyncAvroFileWriter_closed, true, "f");
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Forces pending data into a block immediately.
|
|
97
|
+
*/
|
|
98
|
+
flushBlock() {
|
|
99
|
+
__classPrivateFieldGet(this, _SyncAvroFileWriter_instances, "m", _SyncAvroFileWriter_ensureOpen).call(this);
|
|
100
|
+
__classPrivateFieldGet(this, _SyncAvroFileWriter_instances, "m", _SyncAvroFileWriter_ensureHeaderWritten).call(this);
|
|
101
|
+
if (__classPrivateFieldGet(this, _SyncAvroFileWriter_pendingCount, "f") === 0) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const combined = __classPrivateFieldGet(this, _SyncAvroFileWriter_instances, "m", _SyncAvroFileWriter_combinePending).call(this);
|
|
105
|
+
const encoded = __classPrivateFieldGet(this, _SyncAvroFileWriter_encoder, "f").encode(combined);
|
|
106
|
+
const block = {
|
|
107
|
+
count: BigInt(__classPrivateFieldGet(this, _SyncAvroFileWriter_pendingCount, "f")),
|
|
108
|
+
data: encoded,
|
|
109
|
+
sync: __classPrivateFieldGet(this, _SyncAvroFileWriter_syncMarker, "f"),
|
|
110
|
+
};
|
|
111
|
+
BLOCK_TYPE.writeSync(__classPrivateFieldGet(this, _SyncAvroFileWriter_tap, "f"), block);
|
|
112
|
+
__classPrivateFieldSet(this, _SyncAvroFileWriter_pendingRecords, [], "f");
|
|
113
|
+
__classPrivateFieldSet(this, _SyncAvroFileWriter_pendingBytes, 0, "f");
|
|
114
|
+
__classPrivateFieldSet(this, _SyncAvroFileWriter_pendingCount, 0, "f");
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
_SyncAvroFileWriter_tap = new WeakMap(), _SyncAvroFileWriter_schemaType = new WeakMap(), _SyncAvroFileWriter_codec = new WeakMap(), _SyncAvroFileWriter_encoder = new WeakMap(), _SyncAvroFileWriter_blockSize = new WeakMap(), _SyncAvroFileWriter_syncMarker = new WeakMap(), _SyncAvroFileWriter_metadata = new WeakMap(), _SyncAvroFileWriter_pendingRecords = new WeakMap(), _SyncAvroFileWriter_pendingBytes = new WeakMap(), _SyncAvroFileWriter_pendingCount = new WeakMap(), _SyncAvroFileWriter_headerWritten = new WeakMap(), _SyncAvroFileWriter_closed = new WeakMap(), _SyncAvroFileWriter_builtInEncoders = new WeakMap(), _SyncAvroFileWriter_customEncoders = new WeakMap(), _SyncAvroFileWriter_instances = new WeakSet(), _SyncAvroFileWriter_ensureOpen = function _SyncAvroFileWriter_ensureOpen() {
|
|
118
|
+
if (__classPrivateFieldGet(this, _SyncAvroFileWriter_closed, "f")) {
|
|
119
|
+
throw new Error("Avro writer is already closed.");
|
|
120
|
+
}
|
|
121
|
+
}, _SyncAvroFileWriter_ensureHeaderWritten = function _SyncAvroFileWriter_ensureHeaderWritten() {
|
|
122
|
+
if (__classPrivateFieldGet(this, _SyncAvroFileWriter_headerWritten, "f")) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
__classPrivateFieldGet(this, _SyncAvroFileWriter_instances, "m", _SyncAvroFileWriter_writeHeader).call(this);
|
|
126
|
+
}, _SyncAvroFileWriter_writeHeader = function _SyncAvroFileWriter_writeHeader() {
|
|
127
|
+
const header = {
|
|
128
|
+
magic: MAGIC_BYTES,
|
|
129
|
+
meta: __classPrivateFieldGet(this, _SyncAvroFileWriter_metadata, "f"),
|
|
130
|
+
sync: __classPrivateFieldGet(this, _SyncAvroFileWriter_syncMarker, "f"),
|
|
131
|
+
};
|
|
132
|
+
HEADER_TYPE.writeSync(__classPrivateFieldGet(this, _SyncAvroFileWriter_tap, "f"), header);
|
|
133
|
+
__classPrivateFieldSet(this, _SyncAvroFileWriter_headerWritten, true, "f");
|
|
134
|
+
}, _SyncAvroFileWriter_validateBlockSize = function _SyncAvroFileWriter_validateBlockSize(blockSize) {
|
|
135
|
+
const size = blockSize ?? DEFAULT_BLOCK_SIZE_BYTES;
|
|
136
|
+
if (!Number.isFinite(size) || !Number.isInteger(size) || size <= 0) {
|
|
137
|
+
throw new RangeError("blockSize must be a positive integer byte count.");
|
|
138
|
+
}
|
|
139
|
+
return size;
|
|
140
|
+
}, _SyncAvroFileWriter_initializeSyncMarker = function _SyncAvroFileWriter_initializeSyncMarker(marker) {
|
|
141
|
+
if (!marker) {
|
|
142
|
+
const generated = new Uint8Array(SYNC_MARKER_SIZE);
|
|
143
|
+
crypto.getRandomValues(generated);
|
|
144
|
+
return generated;
|
|
145
|
+
}
|
|
146
|
+
if (marker.length !== SYNC_MARKER_SIZE) {
|
|
147
|
+
throw new Error(`Sync marker must be ${SYNC_MARKER_SIZE} bytes long.`);
|
|
148
|
+
}
|
|
149
|
+
return marker.slice();
|
|
150
|
+
}, _SyncAvroFileWriter_validateCustomEncoders = function _SyncAvroFileWriter_validateCustomEncoders(encoders) {
|
|
151
|
+
if (!encoders) {
|
|
152
|
+
return {};
|
|
153
|
+
}
|
|
154
|
+
for (const codec of Object.keys(encoders)) {
|
|
155
|
+
if (codec in __classPrivateFieldGet(this, _SyncAvroFileWriter_builtInEncoders, "f")) {
|
|
156
|
+
throw new Error(`Cannot override built-in encoder for codec: ${codec}`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return { ...encoders };
|
|
160
|
+
}, _SyncAvroFileWriter_resolveEncoder = function _SyncAvroFileWriter_resolveEncoder(codec) {
|
|
161
|
+
if (codec in __classPrivateFieldGet(this, _SyncAvroFileWriter_builtInEncoders, "f")) {
|
|
162
|
+
return __classPrivateFieldGet(this, _SyncAvroFileWriter_builtInEncoders, "f")[codec];
|
|
163
|
+
}
|
|
164
|
+
if (codec in __classPrivateFieldGet(this, _SyncAvroFileWriter_customEncoders, "f")) {
|
|
165
|
+
return __classPrivateFieldGet(this, _SyncAvroFileWriter_customEncoders, "f")[codec];
|
|
166
|
+
}
|
|
167
|
+
throw new Error(`Unsupported codec: ${codec}. Provide a custom encoder.`);
|
|
168
|
+
}, _SyncAvroFileWriter_buildMetadata = function _SyncAvroFileWriter_buildMetadata(input) {
|
|
169
|
+
const metadata = new Map();
|
|
170
|
+
if (!input) {
|
|
171
|
+
return metadata;
|
|
172
|
+
}
|
|
173
|
+
const setEntry = (key, value) => {
|
|
174
|
+
__classPrivateFieldGet(this, _SyncAvroFileWriter_instances, "m", _SyncAvroFileWriter_assertMetadataKey).call(this, key);
|
|
175
|
+
if (value instanceof Uint8Array) {
|
|
176
|
+
metadata.set(key, value.slice());
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
metadata.set(key, encodeString(value));
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
if (input instanceof Map) {
|
|
183
|
+
for (const [key, value] of input.entries()) {
|
|
184
|
+
setEntry(key, value);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
for (const [key, value] of Object.entries(input)) {
|
|
189
|
+
setEntry(key, value);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return metadata;
|
|
193
|
+
}, _SyncAvroFileWriter_assertMetadataKey = function _SyncAvroFileWriter_assertMetadataKey(key) {
|
|
194
|
+
if (typeof key !== "string" || key.length === 0) {
|
|
195
|
+
throw new Error("Metadata keys must be non-empty strings.");
|
|
196
|
+
}
|
|
197
|
+
if (RESERVED_METADATA_KEYS.has(key)) {
|
|
198
|
+
throw new Error(`Metadata key "${key}" is reserved and managed by the Avro writer.`);
|
|
199
|
+
}
|
|
200
|
+
}, _SyncAvroFileWriter_encodeRecord = function _SyncAvroFileWriter_encodeRecord(record) {
|
|
201
|
+
const buffer = __classPrivateFieldGet(this, _SyncAvroFileWriter_schemaType, "f").toSyncBuffer(record);
|
|
202
|
+
return new Uint8Array(buffer);
|
|
203
|
+
}, _SyncAvroFileWriter_combinePending = function _SyncAvroFileWriter_combinePending() {
|
|
204
|
+
const combined = new Uint8Array(__classPrivateFieldGet(this, _SyncAvroFileWriter_pendingBytes, "f"));
|
|
205
|
+
let offset = 0;
|
|
206
|
+
for (const record of __classPrivateFieldGet(this, _SyncAvroFileWriter_pendingRecords, "f")) {
|
|
207
|
+
combined.set(record, offset);
|
|
208
|
+
offset += record.length;
|
|
209
|
+
}
|
|
210
|
+
return combined;
|
|
211
|
+
};
|
|
@@ -9,7 +9,7 @@ import type { IReadableBuffer } from "./buffer.js";
|
|
|
9
9
|
* Key features:
|
|
10
10
|
* - Blob-backed: Reads data directly from the Blob asynchronously.
|
|
11
11
|
* - Random access: Supports reading at arbitrary byte offsets.
|
|
12
|
-
* - Bounds checking: Operations that
|
|
12
|
+
* - Bounds checking: Operations that exceed buffer bounds throw ReadBufferError.
|
|
13
13
|
* - Memory efficient: Doesn't load data into memory.
|
|
14
14
|
*
|
|
15
15
|
* @example
|
|
@@ -41,9 +41,10 @@ export declare class BlobReadableBuffer implements IReadableBuffer {
|
|
|
41
41
|
*
|
|
42
42
|
* @param offset The byte offset to start reading from (0-based).
|
|
43
43
|
* @param size The number of bytes to read.
|
|
44
|
-
* @returns A Promise that resolves to a new Uint8Array containing the read bytes
|
|
44
|
+
* @returns A Promise that resolves to a new Uint8Array containing the read bytes.
|
|
45
|
+
* @throws ReadBufferError if the requested range is out of bounds.
|
|
45
46
|
*/
|
|
46
|
-
read(offset: number, size: number): Promise<Uint8Array
|
|
47
|
+
read(offset: number, size: number): Promise<Uint8Array>;
|
|
47
48
|
/**
|
|
48
49
|
* Checks if more data can be read starting at the given offset.
|
|
49
50
|
* @param offset The byte offset to check.
|
|
@@ -10,6 +10,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
10
10
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
11
|
};
|
|
12
12
|
var _BlobReadableBuffer_blob;
|
|
13
|
+
import { ReadBufferError } from "./buffer_error.js";
|
|
13
14
|
/**
|
|
14
15
|
* A read-only buffer implementation that provides random access read operations
|
|
15
16
|
* on data from a Blob. This class is useful for working with binary data
|
|
@@ -20,7 +21,7 @@ var _BlobReadableBuffer_blob;
|
|
|
20
21
|
* Key features:
|
|
21
22
|
* - Blob-backed: Reads data directly from the Blob asynchronously.
|
|
22
23
|
* - Random access: Supports reading at arbitrary byte offsets.
|
|
23
|
-
* - Bounds checking: Operations that
|
|
24
|
+
* - Bounds checking: Operations that exceed buffer bounds throw ReadBufferError.
|
|
24
25
|
* - Memory efficient: Doesn't load data into memory.
|
|
25
26
|
*
|
|
26
27
|
* @example
|
|
@@ -57,11 +58,16 @@ export class BlobReadableBuffer {
|
|
|
57
58
|
*
|
|
58
59
|
* @param offset The byte offset to start reading from (0-based).
|
|
59
60
|
* @param size The number of bytes to read.
|
|
60
|
-
* @returns A Promise that resolves to a new Uint8Array containing the read bytes
|
|
61
|
+
* @returns A Promise that resolves to a new Uint8Array containing the read bytes.
|
|
62
|
+
* @throws ReadBufferError if the requested range is out of bounds.
|
|
61
63
|
*/
|
|
62
64
|
async read(offset, size) {
|
|
63
|
-
if (offset
|
|
64
|
-
|
|
65
|
+
if (offset < 0 || size < 0) {
|
|
66
|
+
throw new ReadBufferError(`Offset and size must be non-negative. Got offset=${offset}, size=${size}`, offset, size, __classPrivateFieldGet(this, _BlobReadableBuffer_blob, "f").size);
|
|
67
|
+
}
|
|
68
|
+
if (offset + size > __classPrivateFieldGet(this, _BlobReadableBuffer_blob, "f").size) {
|
|
69
|
+
throw new ReadBufferError(`Operation exceeds buffer bounds. offset=${offset}, size=${size}, bufferLength=${__classPrivateFieldGet(this, _BlobReadableBuffer_blob, "f").size}`, offset, size, __classPrivateFieldGet(this, _BlobReadableBuffer_blob, "f").size);
|
|
70
|
+
}
|
|
65
71
|
// Read directly from the Blob
|
|
66
72
|
const sliced = __classPrivateFieldGet(this, _BlobReadableBuffer_blob, "f").slice(offset, offset + size);
|
|
67
73
|
const arrayBuffer = await sliced.arrayBuffer();
|
|
@@ -73,8 +79,16 @@ export class BlobReadableBuffer {
|
|
|
73
79
|
* @returns True if at least one byte can be read from the offset.
|
|
74
80
|
*/
|
|
75
81
|
async canReadMore(offset) {
|
|
76
|
-
|
|
77
|
-
|
|
82
|
+
try {
|
|
83
|
+
await this.read(offset, 1);
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
if (err instanceof ReadBufferError) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
throw err;
|
|
91
|
+
}
|
|
78
92
|
}
|
|
79
93
|
}
|
|
80
94
|
_BlobReadableBuffer_blob = new WeakMap();
|
|
@@ -4,8 +4,11 @@
|
|
|
4
4
|
export interface IReadableBuffer {
|
|
5
5
|
/**
|
|
6
6
|
* Reads a portion of the buffer starting at offset with the given size.
|
|
7
|
+
*
|
|
8
|
+
* @throws ReadBufferError when the requested range is invalid or exceeds the
|
|
9
|
+
* available bounds.
|
|
7
10
|
*/
|
|
8
|
-
read(offset: number, size: number): Promise<Uint8Array
|
|
11
|
+
read(offset: number, size: number): Promise<Uint8Array>;
|
|
9
12
|
/**
|
|
10
13
|
* Checks if more data can be read starting at the given offset.
|
|
11
14
|
*/
|
|
@@ -18,6 +21,8 @@ export interface IWritableBuffer {
|
|
|
18
21
|
/**
|
|
19
22
|
* Appends bytes to the buffer, advancing its internal write cursor when the
|
|
20
23
|
* operation succeeds.
|
|
24
|
+
*
|
|
25
|
+
* @throws WriteBufferError when the buffer cannot accept the requested bytes.
|
|
21
26
|
*/
|
|
22
27
|
appendBytes(data: Uint8Array): Promise<void>;
|
|
23
28
|
/**
|