@dcl/protocol 1.0.0-28172947415.commit-c2f6832 → 1.0.0-28173821783.commit-63eb0db
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/README.md +0 -201
- package/out-js/decentraland/kernel/apis/restricted_actions.gen.d.ts +0 -21
- package/out-js/decentraland/kernel/apis/restricted_actions.gen.js +6 -85
- package/out-js/decentraland/kernel/apis/restricted_actions.gen.js.map +1 -1
- package/out-js/decentraland/kernel/comms/rfc4/comms.gen.d.ts +0 -21
- package/out-js/decentraland/kernel/comms/rfc4/comms.gen.js +4 -124
- package/out-js/decentraland/kernel/comms/rfc4/comms.gen.js.map +1 -1
- package/out-js/decentraland/sdk/components/avatar_shape.gen.d.ts +0 -8
- package/out-js/decentraland/sdk/components/avatar_shape.gen.js +1 -35
- package/out-js/decentraland/sdk/components/avatar_shape.gen.js.map +1 -1
- package/out-ts/decentraland/kernel/apis/restricted_actions.gen.ts +3 -89
- package/out-ts/decentraland/kernel/comms/rfc4/comms.gen.ts +2 -166
- package/out-ts/decentraland/sdk/components/avatar_shape.gen.ts +0 -34
- package/package.json +6 -9
- package/proto/buf.yaml +47 -0
- package/proto/decentraland/kernel/apis/restricted_actions.proto +0 -7
- package/proto/decentraland/kernel/comms/rfc4/comms.proto +0 -11
- package/proto/decentraland/sdk/components/avatar_shape.proto +0 -5
- package/proto/decentraland/sdk/components/light_source.proto +1 -1
- package/proto/decentraland/sdk/components/virtual_camera.proto +0 -2
- package/proto/google/LICENSE +27 -0
- package/proto/google/README.md +1 -0
- package/proto/google/api/annotations.json +83 -0
- package/proto/google/api/annotations.proto +11 -0
- package/proto/google/api/http.json +86 -0
- package/proto/google/api/http.proto +31 -0
- package/proto/google/protobuf/api.json +118 -0
- package/proto/google/protobuf/api.proto +34 -0
- package/proto/google/protobuf/descriptor.json +739 -0
- package/proto/google/protobuf/descriptor.proto +286 -0
- package/proto/google/protobuf/source_context.json +20 -0
- package/proto/google/protobuf/source_context.proto +7 -0
- package/proto/google/protobuf/type.json +202 -0
- package/proto/google/protobuf/type.proto +89 -0
- package/proto/decentraland/common/options.proto +0 -30
- package/proto/decentraland/common/quantization_example.proto +0 -132
- package/proto/decentraland/pulse/pulse_client.proto +0 -77
- package/proto/decentraland/pulse/pulse_server.proto +0 -138
- package/proto/decentraland/pulse/pulse_shared.proto +0 -48
- package/protoc-gen-bitwise/generator_csharp.js +0 -215
- package/protoc-gen-bitwise/options.js +0 -108
- package/protoc-gen-bitwise/plugin.js +0 -87
- package/protoc-gen-bitwise/runtime/cs/BitReader.cs +0 -112
- package/protoc-gen-bitwise/runtime/cs/BitWriter.cs +0 -117
- package/protoc-gen-bitwise/runtime/cs/Quantize.cs +0 -35
- package/protoc-gen-bitwise/wire.js +0 -239
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Parser for the custom bitwise field options defined in options.proto.
|
|
5
|
-
*
|
|
6
|
-
* The descriptor decoder hands us the raw serialized FieldOptions bytes (it
|
|
7
|
-
* declares `options` as opaque bytes). We walk those bytes looking for the two
|
|
8
|
-
* custom extension field numbers — protobuf preserves unknown/unregistered
|
|
9
|
-
* extension bytes, so they are always present even though no runtime here knows
|
|
10
|
-
* the extension schema. This mirrors the original options_pb2.py.
|
|
11
|
-
*
|
|
12
|
-
* Wire format: tag = (field_number << 3) | wire_type
|
|
13
|
-
* wire_type 0 = varint, 1 = 64-bit, 2 = length-delimited, 5 = 32-bit
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
const { readVarint, skipField } = require('./wire')
|
|
17
|
-
|
|
18
|
-
// Extension field numbers as defined in options.proto.
|
|
19
|
-
const QUANTIZED_FIELD_NUMBER = 50001
|
|
20
|
-
const BIT_PACKED_FIELD_NUMBER = 50002
|
|
21
|
-
|
|
22
|
-
/** Parse a serialized QuantizedFloatOptions message: { min, max, bits }. */
|
|
23
|
-
function parseQuantized(data) {
|
|
24
|
-
const opts = { min: 0.0, max: 0.0, bits: 0 }
|
|
25
|
-
let pos = 0
|
|
26
|
-
while (pos < data.length) {
|
|
27
|
-
let tag
|
|
28
|
-
;[tag, pos] = readVarint(data, pos)
|
|
29
|
-
const fieldNum = tag >>> 3
|
|
30
|
-
const wireType = tag & 0x7
|
|
31
|
-
if (fieldNum === 1 && wireType === 5) {
|
|
32
|
-
// min (float)
|
|
33
|
-
opts.min = data.readFloatLE(pos)
|
|
34
|
-
pos += 4
|
|
35
|
-
} else if (fieldNum === 2 && wireType === 5) {
|
|
36
|
-
// max (float)
|
|
37
|
-
opts.max = data.readFloatLE(pos)
|
|
38
|
-
pos += 4
|
|
39
|
-
} else if (fieldNum === 3 && wireType === 0) {
|
|
40
|
-
// bits (uint32)
|
|
41
|
-
;[opts.bits, pos] = readVarint(data, pos)
|
|
42
|
-
} else {
|
|
43
|
-
pos = skipField(data, pos, wireType)
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
return opts
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/** Parse a serialized BitPackedOptions message: { bits }. */
|
|
50
|
-
function parseBitPacked(data) {
|
|
51
|
-
const opts = { bits: 0 }
|
|
52
|
-
let pos = 0
|
|
53
|
-
while (pos < data.length) {
|
|
54
|
-
let tag
|
|
55
|
-
;[tag, pos] = readVarint(data, pos)
|
|
56
|
-
const fieldNum = tag >>> 3
|
|
57
|
-
const wireType = tag & 0x7
|
|
58
|
-
if (fieldNum === 1 && wireType === 0) {
|
|
59
|
-
// bits (uint32)
|
|
60
|
-
;[opts.bits, pos] = readVarint(data, pos)
|
|
61
|
-
} else {
|
|
62
|
-
pos = skipField(data, pos, wireType)
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
return opts
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Extract custom bitwise options from raw FieldOptions bytes.
|
|
70
|
-
*
|
|
71
|
-
* @param {Buffer|null} optionsRaw serialized FieldOptions, or null when unset.
|
|
72
|
-
* @returns {{quantized: object|null, bitPacked: object|null}}
|
|
73
|
-
*/
|
|
74
|
-
function getFieldOptions(optionsRaw) {
|
|
75
|
-
if (!optionsRaw || optionsRaw.length === 0) {
|
|
76
|
-
return { quantized: null, bitPacked: null }
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
let quantized = null
|
|
80
|
-
let bitPacked = null
|
|
81
|
-
let pos = 0
|
|
82
|
-
|
|
83
|
-
while (pos < optionsRaw.length) {
|
|
84
|
-
let tag
|
|
85
|
-
;[tag, pos] = readVarint(optionsRaw, pos)
|
|
86
|
-
const fieldNum = tag >>> 3
|
|
87
|
-
const wireType = tag & 0x7
|
|
88
|
-
|
|
89
|
-
if (wireType === 2) {
|
|
90
|
-
let len
|
|
91
|
-
;[len, pos] = readVarint(optionsRaw, pos)
|
|
92
|
-
const valueBytes = optionsRaw.subarray(pos, pos + len)
|
|
93
|
-
pos += len
|
|
94
|
-
if (fieldNum === QUANTIZED_FIELD_NUMBER) {
|
|
95
|
-
quantized = parseQuantized(valueBytes)
|
|
96
|
-
} else if (fieldNum === BIT_PACKED_FIELD_NUMBER) {
|
|
97
|
-
bitPacked = parseBitPacked(valueBytes)
|
|
98
|
-
}
|
|
99
|
-
// else: unknown length-delimited field — already consumed.
|
|
100
|
-
} else {
|
|
101
|
-
pos = skipField(optionsRaw, pos, wireType)
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
return { quantized, bitPacked }
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
module.exports = { getFieldOptions }
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
'use strict'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* protoc-gen-bitwise — protoc plugin that generates C# bitwise serialization code.
|
|
6
|
-
*
|
|
7
|
-
* Protocol:
|
|
8
|
-
* 1. protoc writes a serialised CodeGeneratorRequest to this process's stdin.
|
|
9
|
-
* 2. This plugin reads it, generates C# partial classes with float accessor
|
|
10
|
-
* properties for every message that carries [(quantized)] field annotations.
|
|
11
|
-
* 3. A serialised CodeGeneratorResponse is written to stdout.
|
|
12
|
-
*
|
|
13
|
-
* Implemented in plain Node with a self-contained protobuf wire codec (see
|
|
14
|
-
* wire.js) so it runs with only `node` on PATH — no npm install required, even
|
|
15
|
-
* when invoked directly from a sibling checkout.
|
|
16
|
-
*
|
|
17
|
-
* Usage (from project root):
|
|
18
|
-
* protoc \
|
|
19
|
-
* --proto_path=proto \
|
|
20
|
-
* --bitwise_out=generated/ \
|
|
21
|
-
* --plugin=protoc-gen-bitwise=protoc-gen-bitwise/plugin.js \
|
|
22
|
-
* proto/my_messages.proto
|
|
23
|
-
*
|
|
24
|
-
* On Windows, protoc needs an executable wrapper, e.g. a .cmd that runs:
|
|
25
|
-
* node "<path>\protoc-gen-bitwise\plugin.js" %*
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
const { decodeRequest, encodeResponse } = require('./wire')
|
|
29
|
-
const { generateCsharp } = require('./generator_csharp')
|
|
30
|
-
|
|
31
|
-
// CodeGeneratorResponse.Feature.FEATURE_PROTO3_OPTIONAL — advertised so protoc
|
|
32
|
-
// does not reject the plugin when the schema uses proto3 `optional` fields.
|
|
33
|
-
const FEATURE_PROTO3_OPTIONAL = 1
|
|
34
|
-
|
|
35
|
-
function readStdin() {
|
|
36
|
-
return new Promise((resolve, reject) => {
|
|
37
|
-
const chunks = []
|
|
38
|
-
process.stdin.on('data', (chunk) => chunks.push(chunk))
|
|
39
|
-
process.stdin.on('end', () => resolve(Buffer.concat(chunks)))
|
|
40
|
-
process.stdin.on('error', reject)
|
|
41
|
-
})
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
async function main() {
|
|
45
|
-
const requestBytes = await readStdin()
|
|
46
|
-
const request = decodeRequest(requestBytes)
|
|
47
|
-
|
|
48
|
-
// Lookup map for all file descriptors (parity with the Python plugin).
|
|
49
|
-
const fileByName = new Map()
|
|
50
|
-
for (const file of request.protoFile) fileByName.set(file.name, file)
|
|
51
|
-
|
|
52
|
-
const files = []
|
|
53
|
-
let error = null
|
|
54
|
-
|
|
55
|
-
for (const fileName of request.fileToGenerate) {
|
|
56
|
-
// Skip the options definition file itself — it has no messages to generate.
|
|
57
|
-
if (fileName === 'decentraland/common/options.proto') continue
|
|
58
|
-
|
|
59
|
-
const fileProto = fileByName.get(fileName)
|
|
60
|
-
if (!fileProto) continue
|
|
61
|
-
|
|
62
|
-
try {
|
|
63
|
-
const generated = generateCsharp(fileProto)
|
|
64
|
-
if (generated) files.push(generated)
|
|
65
|
-
} catch (exc) {
|
|
66
|
-
error = `protoc-gen-bitwise: error processing ${fileName}: ${exc && exc.message ? exc.message : exc}`
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const response = encodeResponse({
|
|
71
|
-
error,
|
|
72
|
-
supportedFeatures: FEATURE_PROTO3_OPTIONAL,
|
|
73
|
-
files,
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
// Let the write flush before the process exits (do not call process.exit()).
|
|
77
|
-
process.stdout.write(response)
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
main().catch((exc) => {
|
|
81
|
-
const response = encodeResponse({
|
|
82
|
-
error: `protoc-gen-bitwise: ${exc && exc.stack ? exc.stack : exc}`,
|
|
83
|
-
supportedFeatures: FEATURE_PROTO3_OPTIONAL,
|
|
84
|
-
files: [],
|
|
85
|
-
})
|
|
86
|
-
process.stdout.write(response)
|
|
87
|
-
})
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
// Decentraland.Networking.Bitwise — BitReader
|
|
2
|
-
// Copy this file into your Unity project alongside generated *.Bitwise.cs files.
|
|
3
|
-
|
|
4
|
-
using System;
|
|
5
|
-
|
|
6
|
-
namespace Decentraland.Networking.Bitwise
|
|
7
|
-
{
|
|
8
|
-
/// <summary>
|
|
9
|
-
/// Reads bits from a byte buffer, MSB first within each byte (big-endian bit
|
|
10
|
-
/// order). Symmetric counterpart of <see cref="BitWriter"/>: every
|
|
11
|
-
/// Write… call has a corresponding Read… call with identical arguments that
|
|
12
|
-
/// reproduces the original value.
|
|
13
|
-
/// </summary>
|
|
14
|
-
public sealed class BitReader
|
|
15
|
-
{
|
|
16
|
-
private readonly byte[] _buffer;
|
|
17
|
-
private int _bitPos;
|
|
18
|
-
|
|
19
|
-
/// <param name="buffer">Source buffer filled by a <see cref="BitWriter"/>.</param>
|
|
20
|
-
public BitReader(byte[] buffer)
|
|
21
|
-
{
|
|
22
|
-
_buffer = buffer ?? throw new ArgumentNullException(nameof(buffer));
|
|
23
|
-
_bitPos = 0;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/// <summary>Current read position in bits.</summary>
|
|
27
|
-
public int BitPosition => _bitPos;
|
|
28
|
-
|
|
29
|
-
/// <summary>
|
|
30
|
-
/// Returns <c>true</c> when all written bits have been consumed
|
|
31
|
-
/// (i.e. <see cref="BitPosition"/> has reached the end of the buffer).
|
|
32
|
-
/// </summary>
|
|
33
|
-
public bool IsAtEnd => _bitPos >= _buffer.Length * 8;
|
|
34
|
-
|
|
35
|
-
// -----------------------------------------------------------------
|
|
36
|
-
// Core primitive
|
|
37
|
-
// -----------------------------------------------------------------
|
|
38
|
-
|
|
39
|
-
/// <summary>
|
|
40
|
-
/// Reads <paramref name="bits"/> bits and returns them as the
|
|
41
|
-
/// least-significant bits of a <see cref="uint"/>, MSB first.
|
|
42
|
-
/// </summary>
|
|
43
|
-
public uint ReadBits(int bits)
|
|
44
|
-
{
|
|
45
|
-
uint value = 0;
|
|
46
|
-
for (int i = bits - 1; i >= 0; i--)
|
|
47
|
-
{
|
|
48
|
-
int byteIdx = _bitPos / 8;
|
|
49
|
-
int bitIdx = 7 - (_bitPos % 8);
|
|
50
|
-
|
|
51
|
-
if ((_buffer[byteIdx] >> bitIdx & 1) == 1)
|
|
52
|
-
value |= 1u << i;
|
|
53
|
-
|
|
54
|
-
_bitPos++;
|
|
55
|
-
}
|
|
56
|
-
return value;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// -----------------------------------------------------------------
|
|
60
|
-
// Quantized float
|
|
61
|
-
// -----------------------------------------------------------------
|
|
62
|
-
|
|
63
|
-
/// <summary>
|
|
64
|
-
/// Reads a quantized float encoded with <see cref="BitWriter.WriteQuantizedFloat"/>.
|
|
65
|
-
/// Arguments must match those used during encoding exactly.
|
|
66
|
-
/// </summary>
|
|
67
|
-
public float ReadQuantizedFloat(float min, float max, int bits)
|
|
68
|
-
{
|
|
69
|
-
uint maxQ = (1u << bits) - 1;
|
|
70
|
-
uint quantized = ReadBits(bits);
|
|
71
|
-
float normalized = (float)quantized / maxQ;
|
|
72
|
-
return min + normalized * (max - min);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// -----------------------------------------------------------------
|
|
76
|
-
// Standard IEEE 754 helpers
|
|
77
|
-
// -----------------------------------------------------------------
|
|
78
|
-
|
|
79
|
-
/// <summary>Reads a 32-bit IEEE 754 float written by <see cref="BitWriter.WriteFloat"/>.</summary>
|
|
80
|
-
public float ReadFloat()
|
|
81
|
-
{
|
|
82
|
-
uint bits = ReadBits(32);
|
|
83
|
-
byte[] bytes =
|
|
84
|
-
{
|
|
85
|
-
(byte)(bits & 0xFF),
|
|
86
|
-
(byte)((bits >> 8) & 0xFF),
|
|
87
|
-
(byte)((bits >> 16) & 0xFF),
|
|
88
|
-
(byte)((bits >> 24) & 0xFF),
|
|
89
|
-
};
|
|
90
|
-
return BitConverter.ToSingle(bytes, 0);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/// <summary>Reads a 64-bit IEEE 754 double written by <see cref="BitWriter.WriteDouble"/>.</summary>
|
|
94
|
-
public double ReadDouble()
|
|
95
|
-
{
|
|
96
|
-
uint hi = ReadBits(32);
|
|
97
|
-
uint lo = ReadBits(32);
|
|
98
|
-
byte[] bytes =
|
|
99
|
-
{
|
|
100
|
-
(byte)(lo & 0xFF),
|
|
101
|
-
(byte)((lo >> 8) & 0xFF),
|
|
102
|
-
(byte)((lo >> 16) & 0xFF),
|
|
103
|
-
(byte)((lo >> 24) & 0xFF),
|
|
104
|
-
(byte)(hi & 0xFF),
|
|
105
|
-
(byte)((hi >> 8) & 0xFF),
|
|
106
|
-
(byte)((hi >> 16) & 0xFF),
|
|
107
|
-
(byte)((hi >> 24) & 0xFF),
|
|
108
|
-
};
|
|
109
|
-
return BitConverter.ToDouble(bytes, 0);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
// Decentraland.Networking.Bitwise — BitWriter
|
|
2
|
-
// Copy this file into your Unity project alongside generated *.Bitwise.cs files.
|
|
3
|
-
|
|
4
|
-
using System;
|
|
5
|
-
|
|
6
|
-
namespace Decentraland.Networking.Bitwise
|
|
7
|
-
{
|
|
8
|
-
/// <summary>
|
|
9
|
-
/// Writes bits into a pre-allocated byte buffer, MSB first within each byte
|
|
10
|
-
/// (big-endian bit order). This matches the layout expected by
|
|
11
|
-
/// <see cref="BitReader"/> so that encode → decode is always a round-trip no-op.
|
|
12
|
-
/// </summary>
|
|
13
|
-
public sealed class BitWriter
|
|
14
|
-
{
|
|
15
|
-
private readonly byte[] _buffer;
|
|
16
|
-
private int _bitPos;
|
|
17
|
-
|
|
18
|
-
/// <param name="buffer">Destination buffer (must be large enough for all writes).</param>
|
|
19
|
-
public BitWriter(byte[] buffer)
|
|
20
|
-
{
|
|
21
|
-
_buffer = buffer ?? throw new ArgumentNullException(nameof(buffer));
|
|
22
|
-
_bitPos = 0;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/// <summary>Current write position in bits.</summary>
|
|
26
|
-
public int BitPosition => _bitPos;
|
|
27
|
-
|
|
28
|
-
/// <summary>Number of bytes written (rounded up to the nearest byte).</summary>
|
|
29
|
-
public int ByteLength => (_bitPos + 7) / 8;
|
|
30
|
-
|
|
31
|
-
/// <summary>Returns a copy of the written bytes (trimmed to <see cref="ByteLength"/>).</summary>
|
|
32
|
-
public byte[] ToArray()
|
|
33
|
-
{
|
|
34
|
-
var result = new byte[ByteLength];
|
|
35
|
-
Array.Copy(_buffer, result, ByteLength);
|
|
36
|
-
return result;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// -----------------------------------------------------------------
|
|
40
|
-
// Core primitive
|
|
41
|
-
// -----------------------------------------------------------------
|
|
42
|
-
|
|
43
|
-
/// <summary>
|
|
44
|
-
/// Writes the <paramref name="bits"/> least-significant bits of
|
|
45
|
-
/// <paramref name="value"/>, MSB first.
|
|
46
|
-
/// </summary>
|
|
47
|
-
public void WriteBits(uint value, int bits)
|
|
48
|
-
{
|
|
49
|
-
for (int i = bits - 1; i >= 0; i--)
|
|
50
|
-
{
|
|
51
|
-
int byteIdx = _bitPos / 8;
|
|
52
|
-
int bitIdx = 7 - (_bitPos % 8);
|
|
53
|
-
|
|
54
|
-
if ((value >> i & 1u) == 1u)
|
|
55
|
-
_buffer[byteIdx] |= (byte)(1 << bitIdx);
|
|
56
|
-
else
|
|
57
|
-
_buffer[byteIdx] &= (byte)~(1 << bitIdx);
|
|
58
|
-
|
|
59
|
-
_bitPos++;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// -----------------------------------------------------------------
|
|
64
|
-
// Quantized float
|
|
65
|
-
// -----------------------------------------------------------------
|
|
66
|
-
|
|
67
|
-
/// <summary>
|
|
68
|
-
/// Quantizes <paramref name="value"/> into <paramref name="bits"/> bits
|
|
69
|
-
/// using the range [<paramref name="min"/>, <paramref name="max"/>] and
|
|
70
|
-
/// writes it to the buffer.
|
|
71
|
-
///
|
|
72
|
-
/// Uses <c>Math.Round</c> (banker's rounding → ties-to-even) to guarantee
|
|
73
|
-
/// that encode → decode is a round-trip no-op.
|
|
74
|
-
/// </summary>
|
|
75
|
-
public void WriteQuantizedFloat(float value, float min, float max, int bits)
|
|
76
|
-
{
|
|
77
|
-
uint maxQ = (1u << bits) - 1;
|
|
78
|
-
float clamped = Math.Clamp(value, min, max);
|
|
79
|
-
float normalized = (clamped - min) / (max - min);
|
|
80
|
-
uint quantized = (uint)Math.Round(normalized * maxQ);
|
|
81
|
-
WriteBits(quantized, bits);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// -----------------------------------------------------------------
|
|
85
|
-
// Standard IEEE 754 helpers (used for un-annotated float/double fields)
|
|
86
|
-
// -----------------------------------------------------------------
|
|
87
|
-
|
|
88
|
-
/// <summary>Writes a 32-bit IEEE 754 float (4 bytes).</summary>
|
|
89
|
-
public void WriteFloat(float value)
|
|
90
|
-
{
|
|
91
|
-
byte[] bytes = BitConverter.GetBytes(value);
|
|
92
|
-
// GetBytes is little-endian on all platforms; write MSB first.
|
|
93
|
-
uint bits = (uint)bytes[0]
|
|
94
|
-
| ((uint)bytes[1] << 8)
|
|
95
|
-
| ((uint)bytes[2] << 16)
|
|
96
|
-
| ((uint)bytes[3] << 24);
|
|
97
|
-
WriteBits(bits, 32);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/// <summary>Writes a 64-bit IEEE 754 double (8 bytes).</summary>
|
|
101
|
-
public void WriteDouble(double value)
|
|
102
|
-
{
|
|
103
|
-
byte[] bytes = BitConverter.GetBytes(value);
|
|
104
|
-
uint lo = (uint)bytes[0]
|
|
105
|
-
| ((uint)bytes[1] << 8)
|
|
106
|
-
| ((uint)bytes[2] << 16)
|
|
107
|
-
| ((uint)bytes[3] << 24);
|
|
108
|
-
uint hi = (uint)bytes[4]
|
|
109
|
-
| ((uint)bytes[5] << 8)
|
|
110
|
-
| ((uint)bytes[6] << 16)
|
|
111
|
-
| ((uint)bytes[7] << 24);
|
|
112
|
-
// Write high 32 bits first so the bit stream is big-endian at word level too.
|
|
113
|
-
WriteBits(hi, 32);
|
|
114
|
-
WriteBits(lo, 32);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
// Decentraland.Networking.Bitwise — Quantize
|
|
2
|
-
// Copy this file into your project alongside generated *.Bitwise.cs files.
|
|
3
|
-
// ReSharper disable once RedundantUsingDirective
|
|
4
|
-
|
|
5
|
-
using System;
|
|
6
|
-
|
|
7
|
-
namespace Decentraland.Networking.Bitwise
|
|
8
|
-
// ReSharper disable once ArrangeNamespaceBody
|
|
9
|
-
{
|
|
10
|
-
/// <summary>
|
|
11
|
-
/// Static helpers for quantizing float values to/from unsigned integers.
|
|
12
|
-
/// Intended for use with protobuf uint32 fields: the integer is transmitted
|
|
13
|
-
/// as a protobuf varint, while the float accessor lives in a generated partial class.
|
|
14
|
-
/// </summary>
|
|
15
|
-
public static class Quantize
|
|
16
|
-
{
|
|
17
|
-
/// <summary>
|
|
18
|
-
/// Encodes <paramref name="value" /> to a quantized <see cref="uint" />.
|
|
19
|
-
/// Values outside [<paramref name="min" />, <paramref name="max" />] are clamped.
|
|
20
|
-
/// </summary>
|
|
21
|
-
public static uint Encode(float value, float min, float max, int bits)
|
|
22
|
-
{
|
|
23
|
-
var steps = (1u << bits) - 1;
|
|
24
|
-
var t = Math.Clamp((value - min) / (max - min), 0f, 1f);
|
|
25
|
-
return (uint)MathF.Round(t * steps);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/// <summary>Decodes a quantized <see cref="uint" /> back to a float.</summary>
|
|
29
|
-
public static float Decode(uint encoded, float min, float max, int bits)
|
|
30
|
-
{
|
|
31
|
-
var steps = (1u << bits) - 1;
|
|
32
|
-
return (float)encoded / steps * (max - min) + min;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
@@ -1,239 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Self-contained protobuf wire-format codec for protoc-gen-bitwise.
|
|
5
|
-
*
|
|
6
|
-
* The plugin only needs a tiny slice of the descriptor/plugin schemas, so
|
|
7
|
-
* rather than pull in a protobuf runtime (which would force every consumer —
|
|
8
|
-
* including the sibling Pulse checkout that runs this file directly off disk —
|
|
9
|
-
* to `npm install` the protocol repo) we decode the handful of fields we care
|
|
10
|
-
* about by walking the wire format directly. This mirrors the original Python
|
|
11
|
-
* plugin, which already hand-parsed FieldOptions for the same reason.
|
|
12
|
-
*
|
|
13
|
-
* Decoded subset:
|
|
14
|
-
* CodeGeneratorRequest { file_to_generate = 1; proto_file = 15; }
|
|
15
|
-
* FileDescriptorProto { name = 1; package = 2; message_type = 4; }
|
|
16
|
-
* DescriptorProto { name = 1; field = 2; }
|
|
17
|
-
* FieldDescriptorProto { name = 1; label = 4; type = 5; options = 8 (raw bytes); }
|
|
18
|
-
*
|
|
19
|
-
* Encoded subset:
|
|
20
|
-
* CodeGeneratorResponse { error = 1; supported_features = 2; file = 15; }
|
|
21
|
-
* CodeGeneratorResponse.File { name = 1; content = 15; }
|
|
22
|
-
*
|
|
23
|
-
* Wire types: 0 = varint, 1 = 64-bit, 2 = length-delimited, 5 = 32-bit.
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
// ---------------------------------------------------------------------------
|
|
27
|
-
// Low-level readers
|
|
28
|
-
// ---------------------------------------------------------------------------
|
|
29
|
-
|
|
30
|
-
/** Decode a protobuf varint at `pos`. Returns [value, newPos]. */
|
|
31
|
-
function readVarint(buf, pos) {
|
|
32
|
-
let result = 0
|
|
33
|
-
let shift = 0
|
|
34
|
-
let byte
|
|
35
|
-
do {
|
|
36
|
-
byte = buf[pos++]
|
|
37
|
-
// Multiplication (not <<) keeps values correct past 32 bits.
|
|
38
|
-
result += (byte & 0x7f) * Math.pow(2, shift)
|
|
39
|
-
shift += 7
|
|
40
|
-
} while (byte & 0x80)
|
|
41
|
-
return [result, pos]
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/** Advance `pos` past a field of the given wire type. Returns newPos. */
|
|
45
|
-
function skipField(buf, pos, wireType) {
|
|
46
|
-
switch (wireType) {
|
|
47
|
-
case 0: // varint
|
|
48
|
-
return readVarint(buf, pos)[1]
|
|
49
|
-
case 1: // 64-bit
|
|
50
|
-
return pos + 8
|
|
51
|
-
case 2: {
|
|
52
|
-
// length-delimited
|
|
53
|
-
const [length, next] = readVarint(buf, pos)
|
|
54
|
-
return next + length
|
|
55
|
-
}
|
|
56
|
-
case 5: // 32-bit
|
|
57
|
-
return pos + 4
|
|
58
|
-
default:
|
|
59
|
-
// Groups (3/4) are deprecated and never appear in descriptors.
|
|
60
|
-
return pos
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// ---------------------------------------------------------------------------
|
|
65
|
-
// Request decoding
|
|
66
|
-
// ---------------------------------------------------------------------------
|
|
67
|
-
|
|
68
|
-
function decodeFieldDescriptor(buf) {
|
|
69
|
-
const field = { name: '', label: 0, type: 0, optionsRaw: null }
|
|
70
|
-
let pos = 0
|
|
71
|
-
while (pos < buf.length) {
|
|
72
|
-
let tag
|
|
73
|
-
;[tag, pos] = readVarint(buf, pos)
|
|
74
|
-
const fieldNum = tag >>> 3
|
|
75
|
-
const wireType = tag & 0x7
|
|
76
|
-
if (fieldNum === 1 && wireType === 2) {
|
|
77
|
-
let len
|
|
78
|
-
;[len, pos] = readVarint(buf, pos)
|
|
79
|
-
field.name = buf.toString('utf8', pos, pos + len)
|
|
80
|
-
pos += len
|
|
81
|
-
} else if (fieldNum === 4 && wireType === 0) {
|
|
82
|
-
;[field.label, pos] = readVarint(buf, pos)
|
|
83
|
-
} else if (fieldNum === 5 && wireType === 0) {
|
|
84
|
-
;[field.type, pos] = readVarint(buf, pos)
|
|
85
|
-
} else if (fieldNum === 8 && wireType === 2) {
|
|
86
|
-
let len
|
|
87
|
-
;[len, pos] = readVarint(buf, pos)
|
|
88
|
-
// Keep the raw FieldOptions bytes so custom extensions survive (the
|
|
89
|
-
// descriptor schema doesn't know about ext 50001/50002).
|
|
90
|
-
field.optionsRaw = buf.subarray(pos, pos + len)
|
|
91
|
-
pos += len
|
|
92
|
-
} else {
|
|
93
|
-
pos = skipField(buf, pos, wireType)
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
return field
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
function decodeDescriptor(buf) {
|
|
100
|
-
const message = { name: '', field: [] }
|
|
101
|
-
let pos = 0
|
|
102
|
-
while (pos < buf.length) {
|
|
103
|
-
let tag
|
|
104
|
-
;[tag, pos] = readVarint(buf, pos)
|
|
105
|
-
const fieldNum = tag >>> 3
|
|
106
|
-
const wireType = tag & 0x7
|
|
107
|
-
if (fieldNum === 1 && wireType === 2) {
|
|
108
|
-
let len
|
|
109
|
-
;[len, pos] = readVarint(buf, pos)
|
|
110
|
-
message.name = buf.toString('utf8', pos, pos + len)
|
|
111
|
-
pos += len
|
|
112
|
-
} else if (fieldNum === 2 && wireType === 2) {
|
|
113
|
-
let len
|
|
114
|
-
;[len, pos] = readVarint(buf, pos)
|
|
115
|
-
message.field.push(decodeFieldDescriptor(buf.subarray(pos, pos + len)))
|
|
116
|
-
pos += len
|
|
117
|
-
} else {
|
|
118
|
-
// nested_type / enum_type / etc. are intentionally ignored — the
|
|
119
|
-
// generator only walks top-level messages, matching the Python plugin.
|
|
120
|
-
pos = skipField(buf, pos, wireType)
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
return message
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
function decodeFileDescriptor(buf) {
|
|
127
|
-
const file = { name: '', package: '', messageType: [] }
|
|
128
|
-
let pos = 0
|
|
129
|
-
while (pos < buf.length) {
|
|
130
|
-
let tag
|
|
131
|
-
;[tag, pos] = readVarint(buf, pos)
|
|
132
|
-
const fieldNum = tag >>> 3
|
|
133
|
-
const wireType = tag & 0x7
|
|
134
|
-
if (fieldNum === 1 && wireType === 2) {
|
|
135
|
-
let len
|
|
136
|
-
;[len, pos] = readVarint(buf, pos)
|
|
137
|
-
file.name = buf.toString('utf8', pos, pos + len)
|
|
138
|
-
pos += len
|
|
139
|
-
} else if (fieldNum === 2 && wireType === 2) {
|
|
140
|
-
let len
|
|
141
|
-
;[len, pos] = readVarint(buf, pos)
|
|
142
|
-
file.package = buf.toString('utf8', pos, pos + len)
|
|
143
|
-
pos += len
|
|
144
|
-
} else if (fieldNum === 4 && wireType === 2) {
|
|
145
|
-
let len
|
|
146
|
-
;[len, pos] = readVarint(buf, pos)
|
|
147
|
-
file.messageType.push(decodeDescriptor(buf.subarray(pos, pos + len)))
|
|
148
|
-
pos += len
|
|
149
|
-
} else {
|
|
150
|
-
pos = skipField(buf, pos, wireType)
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
return file
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/** Decode a serialized CodeGeneratorRequest. */
|
|
157
|
-
function decodeRequest(buf) {
|
|
158
|
-
const request = { fileToGenerate: [], protoFile: [] }
|
|
159
|
-
let pos = 0
|
|
160
|
-
while (pos < buf.length) {
|
|
161
|
-
let tag
|
|
162
|
-
;[tag, pos] = readVarint(buf, pos)
|
|
163
|
-
const fieldNum = tag >>> 3
|
|
164
|
-
const wireType = tag & 0x7
|
|
165
|
-
if (fieldNum === 1 && wireType === 2) {
|
|
166
|
-
let len
|
|
167
|
-
;[len, pos] = readVarint(buf, pos)
|
|
168
|
-
request.fileToGenerate.push(buf.toString('utf8', pos, pos + len))
|
|
169
|
-
pos += len
|
|
170
|
-
} else if (fieldNum === 15 && wireType === 2) {
|
|
171
|
-
let len
|
|
172
|
-
;[len, pos] = readVarint(buf, pos)
|
|
173
|
-
request.protoFile.push(decodeFileDescriptor(buf.subarray(pos, pos + len)))
|
|
174
|
-
pos += len
|
|
175
|
-
} else {
|
|
176
|
-
pos = skipField(buf, pos, wireType)
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
return request
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// ---------------------------------------------------------------------------
|
|
183
|
-
// Response encoding
|
|
184
|
-
// ---------------------------------------------------------------------------
|
|
185
|
-
|
|
186
|
-
/** Encode an unsigned integer as a protobuf varint Buffer. */
|
|
187
|
-
function encodeVarint(value) {
|
|
188
|
-
const bytes = []
|
|
189
|
-
let v = value
|
|
190
|
-
while (v > 0x7f) {
|
|
191
|
-
bytes.push((v & 0x7f) | 0x80)
|
|
192
|
-
v = Math.floor(v / 128)
|
|
193
|
-
}
|
|
194
|
-
bytes.push(v & 0x7f)
|
|
195
|
-
return Buffer.from(bytes)
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
function encodeTag(fieldNum, wireType) {
|
|
199
|
-
return encodeVarint((fieldNum << 3) | wireType)
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
/** Encode a length-delimited (string/bytes) field: tag + length + payload. */
|
|
203
|
-
function encodeLengthDelimited(fieldNum, payload) {
|
|
204
|
-
const buf = Buffer.isBuffer(payload) ? payload : Buffer.from(payload, 'utf8')
|
|
205
|
-
return Buffer.concat([encodeTag(fieldNum, 2), encodeVarint(buf.length), buf])
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
function encodeFile(file) {
|
|
209
|
-
return Buffer.concat([
|
|
210
|
-
encodeLengthDelimited(1, file.name), // name = 1
|
|
211
|
-
encodeLengthDelimited(15, file.content), // content = 15
|
|
212
|
-
])
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* Encode a CodeGeneratorResponse.
|
|
217
|
-
* @param {{error?: string|null, supportedFeatures?: number, files?: Array<{name:string,content:string}>}} response
|
|
218
|
-
*/
|
|
219
|
-
function encodeResponse(response) {
|
|
220
|
-
const parts = []
|
|
221
|
-
if (response.error != null) {
|
|
222
|
-
parts.push(encodeLengthDelimited(1, response.error)) // error = 1
|
|
223
|
-
}
|
|
224
|
-
if (response.supportedFeatures != null) {
|
|
225
|
-
parts.push(encodeTag(2, 0)) // supported_features = 2 (varint)
|
|
226
|
-
parts.push(encodeVarint(response.supportedFeatures))
|
|
227
|
-
}
|
|
228
|
-
for (const file of response.files || []) {
|
|
229
|
-
parts.push(encodeLengthDelimited(15, encodeFile(file))) // file = 15
|
|
230
|
-
}
|
|
231
|
-
return Buffer.concat(parts)
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
module.exports = {
|
|
235
|
-
readVarint,
|
|
236
|
-
skipField,
|
|
237
|
-
decodeRequest,
|
|
238
|
-
encodeResponse,
|
|
239
|
-
}
|