< Summary

Information
Class: Ice.OutputStream
Assembly: Ice
File(s): /home/runner/work/ice/ice/csharp/src/Ice/OutputStream.cs
Tag: 71_18251537082
Line coverage
88%
Covered lines: 623
Uncovered lines: 84
Coverable lines: 707
Total lines: 2293
Line coverage: 88.1%
Branch coverage
78%
Covered branches: 319
Total branches: 406
Branch coverage: 78.5%
Method coverage
93%
Covered methods: 120
Total methods: 129
Method coverage: 93%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%22100%
.ctor(...)100%11100%
.ctor(...)100%11100%
reset()100%11100%
clear()50%3.19233.33%
finished()100%11100%
swap(...)100%11100%
resetEncapsulation()100%11100%
resize(...)100%11100%
startValue(...)100%11100%
endValue()100%11100%
startException()100%11100%
endException()100%11100%
startEncapsulation()100%22100%
startEncapsulation(...)100%44100%
endEncapsulation()100%11100%
writeEmptyEncapsulation(...)100%11100%
writeEncapsulation(...)50%2.03280%
getEncoding()100%22100%
startSlice(...)100%11100%
endSlice()100%11100%
writePendingValues()87.5%88100%
writeSize(...)100%22100%
startSize()100%11100%
endSize(...)100%11100%
writeBlob(...)50%2.03280%
writeBlob(...)0%620%
writeOptional(...)100%22100%
writeByte(...)100%11100%
writeByte(...)100%22100%
writeByte(...)100%22100%
rewriteByte(...)100%11100%
writeByteSeq(...)100%22100%
writeByteSeq(...)71.43%18.861470.83%
writeByteSeq(...)100%44100%
writeByteSeq(...)0%2040%
writeBool(...)100%11100%
writeBool(...)100%22100%
writeBool(...)100%22100%
rewriteBool(...)100%210%
writeBoolSeq(...)100%22100%
writeBoolSeq(...)71.43%18.861470.83%
writeBoolSeq(...)100%44100%
writeBoolSeq(...)0%2040%
writeShort(...)100%11100%
writeShort(...)100%22100%
writeShort(...)100%22100%
writeShortSeq(...)100%22100%
writeShortSeq(...)71.43%18.861470.83%
writeShortSeq(...)87.5%88100%
writeShortSeq(...)87.5%88100%
writeInt(...)100%11100%
writeInt(...)100%22100%
writeInt(...)100%22100%
rewriteInt(...)100%11100%
writeIntSeq(...)100%22100%
writeIntSeq(...)100%1414100%
writeIntSeq(...)75%88100%
writeIntSeq(...)0%7280%
writeLong(...)100%11100%
writeLong(...)100%22100%
writeLong(...)100%22100%
writeLongSeq(...)100%22100%
writeLongSeq(...)71.43%18.861470.83%
writeLongSeq(...)75%88100%
writeLongSeq(...)0%7280%
writeFloat(...)100%11100%
writeFloat(...)100%22100%
writeFloat(...)100%22100%
writeFloatSeq(...)100%22100%
writeFloatSeq(...)71.43%18.861470.83%
writeFloatSeq(...)75%88100%
writeFloatSeq(...)0%7280%
writeDouble(...)100%11100%
writeDouble(...)100%22100%
writeDouble(...)100%22100%
writeDoubleSeq(...)100%22100%
writeDoubleSeq(...)71.43%18.861470.83%
writeDoubleSeq(...)75%88100%
writeDoubleSeq(...)0%7280%
.cctor()100%11100%
writeString(...)100%44100%
writeString(...)100%44100%
writeStringSeq(...)100%44100%
writeStringSeq(...)100%44100%
writeStringSeq(...)100%44100%
writeStringSeq(...)0%2040%
writeProxy(...)100%22100%
writeProxy(...)100%44100%
writeEnum(...)100%66100%
writeEnum(...)100%22100%
writeValue(...)100%11100%
writeException(...)100%11100%
writeOptionalImpl(...)100%44100%
pos()100%11100%
pos(...)100%11100%
size()100%11100%
isEmpty()100%11100%
expand(...)100%11100%
prepareWrite()100%11100%
getBuffer()100%11100%
.ctor(...)100%11100%
writeOptional(...)100%11100%
writePendingValues()100%11100%
registerTypeId(...)100%44100%
.ctor(...)100%11100%
writeValue(...)100%22100%
writeException(...)100%22100%
startInstance(...)100%11100%
endInstance()100%22100%
startSlice(...)100%44100%
endSlice()100%11100%
writePendingValues()100%66100%
registerValue(...)100%44100%
.ctor(...)100%11100%
writeValue(...)100%1010100%
writeException(...)100%11100%
startInstance(...)100%66100%
endInstance()100%11100%
startSlice(...)100%1616100%
endSlice()100%1010100%
writeOptional(...)75%4.07483.33%
writeSlicedData(...)92.86%14.061493.33%
writeInstance(...)100%22100%
.ctor(...)100%22100%
reset()100%11100%
setEncoding(...)100%11100%
isEncoding_1_0()100%22100%
initEncaps()87.5%8.05890.91%

File(s)

/home/runner/work/ice/ice/csharp/src/Ice/OutputStream.cs

#LineLine coverage
 1// Copyright (c) ZeroC, Inc.
 2
 3#nullable enable
 4
 5using System.Diagnostics;
 6
 7using Protocol = Ice.Internal.Protocol;
 8
 9namespace Ice;
 10
 11/// <summary>
 12/// Interface for output streams used to write Slice types to a sequence
 13/// of bytes.
 14/// </summary>
 15public sealed class OutputStream
 16{
 17    /// <summary>
 18    /// Initializes a new instance of the <see cref="OutputStream" /> class. The output stream is initially empty.
 19    /// </summary>
 20    /// <param name="encoding">The encoding version. null is equivalent to encoding 1.1.</param>
 21    /// <param name="format">The class format.</param>
 122    public OutputStream(EncodingVersion? encoding = null, FormatType format = FormatType.CompactFormat)
 23    {
 124        _buf = new Internal.Buffer();
 125        _encoding = encoding ?? Util.currentEncoding;
 126        _format = format;
 127    }
 28
 29    /// <summary>
 30    /// Initializes a new instance of the <see cref="OutputStream" /> class. The output stream is initially empty,
 31    /// and uses the communicator's default encoding version and default class format.
 32    /// </summary>
 33    /// <param name="communicator">The communicator that provides the encoding version and class format.</param>
 34    public OutputStream(Communicator communicator)
 135        : this(
 136            communicator.instance.defaultsAndOverrides().defaultEncoding,
 137            communicator.instance.defaultsAndOverrides().defaultFormat)
 38    {
 139    }
 40
 41    internal OutputStream(
 42        Internal.Buffer buf,
 43        EncodingVersion? encoding = null,
 44        FormatType format = FormatType.CompactFormat)
 145        : this(encoding, format) => _buf = buf;
 46
 47    /// <summary>
 48    /// Resets this output stream. This method allows the stream to be reused, to avoid creating
 49    /// unnecessary garbage.
 50    /// </summary>
 51    public void reset()
 52    {
 153        _buf.reset();
 154        clear();
 155    }
 56
 57    /// <summary>
 58    /// Releases any data retained by encapsulations. The reset() method internally calls clear().
 59    /// </summary>
 60    public void clear()
 61    {
 162        if (_encapsStack != null)
 63        {
 64            Debug.Assert(_encapsStack.next == null);
 065            _encapsStack.next = _encapsCache;
 066            _encapsCache = _encapsStack;
 067            _encapsStack = null;
 068            _encapsCache.reset();
 69        }
 170    }
 71
 72    /// <summary>
 73    /// Indicates that the marshaling of a request or reply is finished.
 74    /// </summary>
 75    /// <returns>The byte sequence containing the encoded request or reply.</returns>
 76    public byte[] finished()
 77    {
 178        Ice.Internal.Buffer buf = prepareWrite();
 179        byte[] result = new byte[buf.b.limit()];
 180        buf.b.get(result);
 181        return result;
 82    }
 83
 84    /// <summary>
 85    /// Swaps the contents of one stream with another.
 86    /// </summary>
 87    /// <param name="other">The other stream.</param>
 88    public void swap(OutputStream other)
 89    {
 190        Ice.Internal.Buffer tmpBuf = other._buf;
 191        other._buf = _buf;
 192        _buf = tmpBuf;
 93
 194        EncodingVersion tmpEncoding = other._encoding;
 195        other._encoding = _encoding;
 196        _encoding = tmpEncoding;
 97
 98        //
 99        // Swap is never called for streams that have encapsulations being written. However,
 100        // encapsulations might still be set in case marshaling failed. We just
 101        // reset the encapsulations if there are still some set.
 102        //
 1103        resetEncapsulation();
 1104        other.resetEncapsulation();
 1105    }
 106
 1107    private void resetEncapsulation() => _encapsStack = null;
 108
 109    /// <summary>
 110    /// Resizes the stream to a new size.
 111    /// </summary>
 112    /// <param name="sz">The new size.</param>
 113    public void resize(int sz)
 114    {
 1115        _buf.resize(sz, false);
 1116        _buf.b.position(sz);
 1117    }
 118
 119    /// <summary>
 120    /// Marks the start of a class instance.
 121    /// </summary>
 122    /// <param name="data">Preserved slices for this instance, or null.</param>
 123    public void startValue(SlicedData? data)
 124    {
 125        Debug.Assert(_encapsStack != null && _encapsStack.encoder != null);
 1126        _encapsStack.encoder.startInstance(SliceType.ValueSlice, data);
 1127    }
 128
 129    /// <summary>
 130    /// Marks the end of a class instance.
 131    /// </summary>
 132    public void endValue()
 133    {
 134        Debug.Assert(_encapsStack != null && _encapsStack.encoder != null);
 1135        _encapsStack.encoder.endInstance();
 1136    }
 137
 138    /// <summary>
 139    /// Marks the start of a user exception.
 140    /// </summary>
 141    public void startException()
 142    {
 143        Debug.Assert(_encapsStack != null && _encapsStack.encoder != null);
 1144        _encapsStack.encoder.startInstance(SliceType.ExceptionSlice, null);
 1145    }
 146
 147    /// <summary>
 148    /// Marks the end of a user exception.
 149    /// </summary>
 150    public void endException()
 151    {
 152        Debug.Assert(_encapsStack != null && _encapsStack.encoder != null);
 1153        _encapsStack.encoder.endInstance();
 1154    }
 155
 156    /// <summary>
 157    /// Writes the start of an encapsulation to the stream.
 158    /// </summary>
 159    public void startEncapsulation()
 160    {
 161        //
 162        // If no encoding version is specified, use the current write
 163        // encapsulation encoding version if there's a current write
 164        // encapsulation, otherwise, use the stream encoding version.
 165        //
 166
 1167        if (_encapsStack != null)
 168        {
 1169            startEncapsulation(_encapsStack.encoding, _encapsStack.format);
 170        }
 171        else
 172        {
 1173            startEncapsulation(_encoding, format: null);
 174        }
 1175    }
 176
 177    /// <summary>
 178    /// Writes the start of an encapsulation to the stream.
 179    /// </summary>
 180    /// <param name="encoding">The encoding version of the encapsulation.</param>
 181    /// <param name="format">Specify the compact or sliced format. When null, use the OutputStream's class format.
 182    /// </param>
 183    public void startEncapsulation(EncodingVersion encoding, FormatType? format = null)
 184    {
 1185        Protocol.checkSupportedEncoding(encoding);
 186
 1187        Encaps? curr = _encapsCache;
 1188        if (curr != null)
 189        {
 1190            curr.reset();
 1191            _encapsCache = _encapsCache!.next;
 192        }
 193        else
 194        {
 1195            curr = new Encaps();
 196        }
 1197        curr.next = _encapsStack;
 1198        _encapsStack = curr;
 199
 1200        _encapsStack.format = format ?? _format;
 1201        _encapsStack.setEncoding(encoding);
 1202        _encapsStack.start = _buf.b.position();
 203
 1204        writeInt(0); // Placeholder for the encapsulation length.
 1205        EncodingVersion.ice_write(this, _encapsStack.encoding);
 1206    }
 207
 208    /// <summary>
 209    /// Ends the previous encapsulation.
 210    /// </summary>
 211    public void endEncapsulation()
 212    {
 213        Debug.Assert(_encapsStack != null);
 214
 215        // Size includes size and version.
 1216        int start = _encapsStack.start;
 1217        int sz = _buf.size() - start;
 1218        _buf.b.putInt(start, sz);
 219
 1220        Encaps curr = _encapsStack;
 1221        _encapsStack = curr.next;
 1222        curr.next = _encapsCache;
 1223        _encapsCache = curr;
 1224        _encapsCache.reset();
 1225    }
 226
 227    /// <summary>
 228    /// Writes an empty encapsulation using the given encoding version.
 229    /// </summary>
 230    /// <param name="encoding">The encoding version of the encapsulation.</param>
 231    public void writeEmptyEncapsulation(EncodingVersion encoding)
 232    {
 1233        Protocol.checkSupportedEncoding(encoding);
 1234        writeInt(6); // Size
 1235        EncodingVersion.ice_write(this, encoding);
 1236    }
 237
 238    /// <summary>
 239    /// Writes a pre-encoded encapsulation.
 240    /// </summary>
 241    /// <param name="v">The encapsulation data.</param>
 242    public void writeEncapsulation(byte[] v)
 243    {
 1244        if (v.Length < 6)
 245        {
 0246            throw new MarshalException($"A byte sequence with {v.Length} bytes is not a valid encapsulation.");
 247        }
 1248        expand(v.Length);
 1249        _buf.b.put(v);
 1250    }
 251
 252    /// <summary>
 253    /// Determines the current encoding version.
 254    /// </summary>
 255    /// <returns>The encoding version.</returns>
 1256    public EncodingVersion getEncoding() => _encapsStack != null ? _encapsStack.encoding : _encoding;
 257
 258    /// <summary>
 259    /// Marks the start of a new slice for a class instance or user exception.
 260    /// </summary>
 261    /// <param name="typeId">The Slice type ID corresponding to this slice.</param>
 262    /// <param name="compactId">The Slice compact type ID corresponding to this slice or -1 if no compact ID
 263    /// is defined for the type ID.</param>
 264    /// <param name="last">True if this is the last slice, false otherwise.</param>
 265    public void startSlice(string typeId, int compactId, bool last)
 266    {
 267        Debug.Assert(_encapsStack != null && _encapsStack.encoder != null);
 1268        _encapsStack.encoder.startSlice(typeId, compactId, last);
 1269    }
 270
 271    /// <summary>
 272    /// Marks the end of a slice for a class instance or user exception.
 273    /// </summary>
 274    public void endSlice()
 275    {
 276        Debug.Assert(_encapsStack != null && _encapsStack.encoder != null);
 1277        _encapsStack.encoder.endSlice();
 1278    }
 279
 280    /// <summary>
 281    /// Writes the state of Slice classes whose index was previously written with writeValue() to the stream.
 282    /// </summary>
 283    public void writePendingValues()
 284    {
 1285        if (_encapsStack != null && _encapsStack.encoder != null)
 286        {
 1287            _encapsStack.encoder.writePendingValues();
 288        }
 1289        else if (_encapsStack != null ?
 1290                _encapsStack.encoding_1_0 : _encoding.Equals(Util.Encoding_1_0))
 291        {
 292            //
 293            // If using the 1.0 encoding and no instances were written, we
 294            // still write an empty sequence for pending instances if
 295            // requested (i.e.: if this is called).
 296            //
 297            // This is required by the 1.0 encoding, even if no instances
 298            // are written we do marshal an empty sequence if marshaled
 299            // data types use classes.
 300            //
 1301            writeSize(0);
 302        }
 1303    }
 304
 305    /// <summary>
 306    /// Writes a size to the stream.
 307    /// </summary>
 308    /// <param name="v">The size to write.</param>
 309    public void writeSize(int v)
 310    {
 1311        if (v > 254)
 312        {
 1313            expand(5);
 1314            _buf.b.put(255);
 1315            _buf.b.putInt(v);
 316        }
 317        else
 318        {
 1319            expand(1);
 1320            _buf.b.put((byte)v);
 321        }
 1322    }
 323
 324    /// <summary>
 325    /// Returns the current position and allocates four bytes for a fixed-length (32-bit) size value.
 326    /// </summary>
 327    /// <returns>The position at which to store the size value.</returns>
 328    public int startSize()
 329    {
 1330        int pos = _buf.b.position();
 1331        writeInt(0); // Placeholder for 32-bit size
 1332        return pos;
 333    }
 334
 335    /// <summary>
 336    /// Computes the amount of data written since the previous call to startSize and writes that value
 337    /// at the saved position.
 338    /// </summary>
 339    /// <param name="pos">The saved position.</param>
 340    public void endSize(int pos)
 341    {
 342        Debug.Assert(pos >= 0);
 1343        rewriteInt(_buf.b.position() - pos - 4, pos);
 1344    }
 345
 346    /// <summary>
 347    /// Writes a blob of bytes to the stream.
 348    /// </summary>
 349    /// <param name="v">The byte array to be written. All of the bytes in the array are written.</param>
 350    public void writeBlob(byte[] v)
 351    {
 1352        if (v == null)
 353        {
 0354            return;
 355        }
 1356        expand(v.Length);
 1357        _buf.b.put(v);
 1358    }
 359
 360    /// <summary>
 361    /// Writes a blob of bytes to the stream.
 362    /// </summary>
 363    /// <param name="v">The byte array to be written. All of the bytes in the array are written.</param>
 364    /// <param name="off">The offset into the byte array from which to copy.</param>
 365    /// <param name="len">The number of bytes from the byte array to copy.</param>
 366    public void writeBlob(byte[] v, int off, int len)
 367    {
 0368        if (v == null)
 369        {
 0370            return;
 371        }
 0372        expand(len);
 0373        _buf.b.put(v, off, len);
 0374    }
 375
 376    /// <summary>
 377    /// Write the header information for an optional value.
 378    /// </summary>
 379    /// <param name="tag">The numeric tag associated with the value.</param>
 380    /// <param name="format">The optional format of the value.</param>
 381    /// <returns><c>true</c> if the encoding supports optional values and the header information was written to the stre
 382    /// <c>false</c> otherwise.</returns>
 383    public bool writeOptional(int tag, OptionalFormat format)
 384    {
 385        Debug.Assert(_encapsStack != null);
 1386        if (_encapsStack.encoder != null)
 387        {
 1388            return _encapsStack.encoder.writeOptional(tag, format);
 389        }
 390        else
 391        {
 1392            return writeOptionalImpl(tag, format);
 393        }
 394    }
 395
 396    /// <summary>
 397    /// Writes a byte to the stream.
 398    /// </summary>
 399    /// <param name="v">The byte to write to the stream.</param>
 400    public void writeByte(byte v)
 401    {
 1402        expand(1);
 1403        _buf.b.put(v);
 1404    }
 405
 406    /// <summary>
 407    /// Writes an optional byte to the stream.
 408    /// </summary>
 409    /// <param name="tag">The optional tag.</param>
 410    /// <param name="v">The optional byte to write to the stream.</param>
 411    public void writeByte(int tag, byte? v)
 412    {
 1413        if (v.HasValue)
 414        {
 1415            writeByte(tag, v.Value);
 416        }
 1417    }
 418
 419    /// <summary>
 420    /// Writes an optional byte to the stream.
 421    /// </summary>
 422    /// <param name="tag">The optional tag.</param>
 423    /// <param name="v">The byte to write to the stream.</param>
 424    public void writeByte(int tag, byte v)
 425    {
 1426        if (writeOptional(tag, OptionalFormat.F1))
 427        {
 1428            writeByte(v);
 429        }
 1430    }
 431
 432    /// <summary>
 433    /// Writes a byte to the stream at the given position. The current position of the stream is not modified.
 434    /// </summary>
 435    /// <param name="v">The byte to write to the stream.</param>
 436    /// <param name="dest">The position at which to store the byte in the buffer.</param>
 1437    public void rewriteByte(byte v, int dest) => _buf.b.put(dest, v);
 438
 439    /// <summary>
 440    /// Writes a byte sequence to the stream.
 441    /// </summary>
 442    /// <param name="v">The byte sequence to write to the stream.
 443    /// Passing null causes an empty sequence to be written to the stream.</param>
 444    public void writeByteSeq(byte[] v)
 445    {
 1446        if (v == null)
 447        {
 1448            writeSize(0);
 449        }
 450        else
 451        {
 1452            writeSize(v.Length);
 1453            expand(v.Length);
 1454            _buf.b.put(v);
 455        }
 1456    }
 457
 458    /// <summary>
 459    /// Writes a byte sequence to the stream.
 460    /// </summary>
 461    /// <param name="count">The number of elements in the sequence.</param>
 462    /// <param name="v">An enumerator for the container holding the sequence.</param>
 463    public void writeByteSeq(int count, IEnumerable<byte> v)
 464    {
 1465        if (count == 0)
 466        {
 0467            writeSize(0);
 0468            return;
 469        }
 470
 471        {
 1472            if (v is List<byte> value)
 473            {
 1474                writeByteSeq(value.ToArray());
 1475                return;
 476            }
 477        }
 478
 479        {
 1480            if (v is LinkedList<byte>)
 481            {
 1482                writeSize(count);
 1483                expand(count);
 1484                IEnumerator<byte> i = v.GetEnumerator();
 1485                while (i.MoveNext())
 486                {
 1487                    _buf.b.put(i.Current);
 488                }
 1489                return;
 490            }
 491        }
 492
 493        {
 1494            if (v is Queue<byte> value)
 495            {
 1496                writeByteSeq(value.ToArray());
 1497                return;
 498            }
 499        }
 500
 501        {
 1502            if (v is Stack<byte> value)
 503            {
 1504                writeByteSeq(value.ToArray());
 1505                return;
 506            }
 507        }
 508
 0509        writeSize(count);
 0510        expand(count);
 0511        foreach (byte b in v)
 512        {
 0513            _buf.b.put(b);
 514        }
 0515    }
 516
 517    /// <summary>
 518    /// Writes an optional byte sequence to the stream.
 519    /// </summary>
 520    /// <param name="tag">The optional tag.</param>
 521    /// <param name="v">The byte sequence to write to the stream.</param>
 522    public void writeByteSeq(int tag, byte[]? v)
 523    {
 1524        if (v is not null && writeOptional(tag, OptionalFormat.VSize))
 525        {
 1526            writeByteSeq(v);
 527        }
 1528    }
 529
 530    /// <summary>
 531    /// Writes an optional byte sequence to the stream.
 532    /// </summary>
 533    /// <param name="tag">The optional tag.</param>
 534    /// <param name="count">The number of elements in the sequence.</param>
 535    /// <param name="v">An enumerator for the byte sequence.</param>
 536    public void writeByteSeq(int tag, int count, IEnumerable<byte>? v)
 537    {
 0538        if (v is not null && writeOptional(tag, OptionalFormat.VSize))
 539        {
 0540            writeByteSeq(count, v);
 541        }
 0542    }
 543
 544    /// <summary>
 545    /// Writes a boolean to the stream.
 546    /// </summary>
 547    /// <param name="v">The boolean to write to the stream.</param>
 548    public void writeBool(bool v)
 549    {
 1550        expand(1);
 1551        _buf.b.put(v ? (byte)1 : (byte)0);
 1552    }
 553
 554    /// <summary>
 555    /// Writes an optional boolean to the stream.
 556    /// </summary>
 557    /// <param name="tag">The optional tag.</param>
 558    /// <param name="v">The optional boolean to write to the stream.</param>
 559    public void writeBool(int tag, bool? v)
 560    {
 1561        if (v.HasValue)
 562        {
 1563            writeBool(tag, v.Value);
 564        }
 1565    }
 566
 567    /// <summary>
 568    /// Writes an optional boolean to the stream.
 569    /// </summary>
 570    /// <param name="tag">The optional tag.</param>
 571    /// <param name="v">The boolean to write to the stream.</param>
 572    public void writeBool(int tag, bool v)
 573    {
 1574        if (writeOptional(tag, OptionalFormat.F1))
 575        {
 1576            writeBool(v);
 577        }
 1578    }
 579
 580    /// <summary>
 581    /// Writes a boolean to the stream at the given position. The current position of the stream is not modified.
 582    /// </summary>
 583    /// <param name="v">The boolean to write to the stream.</param>
 584    /// <param name="dest">The position at which to store the boolean in the buffer.</param>
 0585    public void rewriteBool(bool v, int dest) => _buf.b.put(dest, v ? (byte)1 : (byte)0);
 586
 587    /// <summary>
 588    /// Writes a boolean sequence to the stream.
 589    /// </summary>
 590    /// <param name="v">The boolean sequence to write to the stream.
 591    /// Passing null causes an empty sequence to be written to the stream.</param>
 592    public void writeBoolSeq(bool[] v)
 593    {
 1594        if (v == null)
 595        {
 1596            writeSize(0);
 597        }
 598        else
 599        {
 1600            writeSize(v.Length);
 1601            expand(v.Length);
 1602            _buf.b.putBoolSeq(v);
 603        }
 1604    }
 605
 606    /// <summary>
 607    /// Writes a boolean sequence to the stream.
 608    /// </summary>
 609    /// <param name="count">The number of elements in the sequence.</param>
 610    /// <param name="v">An enumerator for the container holding the sequence.</param>
 611    public void writeBoolSeq(int count, IEnumerable<bool> v)
 612    {
 1613        if (count == 0)
 614        {
 0615            writeSize(0);
 0616            return;
 617        }
 618
 619        {
 1620            if (v is List<bool> value)
 621            {
 1622                writeBoolSeq(value.ToArray());
 1623                return;
 624            }
 625        }
 626
 627        {
 1628            if (v is LinkedList<bool>)
 629            {
 1630                writeSize(count);
 1631                expand(count);
 1632                IEnumerator<bool> i = v.GetEnumerator();
 1633                while (i.MoveNext())
 634                {
 1635                    _buf.b.putBool(i.Current);
 636                }
 1637                return;
 638            }
 639        }
 640
 641        {
 1642            if (v is Queue<bool> value)
 643            {
 1644                writeBoolSeq(value.ToArray());
 1645                return;
 646            }
 647        }
 648
 649        {
 1650            if (v is Stack<bool> value)
 651            {
 1652                writeBoolSeq(value.ToArray());
 1653                return;
 654            }
 655        }
 656
 0657        writeSize(count);
 0658        expand(count);
 0659        foreach (bool b in v)
 660        {
 0661            _buf.b.putBool(b);
 662        }
 0663    }
 664
 665    /// <summary>
 666    /// Writes an optional boolean sequence to the stream.
 667    /// </summary>
 668    /// <param name="tag">The optional tag.</param>
 669    /// <param name="v">The boolean sequence to write to the stream.</param>
 670    public void writeBoolSeq(int tag, bool[]? v)
 671    {
 1672        if (v is not null && writeOptional(tag, OptionalFormat.VSize))
 673        {
 1674            writeBoolSeq(v);
 675        }
 1676    }
 677
 678    /// <summary>
 679    /// Writes an optional boolean sequence to the stream.
 680    /// </summary>
 681    /// <param name="tag">The optional tag.</param>
 682    /// <param name="count">The number of elements in the sequence.</param>
 683    /// <param name="v">An enumerator for the boolean sequence.</param>
 684    public void writeBoolSeq(int tag, int count, IEnumerable<bool>? v)
 685    {
 0686        if (v is not null && writeOptional(tag, OptionalFormat.VSize))
 687        {
 0688            writeBoolSeq(count, v);
 689        }
 0690    }
 691
 692    /// <summary>
 693    /// Writes a short to the stream.
 694    /// </summary>
 695    /// <param name="v">The short to write to the stream.</param>
 696    public void writeShort(short v)
 697    {
 1698        expand(2);
 1699        _buf.b.putShort(v);
 1700    }
 701
 702    /// <summary>
 703    /// Writes an optional short to the stream.
 704    /// </summary>
 705    /// <param name="tag">The optional tag.</param>
 706    /// <param name="v">The optional short to write to the stream.</param>
 707    public void writeShort(int tag, short? v)
 708    {
 1709        if (v.HasValue)
 710        {
 1711            writeShort(tag, v.Value);
 712        }
 1713    }
 714
 715    /// <summary>
 716    /// Writes an optional short to the stream.
 717    /// </summary>
 718    /// <param name="tag">The optional tag.</param>
 719    /// <param name="v">The short to write to the stream.</param>
 720    public void writeShort(int tag, short v)
 721    {
 1722        if (writeOptional(tag, OptionalFormat.F2))
 723        {
 1724            writeShort(v);
 725        }
 1726    }
 727
 728    /// <summary>
 729    /// Writes a short sequence to the stream.
 730    /// </summary>
 731    /// <param name="v">The short sequence to write to the stream.
 732    /// Passing null causes an empty sequence to be written to the stream.</param>
 733    public void writeShortSeq(short[] v)
 734    {
 1735        if (v == null)
 736        {
 1737            writeSize(0);
 738        }
 739        else
 740        {
 1741            writeSize(v.Length);
 1742            expand(v.Length * 2);
 1743            _buf.b.putShortSeq(v);
 744        }
 1745    }
 746
 747    /// <summary>
 748    /// Writes a short sequence to the stream.
 749    /// </summary>
 750    /// <param name="count">The number of elements in the sequence.</param>
 751    /// <param name="v">An enumerator for the container holding the sequence.</param>
 752    public void writeShortSeq(int count, IEnumerable<short> v)
 753    {
 1754        if (count == 0)
 755        {
 0756            writeSize(0);
 0757            return;
 758        }
 759
 760        {
 1761            if (v is List<short> value)
 762            {
 1763                writeShortSeq(value.ToArray());
 1764                return;
 765            }
 766        }
 767
 768        {
 1769            if (v is LinkedList<short>)
 770            {
 1771                writeSize(count);
 1772                expand(count * 2);
 1773                IEnumerator<short> i = v.GetEnumerator();
 1774                while (i.MoveNext())
 775                {
 1776                    _buf.b.putShort(i.Current);
 777                }
 1778                return;
 779            }
 780        }
 781
 782        {
 1783            if (v is Queue<short> value)
 784            {
 1785                writeShortSeq(value.ToArray());
 1786                return;
 787            }
 788        }
 789
 790        {
 1791            if (v is Stack<short> value)
 792            {
 1793                writeShortSeq(value.ToArray());
 1794                return;
 795            }
 796        }
 797
 0798        writeSize(count);
 0799        expand(count * 2);
 0800        foreach (short s in v)
 801        {
 0802            _buf.b.putShort(s);
 803        }
 0804    }
 805
 806    /// <summary>
 807    /// Writes an optional short sequence to the stream.
 808    /// </summary>
 809    /// <param name="tag">The optional tag.</param>
 810    /// <param name="v">The short sequence to write to the stream.</param>
 811    public void writeShortSeq(int tag, short[]? v)
 812    {
 1813        if (v is not null && writeOptional(tag, OptionalFormat.VSize))
 814        {
 1815            writeSize(v.Length == 0 ? 1 : (v.Length * 2) + (v.Length > 254 ? 5 : 1));
 1816            writeShortSeq(v);
 817        }
 1818    }
 819
 820    /// <summary>
 821    /// Writes an optional short sequence to the stream.
 822    /// </summary>
 823    /// <param name="tag">The optional tag.</param>
 824    /// <param name="count">The number of elements in the sequence.</param>
 825    /// <param name="v">An enumerator for the short sequence.</param>
 826    public void writeShortSeq(int tag, int count, IEnumerable<short>? v)
 827    {
 1828        if (v is not null && writeOptional(tag, OptionalFormat.VSize))
 829        {
 1830            writeSize(count == 0 ? 1 : (count * 2) + (count > 254 ? 5 : 1));
 1831            writeShortSeq(count, v);
 832        }
 1833    }
 834
 835    /// <summary>
 836    /// Writes an int to the stream.
 837    /// </summary>
 838    /// <param name="v">The int to write to the stream.</param>
 839    public void writeInt(int v)
 840    {
 1841        expand(4);
 1842        _buf.b.putInt(v);
 1843    }
 844
 845    /// <summary>
 846    /// Writes an optional int to the stream.
 847    /// </summary>
 848    /// <param name="tag">The optional tag.</param>
 849    /// <param name="v">The optional int to write to the stream.</param>
 850    public void writeInt(int tag, int? v)
 851    {
 1852        if (v.HasValue)
 853        {
 1854            writeInt(tag, v.Value);
 855        }
 1856    }
 857
 858    /// <summary>
 859    /// Writes an optional int to the stream.
 860    /// </summary>
 861    /// <param name="tag">The optional tag.</param>
 862    /// <param name="v">The int to write to the stream.</param>
 863    public void writeInt(int tag, int v)
 864    {
 1865        if (writeOptional(tag, OptionalFormat.F4))
 866        {
 1867            writeInt(v);
 868        }
 1869    }
 870
 871    /// <summary>
 872    /// Writes an int to the stream at the given position. The current position of the stream is not modified.
 873    /// </summary>
 874    /// <param name="v">The int to write to the stream.</param>
 875    /// <param name="dest">The position at which to store the int in the buffer.</param>
 1876    public void rewriteInt(int v, int dest) => _buf.b.putInt(dest, v);
 877
 878    /// <summary>
 879    /// Writes an int sequence to the stream.
 880    /// </summary>
 881    /// <param name="v">The int sequence to write to the stream.
 882    /// Passing null causes an empty sequence to be written to the stream.</param>
 883    public void writeIntSeq(int[] v)
 884    {
 1885        if (v == null)
 886        {
 1887            writeSize(0);
 888        }
 889        else
 890        {
 1891            writeSize(v.Length);
 1892            expand(v.Length * 4);
 1893            _buf.b.putIntSeq(v);
 894        }
 1895    }
 896
 897    /// <summary>
 898    /// Writes an int sequence to the stream.
 899    /// </summary>
 900    /// <param name="count">The number of elements in the sequence.</param>
 901    /// <param name="v">An enumerator for the container holding the sequence.</param>
 902    public void writeIntSeq(int count, IEnumerable<int> v)
 903    {
 1904        if (count == 0)
 905        {
 1906            writeSize(0);
 1907            return;
 908        }
 909
 910        {
 1911            if (v is List<int> value)
 912            {
 1913                writeIntSeq(value.ToArray());
 1914                return;
 915            }
 916        }
 917
 918        {
 1919            if (v is LinkedList<int>)
 920            {
 1921                writeSize(count);
 1922                expand(count * 4);
 1923                IEnumerator<int> i = v.GetEnumerator();
 1924                while (i.MoveNext())
 925                {
 1926                    _buf.b.putInt(i.Current);
 927                }
 1928                return;
 929            }
 930        }
 931
 932        {
 1933            if (v is Queue<int> value)
 934            {
 1935                writeIntSeq(value.ToArray());
 1936                return;
 937            }
 938        }
 939
 940        {
 1941            if (v is Stack<int> value)
 942            {
 1943                writeIntSeq(value.ToArray());
 1944                return;
 945            }
 946        }
 947
 1948        writeSize(count);
 1949        expand(count * 4);
 1950        foreach (int i in v)
 951        {
 1952            _buf.b.putInt(i);
 953        }
 1954    }
 955
 956    /// <summary>
 957    /// Writes an optional int sequence to the stream.
 958    /// </summary>
 959    /// <param name="tag">The optional tag.</param>
 960    /// <param name="v">The int sequence to write to the stream.</param>
 961    public void writeIntSeq(int tag, int[]? v)
 962    {
 1963        if (v is not null && writeOptional(tag, OptionalFormat.VSize))
 964        {
 1965            writeSize(v.Length == 0 ? 1 : (v.Length * 4) + (v.Length > 254 ? 5 : 1));
 1966            writeIntSeq(v);
 967        }
 1968    }
 969
 970    /// <summary>
 971    /// Writes an optional int sequence to the stream.
 972    /// </summary>
 973    /// <param name="tag">The optional tag.</param>
 974    /// <param name="count">The number of elements in the sequence.</param>
 975    /// <param name="v">An enumerator for the int sequence.</param>
 976    public void writeIntSeq(int tag, int count, IEnumerable<int>? v)
 977    {
 0978        if (v is not null && writeOptional(tag, OptionalFormat.VSize))
 979        {
 0980            writeSize(count == 0 ? 1 : (count * 4) + (count > 254 ? 5 : 1));
 0981            writeIntSeq(count, v);
 982        }
 0983    }
 984
 985    /// <summary>
 986    /// Writes a long to the stream.
 987    /// </summary>
 988    /// <param name="v">The long to write to the stream.</param>
 989    public void writeLong(long v)
 990    {
 1991        expand(8);
 1992        _buf.b.putLong(v);
 1993    }
 994
 995    /// <summary>
 996    /// Writes an optional long to the stream.
 997    /// </summary>
 998    /// <param name="tag">The optional tag.</param>
 999    /// <param name="v">The optional long to write to the stream.</param>
 1000    public void writeLong(int tag, long? v)
 1001    {
 11002        if (v.HasValue)
 1003        {
 11004            writeLong(tag, v.Value);
 1005        }
 11006    }
 1007
 1008    /// <summary>
 1009    /// Writes an optional long to the stream.
 1010    /// </summary>
 1011    /// <param name="tag">The optional tag.</param>
 1012    /// <param name="v">The long to write to the stream.</param>
 1013    public void writeLong(int tag, long v)
 1014    {
 11015        if (writeOptional(tag, OptionalFormat.F8))
 1016        {
 11017            writeLong(v);
 1018        }
 11019    }
 1020
 1021    /// <summary>
 1022    /// Writes a long sequence to the stream.
 1023    /// </summary>
 1024    /// <param name="v">The long sequence to write to the stream.
 1025    /// Passing null causes an empty sequence to be written to the stream.</param>
 1026    public void writeLongSeq(long[] v)
 1027    {
 11028        if (v == null)
 1029        {
 11030            writeSize(0);
 1031        }
 1032        else
 1033        {
 11034            writeSize(v.Length);
 11035            expand(v.Length * 8);
 11036            _buf.b.putLongSeq(v);
 1037        }
 11038    }
 1039
 1040    /// <summary>
 1041    /// Writes a long sequence to the stream.
 1042    /// </summary>
 1043    /// <param name="count">The number of elements in the sequence.</param>
 1044    /// <param name="v">An enumerator for the container holding the sequence.</param>
 1045    public void writeLongSeq(int count, IEnumerable<long> v)
 1046    {
 11047        if (count == 0)
 1048        {
 01049            writeSize(0);
 01050            return;
 1051        }
 1052
 1053        {
 11054            if (v is List<long> value)
 1055            {
 11056                writeLongSeq(value.ToArray());
 11057                return;
 1058            }
 1059        }
 1060
 1061        {
 11062            if (v is LinkedList<long>)
 1063            {
 11064                writeSize(count);
 11065                expand(count * 8);
 11066                IEnumerator<long> i = v.GetEnumerator();
 11067                while (i.MoveNext())
 1068                {
 11069                    _buf.b.putLong(i.Current);
 1070                }
 11071                return;
 1072            }
 1073        }
 1074
 1075        {
 11076            if (v is Queue<long> value)
 1077            {
 11078                writeLongSeq(value.ToArray());
 11079                return;
 1080            }
 1081        }
 1082
 1083        {
 11084            if (v is Stack<long> value)
 1085            {
 11086                writeLongSeq(value.ToArray());
 11087                return;
 1088            }
 1089        }
 1090
 01091        writeSize(count);
 01092        expand(count * 8);
 01093        foreach (long l in v)
 1094        {
 01095            _buf.b.putLong(l);
 1096        }
 01097    }
 1098
 1099    /// <summary>
 1100    /// Writes an optional long sequence to the stream.
 1101    /// </summary>
 1102    /// <param name="tag">The optional tag.</param>
 1103    /// <param name="v">The long sequence to write to the stream.</param>
 1104    public void writeLongSeq(int tag, long[]? v)
 1105    {
 11106        if (v is not null && writeOptional(tag, OptionalFormat.VSize))
 1107        {
 11108            writeSize(v.Length == 0 ? 1 : (v.Length * 8) + (v.Length > 254 ? 5 : 1));
 11109            writeLongSeq(v);
 1110        }
 11111    }
 1112
 1113    /// <summary>
 1114    /// Writes an optional long sequence to the stream.
 1115    /// </summary>
 1116    /// <param name="tag">The optional tag.</param>
 1117    /// <param name="count">The number of elements in the sequence.</param>
 1118    /// <param name="v">An enumerator for the long sequence.</param>
 1119    public void writeLongSeq(int tag, int count, IEnumerable<long>? v)
 1120    {
 01121        if (v is not null && writeOptional(tag, OptionalFormat.VSize))
 1122        {
 01123            writeSize(count == 0 ? 1 : (count * 8) + (count > 254 ? 5 : 1));
 01124            writeLongSeq(count, v);
 1125        }
 01126    }
 1127
 1128    /// <summary>
 1129    /// Writes a float to the stream.
 1130    /// </summary>
 1131    /// <param name="v">The float to write to the stream.</param>
 1132    public void writeFloat(float v)
 1133    {
 11134        expand(4);
 11135        _buf.b.putFloat(v);
 11136    }
 1137
 1138    /// <summary>
 1139    /// Writes an optional float to the stream.
 1140    /// </summary>
 1141    /// <param name="tag">The optional tag.</param>
 1142    /// <param name="v">The optional float to write to the stream.</param>
 1143    public void writeFloat(int tag, float? v)
 1144    {
 11145        if (v.HasValue)
 1146        {
 11147            writeFloat(tag, v.Value);
 1148        }
 11149    }
 1150
 1151    /// <summary>
 1152    /// Writes an optional float to the stream.
 1153    /// </summary>
 1154    /// <param name="tag">The optional tag.</param>
 1155    /// <param name="v">The float to write to the stream.</param>
 1156    public void writeFloat(int tag, float v)
 1157    {
 11158        if (writeOptional(tag, OptionalFormat.F4))
 1159        {
 11160            writeFloat(v);
 1161        }
 11162    }
 1163
 1164    /// <summary>
 1165    /// Writes a float sequence to the stream.
 1166    /// </summary>
 1167    /// <param name="v">The float sequence to write to the stream.
 1168    /// Passing null causes an empty sequence to be written to the stream.</param>
 1169    public void writeFloatSeq(float[] v)
 1170    {
 11171        if (v == null)
 1172        {
 11173            writeSize(0);
 1174        }
 1175        else
 1176        {
 11177            writeSize(v.Length);
 11178            expand(v.Length * 4);
 11179            _buf.b.putFloatSeq(v);
 1180        }
 11181    }
 1182
 1183    /// <summary>
 1184    /// Writes a float sequence to the stream.
 1185    /// </summary>
 1186    /// <param name="count">The number of elements in the sequence.</param>
 1187    /// <param name="v">An enumerator for the container holding the sequence.</param>
 1188    public void writeFloatSeq(int count, IEnumerable<float> v)
 1189    {
 11190        if (count == 0)
 1191        {
 01192            writeSize(0);
 01193            return;
 1194        }
 1195
 1196        {
 11197            if (v is List<float> value)
 1198            {
 11199                writeFloatSeq(value.ToArray());
 11200                return;
 1201            }
 1202        }
 1203
 1204        {
 11205            if (v is LinkedList<float>)
 1206            {
 11207                writeSize(count);
 11208                expand(count * 4);
 11209                IEnumerator<float> i = v.GetEnumerator();
 11210                while (i.MoveNext())
 1211                {
 11212                    _buf.b.putFloat(i.Current);
 1213                }
 11214                return;
 1215            }
 1216        }
 1217
 1218        {
 11219            if (v is Queue<float> value)
 1220            {
 11221                writeFloatSeq(value.ToArray());
 11222                return;
 1223            }
 1224        }
 1225
 1226        {
 11227            if (v is Stack<float> value)
 1228            {
 11229                writeFloatSeq(value.ToArray());
 11230                return;
 1231            }
 1232        }
 1233
 01234        writeSize(count);
 01235        expand(count * 4);
 01236        foreach (float f in v)
 1237        {
 01238            _buf.b.putFloat(f);
 1239        }
 01240    }
 1241
 1242    /// <summary>
 1243    /// Writes an optional float sequence to the stream.
 1244    /// </summary>
 1245    /// <param name="tag">The optional tag.</param>
 1246    /// <param name="v">The float sequence to write to the stream.</param>
 1247    public void writeFloatSeq(int tag, float[]? v)
 1248    {
 11249        if (v is not null && writeOptional(tag, OptionalFormat.VSize))
 1250        {
 11251            writeSize(v.Length == 0 ? 1 : (v.Length * 4) + (v.Length > 254 ? 5 : 1));
 11252            writeFloatSeq(v);
 1253        }
 11254    }
 1255
 1256    /// <summary>
 1257    /// Writes an optional float sequence to the stream.
 1258    /// </summary>
 1259    /// <param name="tag">The optional tag.</param>
 1260    /// <param name="count">The number of elements in the sequence.</param>
 1261    /// <param name="v">An enumerator for the float sequence.</param>
 1262    public void writeFloatSeq(int tag, int count, IEnumerable<float>? v)
 1263    {
 01264        if (v is not null && writeOptional(tag, OptionalFormat.VSize))
 1265        {
 01266            writeSize(count == 0 ? 1 : (count * 4) + (count > 254 ? 5 : 1));
 01267            writeFloatSeq(count, v);
 1268        }
 01269    }
 1270
 1271    /// <summary>
 1272    /// Writes a double to the stream.
 1273    /// </summary>
 1274    /// <param name="v">The double to write to the stream.</param>
 1275    public void writeDouble(double v)
 1276    {
 11277        expand(8);
 11278        _buf.b.putDouble(v);
 11279    }
 1280
 1281    /// <summary>
 1282    /// Writes an optional double to the stream.
 1283    /// </summary>
 1284    /// <param name="tag">The optional tag.</param>
 1285    /// <param name="v">The optional double to write to the stream.</param>
 1286    public void writeDouble(int tag, double? v)
 1287    {
 11288        if (v.HasValue)
 1289        {
 11290            writeDouble(tag, v.Value);
 1291        }
 11292    }
 1293
 1294    /// <summary>
 1295    /// Writes an optional double to the stream.
 1296    /// </summary>
 1297    /// <param name="tag">The optional tag.</param>
 1298    /// <param name="v">The double to write to the stream.</param>
 1299    public void writeDouble(int tag, double v)
 1300    {
 11301        if (writeOptional(tag, OptionalFormat.F8))
 1302        {
 11303            writeDouble(v);
 1304        }
 11305    }
 1306
 1307    /// <summary>
 1308    /// Writes a double sequence to the stream.
 1309    /// </summary>
 1310    /// <param name="v">The double sequence to write to the stream.
 1311    /// Passing null causes an empty sequence to be written to the stream.</param>
 1312    public void writeDoubleSeq(double[] v)
 1313    {
 11314        if (v == null)
 1315        {
 11316            writeSize(0);
 1317        }
 1318        else
 1319        {
 11320            writeSize(v.Length);
 11321            expand(v.Length * 8);
 11322            _buf.b.putDoubleSeq(v);
 1323        }
 11324    }
 1325
 1326    /// <summary>
 1327    /// Writes a double sequence to the stream.
 1328    /// </summary>
 1329    /// <param name="count">The number of elements in the sequence.</param>
 1330    /// <param name="v">An enumerator for the container holding the sequence.</param>
 1331    public void writeDoubleSeq(int count, IEnumerable<double> v)
 1332    {
 11333        if (count == 0)
 1334        {
 01335            writeSize(0);
 01336            return;
 1337        }
 1338
 1339        {
 11340            if (v is List<double> value)
 1341            {
 11342                writeDoubleSeq(value.ToArray());
 11343                return;
 1344            }
 1345        }
 1346
 1347        {
 11348            if (v is LinkedList<double>)
 1349            {
 11350                writeSize(count);
 11351                expand(count * 8);
 11352                IEnumerator<double> i = v.GetEnumerator();
 11353                while (i.MoveNext())
 1354                {
 11355                    _buf.b.putDouble(i.Current);
 1356                }
 11357                return;
 1358            }
 1359        }
 1360
 1361        {
 11362            if (v is Queue<double> value)
 1363            {
 11364                writeDoubleSeq(value.ToArray());
 11365                return;
 1366            }
 1367        }
 1368
 1369        {
 11370            if (v is Stack<double> value)
 1371            {
 11372                writeDoubleSeq(value.ToArray());
 11373                return;
 1374            }
 1375        }
 1376
 01377        writeSize(count);
 01378        expand(count * 8);
 01379        foreach (double d in v)
 1380        {
 01381            _buf.b.putDouble(d);
 1382        }
 01383    }
 1384
 1385    /// <summary>
 1386    /// Writes an optional double sequence to the stream.
 1387    /// </summary>
 1388    /// <param name="tag">The optional tag.</param>
 1389    /// <param name="v">The double sequence to write to the stream.</param>
 1390    public void writeDoubleSeq(int tag, double[]? v)
 1391    {
 11392        if (v is not null && writeOptional(tag, OptionalFormat.VSize))
 1393        {
 11394            writeSize(v.Length == 0 ? 1 : (v.Length * 8) + (v.Length > 254 ? 5 : 1));
 11395            writeDoubleSeq(v);
 1396        }
 11397    }
 1398
 1399    /// <summary>
 1400    /// Writes an optional double sequence to the stream.
 1401    /// </summary>
 1402    /// <param name="tag">The optional tag.</param>
 1403    /// <param name="count">The number of elements in the sequence.</param>
 1404    /// <param name="v">An enumerator for the double sequence.</param>
 1405    public void writeDoubleSeq(int tag, int count, IEnumerable<double>? v)
 1406    {
 01407        if (v is not null && writeOptional(tag, OptionalFormat.VSize))
 1408        {
 01409            writeSize(count == 0 ? 1 : (count * 8) + (count > 254 ? 5 : 1));
 01410            writeDoubleSeq(count, v);
 1411        }
 01412    }
 1413
 11414    private static readonly System.Text.UTF8Encoding utf8 = new System.Text.UTF8Encoding(false, true);
 1415
 1416    /// <summary>
 1417    /// Writes a string to the stream.
 1418    /// </summary>
 1419    /// <param name="v">The string to write to the stream. Passing null causes
 1420    /// an empty string to be written to the stream.</param>
 1421    public void writeString(string v)
 1422    {
 11423        if (v == null || v.Length == 0)
 1424        {
 11425            writeSize(0);
 11426            return;
 1427        }
 11428        byte[] arr = utf8.GetBytes(v);
 11429        writeSize(arr.Length);
 11430        expand(arr.Length);
 11431        _buf.b.put(arr);
 11432    }
 1433
 1434    /// <summary>
 1435    /// Writes an optional string to the stream.
 1436    /// </summary>
 1437    /// <param name="tag">The optional tag.</param>
 1438    /// <param name="v">The string to write to the stream.</param>
 1439    public void writeString(int tag, string? v)
 1440    {
 11441        if (v is not null && writeOptional(tag, OptionalFormat.VSize))
 1442        {
 11443            writeString(v);
 1444        }
 11445    }
 1446
 1447    /// <summary>
 1448    /// Writes a string sequence to the stream.
 1449    /// </summary>
 1450    /// <param name="v">The string sequence to write to the stream.
 1451    /// Passing null causes an empty sequence to be written to the stream.</param>
 1452    public void writeStringSeq(string[] v)
 1453    {
 11454        if (v == null)
 1455        {
 11456            writeSize(0);
 1457        }
 1458        else
 1459        {
 11460            writeSize(v.Length);
 11461            for (int i = 0; i < v.Length; i++)
 1462            {
 11463                writeString(v[i]);
 1464            }
 1465        }
 11466    }
 1467
 1468    /// <summary>
 1469    /// Writes a string sequence to the stream.
 1470    /// </summary>
 1471    /// <param name="count">The number of elements in the sequence.</param>
 1472    /// <param name="v">An enumerator for the container holding the sequence.</param>
 1473    public void writeStringSeq(int count, IEnumerable<string> v)
 1474    {
 11475        writeSize(count);
 11476        if (count != 0)
 1477        {
 11478            foreach (string s in v)
 1479            {
 11480                writeString(s);
 1481            }
 1482        }
 11483    }
 1484
 1485    /// <summary>
 1486    /// Writes an optional string sequence to the stream.
 1487    /// </summary>
 1488    /// <param name="tag">The optional tag.</param>
 1489    /// <param name="v">The string sequence to write to the stream.</param>
 1490    public void writeStringSeq(int tag, string[]? v)
 1491    {
 11492        if (v is not null && writeOptional(tag, OptionalFormat.FSize))
 1493        {
 11494            int pos = startSize();
 11495            writeStringSeq(v);
 11496            endSize(pos);
 1497        }
 11498    }
 1499
 1500    /// <summary>
 1501    /// Writes an optional string sequence to the stream.
 1502    /// </summary>
 1503    /// <param name="tag">The optional tag.</param>
 1504    /// <param name="count">The number of elements in the sequence.</param>
 1505    /// <param name="v">An enumerator for the string sequence.</param>
 1506    public void writeStringSeq(int tag, int count, IEnumerable<string>? v)
 1507    {
 01508        if (v is not null && writeOptional(tag, OptionalFormat.FSize))
 1509        {
 01510            int pos = startSize();
 01511            writeStringSeq(count, v);
 01512            endSize(pos);
 1513        }
 01514    }
 1515
 1516    /// <summary>
 1517    /// Writes a proxy to the stream.
 1518    /// </summary>
 1519    /// <param name="v">The proxy to write.</param>
 1520    public void writeProxy(ObjectPrx? v)
 1521    {
 11522        if (v is not null)
 1523        {
 11524            v.iceWrite(this);
 1525        }
 1526        else
 1527        {
 11528            Identity.ice_write(this, new Identity());
 1529        }
 11530    }
 1531
 1532    /// <summary>
 1533    /// Writes an optional proxy to the stream.
 1534    /// </summary>
 1535    /// <param name="tag">The optional tag.</param>
 1536    /// <param name="v">The proxy to write.</param>
 1537    public void writeProxy(int tag, ObjectPrx? v)
 1538    {
 1539        // We don't write anything for an optional proxy with a null value.
 11540        if (v is not null && writeOptional(tag, OptionalFormat.FSize))
 1541        {
 11542            int pos = startSize();
 11543            writeProxy(v);
 11544            endSize(pos);
 1545        }
 11546    }
 1547
 1548    /// <summary>
 1549    /// Writes an enumerated value.
 1550    /// </summary>
 1551    /// <param name="v">The enumerator.</param>
 1552    /// <param name="maxValue">The maximum enumerator value in the definition.</param>
 1553    public void writeEnum(int v, int maxValue)
 1554    {
 11555        if (isEncoding_1_0())
 1556        {
 11557            if (maxValue < 127)
 1558            {
 11559                writeByte((byte)v);
 1560            }
 11561            else if (maxValue < 32767)
 1562            {
 11563                writeShort((short)v);
 1564            }
 1565            else
 1566            {
 11567                writeInt(v);
 1568            }
 1569        }
 1570        else
 1571        {
 11572            writeSize(v);
 1573        }
 11574    }
 1575
 1576    /// <summary>
 1577    /// Writes an optional enumerator to the stream.
 1578    /// </summary>
 1579    /// <param name="tag">The optional tag.</param>
 1580    /// <param name="v">The enumerator.</param>
 1581    /// <param name="maxValue">The maximum enumerator value in the definition.</param>
 1582    public void writeEnum(int tag, int v, int maxValue)
 1583    {
 11584        if (writeOptional(tag, OptionalFormat.Size))
 1585        {
 11586            writeEnum(v, maxValue);
 1587        }
 11588    }
 1589
 1590    /// <summary>
 1591    /// Writes a class instance to the stream.
 1592    /// </summary>
 1593    /// <param name="v">The value to write. This method writes the index of an instance; the state of the value is
 1594    /// written once writePendingValues() is called.</param>
 1595    public void writeValue(Value? v)
 1596    {
 11597        initEncaps();
 11598        _encapsStack!.encoder!.writeValue(v);
 11599    }
 1600
 1601    /// <summary>
 1602    /// Writes a user exception to the stream.
 1603    /// </summary>
 1604    /// <param name="v">The user exception to write.</param>
 1605    public void writeException(UserException v)
 1606    {
 11607        initEncaps();
 1608        // Exceptions are always encoded with the sliced format.
 11609        _encapsStack!.format = FormatType.SlicedFormat;
 11610        _encapsStack!.encoder!.writeException(v);
 11611    }
 1612
 1613    private bool writeOptionalImpl(int tag, OptionalFormat format)
 1614    {
 11615        if (isEncoding_1_0())
 1616        {
 11617            return false; // Optional members aren't supported with the 1.0 encoding.
 1618        }
 1619
 11620        int v = (int)format;
 11621        if (tag < 30)
 1622        {
 11623            v |= tag << 3;
 11624            writeByte((byte)v);
 1625        }
 1626        else
 1627        {
 11628            v |= 0x0F0; // tag = 30
 11629            writeByte((byte)v);
 11630            writeSize(tag);
 1631        }
 11632        return true;
 1633    }
 1634
 1635    /// <summary>
 1636    /// Determines the current position in the stream.
 1637    /// </summary>
 1638    /// <returns>The current position.</returns>
 11639    public int pos() => _buf.b.position();
 1640
 1641    /// <summary>
 1642    /// Sets the current position in the stream.
 1643    /// </summary>
 1644    /// <param name="n">The new position.</param>
 11645    public void pos(int n) => _buf.b.position(n);
 1646
 1647    /// <summary>
 1648    /// Determines the current size of the stream.
 1649    /// </summary>
 1650    /// <returns>The current size.</returns>
 11651    public int size() => _buf.size();
 1652
 1653    /// <summary>
 1654    /// Determines whether the stream is empty.
 1655    /// </summary>
 1656    /// <returns>True if no data has been written yet, false otherwise.</returns>
 11657    public bool isEmpty() => _buf.empty();
 1658
 1659    /// <summary>
 1660    /// Expand the stream to accept more data.
 1661    /// </summary>
 1662    /// <param name="n">The number of bytes to accommodate in the stream.</param>
 11663    public void expand(int n) => _buf.expand(n);
 1664
 1665    /// <summary>
 1666    /// Prepares the internal data buffer to be written to a socket.
 1667    /// </summary>
 1668    internal Ice.Internal.Buffer prepareWrite()
 1669    {
 11670        _buf.b.limit(_buf.size());
 11671        _buf.b.position(0);
 11672        return _buf;
 1673    }
 1674
 1675    /// <summary>
 1676    /// Retrieves the internal data buffer.
 1677    /// </summary>
 1678    /// <returns>The buffer.</returns>
 11679    internal Ice.Internal.Buffer getBuffer() => _buf;
 1680
 1681    private Ice.Internal.Buffer _buf;
 1682
 1683    private readonly FormatType _format;
 1684
 1685    private enum SliceType
 1686    {
 1687        NoSlice,
 1688        ValueSlice,
 1689        ExceptionSlice
 1690    }
 1691
 1692    private abstract class EncapsEncoder
 1693    {
 11694        protected EncapsEncoder(OutputStream stream, Encaps encaps)
 1695        {
 11696            _stream = stream;
 11697            _encaps = encaps;
 11698            _typeIdIndex = 0;
 11699            _marshaledMap = new Dictionary<Value, int>();
 11700        }
 1701
 1702        internal abstract void writeValue(Value? v);
 1703
 1704        internal abstract void writeException(UserException v);
 1705
 1706        internal abstract void startInstance(SliceType type, SlicedData? data);
 1707
 1708        internal abstract void endInstance();
 1709
 1710        internal abstract void startSlice(string typeId, int compactId, bool last);
 1711
 1712        internal abstract void endSlice();
 1713
 11714        internal virtual bool writeOptional(int tag, OptionalFormat format) => false;
 1715
 1716        internal virtual void writePendingValues()
 1717        {
 11718        }
 1719
 1720        protected int registerTypeId(string typeId)
 1721        {
 11722            _typeIdMap ??= new Dictionary<string, int>();
 1723
 11724            if (_typeIdMap.TryGetValue(typeId, out int p))
 1725            {
 11726                return p;
 1727            }
 1728            else
 1729            {
 11730                _typeIdMap.Add(typeId, ++_typeIdIndex);
 11731                return -1;
 1732            }
 1733        }
 1734
 1735        protected readonly OutputStream _stream;
 1736
 1737        protected readonly Encaps _encaps;
 1738
 1739        // Encapsulation attributes for instance marshaling.
 1740        protected readonly Dictionary<Value, int> _marshaledMap;
 1741
 1742        // Encapsulation attributes for instance marshaling.
 1743        private Dictionary<string, int>? _typeIdMap;
 1744
 1745        private int _typeIdIndex;
 1746    }
 1747
 1748    private sealed class EncapsEncoder10 : EncapsEncoder
 1749    {
 1750        internal EncapsEncoder10(OutputStream stream, Encaps encaps)
 11751            : base(stream, encaps)
 1752        {
 11753            _sliceType = SliceType.NoSlice;
 11754            _valueIdIndex = 0;
 11755            _toBeMarshaledMap = new Dictionary<Value, int>();
 11756        }
 1757
 1758        internal override void writeValue(Value? v)
 1759        {
 1760            //
 1761            // Object references are encoded as a negative integer in 1.0.
 1762            //
 11763            if (v != null)
 1764            {
 11765                _stream.writeInt(-registerValue(v));
 1766            }
 1767            else
 1768            {
 11769                _stream.writeInt(0);
 1770            }
 11771        }
 1772
 1773        internal override void writeException(UserException v)
 1774        {
 1775            //
 1776            // User exception with the 1.0 encoding start with a bool
 1777            // flag that indicates whether or not the exception uses
 1778            // classes.
 1779            //
 1780            // This allows reading the pending instances even if some part of
 1781            // the exception was sliced.
 1782            //
 11783            bool usesClasses = v.iceUsesClasses();
 11784            _stream.writeBool(usesClasses);
 11785            v.iceWrite(_stream);
 11786            if (usesClasses)
 1787            {
 11788                writePendingValues();
 1789            }
 11790        }
 1791
 11792        internal override void startInstance(SliceType sliceType, SlicedData? sliceData) => _sliceType = sliceType;
 1793
 1794        internal override void endInstance()
 1795        {
 11796            if (_sliceType == SliceType.ValueSlice)
 1797            {
 1798                //
 1799                // Write the Object slice.
 1800                //
 11801                startSlice(Value.ice_staticId(), -1, true);
 11802                _stream.writeSize(0); // For compatibility with the old AFM.
 11803                endSlice();
 1804            }
 11805            _sliceType = SliceType.NoSlice;
 11806        }
 1807
 1808        internal override void startSlice(string typeId, int compactId, bool last)
 1809        {
 1810            //
 1811            // For instance slices, encode a bool to indicate how the type ID
 1812            // is encoded and the type ID either as a string or index. For
 1813            // exception slices, always encode the type ID as a string.
 1814            //
 11815            if (_sliceType == SliceType.ValueSlice)
 1816            {
 11817                int index = registerTypeId(typeId);
 11818                if (index < 0)
 1819                {
 11820                    _stream.writeBool(false);
 11821                    _stream.writeString(typeId);
 1822                }
 1823                else
 1824                {
 11825                    _stream.writeBool(true);
 11826                    _stream.writeSize(index);
 1827                }
 1828            }
 1829            else
 1830            {
 11831                _stream.writeString(typeId);
 1832            }
 1833
 11834            _stream.writeInt(0); // Placeholder for the slice length.
 1835
 11836            _writeSlice = _stream.pos();
 11837        }
 1838
 1839        internal override void endSlice()
 1840        {
 1841            //
 1842            // Write the slice length.
 1843            //
 11844            int sz = _stream.pos() - _writeSlice + 4;
 11845            _stream.rewriteInt(sz, _writeSlice - 4);
 11846        }
 1847
 1848        internal override void writePendingValues()
 1849        {
 11850            while (_toBeMarshaledMap.Count > 0)
 1851            {
 1852                //
 1853                // Consider the to be marshaled instances as marshaled now,
 1854                // this is necessary to avoid adding again the "to be
 1855                // marshaled instances" into _toBeMarshaledMap while writing
 1856                // instances.
 1857                //
 11858                foreach (KeyValuePair<Value, int> e in _toBeMarshaledMap)
 1859                {
 11860                    _marshaledMap.Add(e.Key, e.Value);
 1861                }
 1862
 11863                Dictionary<Value, int> savedMap = _toBeMarshaledMap;
 11864                _toBeMarshaledMap = new Dictionary<Value, int>();
 11865                _stream.writeSize(savedMap.Count);
 11866                foreach (KeyValuePair<Value, int> p in savedMap)
 1867                {
 1868                    //
 1869                    // Ask the instance to marshal itself. Any new class
 1870                    // instances that are triggered by the classes marshaled
 1871                    // are added to toBeMarshaledMap.
 1872                    //
 11873                    _stream.writeInt(p.Value);
 1874
 11875                    p.Key.ice_preMarshal();
 11876                    p.Key.iceWrite(_stream);
 1877                }
 1878            }
 11879            _stream.writeSize(0); // Zero marker indicates end of sequence of sequences of instances.
 11880        }
 1881
 1882        private int registerValue(Value v)
 1883        {
 1884            Debug.Assert(v != null);
 1885
 1886            //
 1887            // Look for this instance in the to-be-marshaled map.
 1888            //
 11889            if (_toBeMarshaledMap.TryGetValue(v, out int p))
 1890            {
 11891                return p;
 1892            }
 1893
 1894            //
 1895            // Didn't find it, try the marshaled map next.
 1896            //
 11897            if (_marshaledMap.TryGetValue(v, out p))
 1898            {
 11899                return p;
 1900            }
 1901
 1902            //
 1903            // We haven't seen this instance previously, create a new
 1904            // index, and insert it into the to-be-marshaled map.
 1905            //
 11906            _toBeMarshaledMap.Add(v, ++_valueIdIndex);
 11907            return _valueIdIndex;
 1908        }
 1909
 1910        // Instance attributes
 1911        private SliceType _sliceType;
 1912
 1913        // Slice attributes
 1914        private int _writeSlice;        // Position of the slice data members
 1915
 1916        // Encapsulation attributes for instance marshaling.
 1917        private int _valueIdIndex;
 1918        private Dictionary<Value, int> _toBeMarshaledMap;
 1919    }
 1920
 1921    private sealed class EncapsEncoder11 : EncapsEncoder
 1922    {
 1923        internal EncapsEncoder11(OutputStream stream, Encaps encaps)
 11924            : base(stream, encaps)
 1925        {
 11926            _current = null;
 11927            _valueIdIndex = 1;
 11928        }
 1929
 1930        internal override void writeValue(Value? v)
 1931        {
 11932            if (v == null)
 1933            {
 11934                _stream.writeSize(0);
 1935            }
 11936            else if (_current != null && _encaps.format == FormatType.SlicedFormat)
 1937            {
 11938                if (_current.indirectionTable == null)
 1939                {
 11940                    _current.indirectionTable = new List<Value>();
 11941                    _current.indirectionMap = new Dictionary<Value, int>();
 1942                }
 1943
 1944                //
 1945                // If writing an instance within a slice and using the sliced
 1946                // format, write an index from the instance indirection table.
 1947                //
 11948                if (!_current.indirectionMap!.TryGetValue(v, out int index))
 1949                {
 11950                    _current.indirectionTable.Add(v);
 11951                    int idx = _current.indirectionTable.Count; // Position + 1 (0 is reserved for nil)
 11952                    _current.indirectionMap.Add(v, idx);
 11953                    _stream.writeSize(idx);
 1954                }
 1955                else
 1956                {
 11957                    _stream.writeSize(index);
 1958                }
 1959            }
 1960            else
 1961            {
 11962                writeInstance(v); // Write the instance or a reference if already marshaled.
 1963            }
 11964        }
 1965
 11966        internal override void writeException(UserException v) => v.iceWrite(_stream);
 1967
 1968        internal override void startInstance(SliceType sliceType, SlicedData? data)
 1969        {
 11970            if (_current == null)
 1971            {
 11972                _current = new InstanceData(null);
 1973            }
 1974            else
 1975            {
 11976                _current = _current.next ?? new InstanceData(_current);
 1977            }
 11978            _current.sliceType = sliceType;
 11979            _current.firstSlice = true;
 1980
 11981            if (data != null)
 1982            {
 11983                writeSlicedData(data);
 1984            }
 11985        }
 1986
 11987        internal override void endInstance() => _current = _current!.previous;
 1988
 1989        internal override void startSlice(string typeId, int compactId, bool last)
 1990        {
 1991            Debug.Assert((_current!.indirectionTable == null || _current.indirectionTable.Count == 0) &&
 1992                         (_current.indirectionMap == null || _current.indirectionMap.Count == 0));
 1993
 11994            _current.sliceFlagsPos = _stream.pos();
 1995
 11996            _current.sliceFlags = 0;
 11997            if (_encaps.format == FormatType.SlicedFormat)
 1998            {
 1999                //
 2000                // Encode the slice size if using the sliced format.
 2001                //
 12002                _current.sliceFlags |= Protocol.FLAG_HAS_SLICE_SIZE;
 2003            }
 12004            if (last)
 2005            {
 12006                _current.sliceFlags |= Protocol.FLAG_IS_LAST_SLICE; // This is the last slice.
 2007            }
 2008
 12009            _stream.writeByte(0); // Placeholder for the slice flags
 2010
 2011            //
 2012            // For instance slices, encode the flag and the type ID either as a
 2013            // string or index. For exception slices, always encode the type
 2014            // ID a string.
 2015            //
 12016            if (_current.sliceType == SliceType.ValueSlice)
 2017            {
 2018                //
 2019                // Encode the type ID (only in the first slice for the compact
 2020                // encoding).
 2021                //
 12022                if (_encaps.format == FormatType.SlicedFormat || _current.firstSlice)
 2023                {
 12024                    if (compactId != -1)
 2025                    {
 12026                        _current.sliceFlags |= Protocol.FLAG_HAS_TYPE_ID_COMPACT;
 12027                        _stream.writeSize(compactId);
 2028                    }
 2029                    else
 2030                    {
 12031                        int index = registerTypeId(typeId);
 12032                        if (index < 0)
 2033                        {
 12034                            _current.sliceFlags |= Protocol.FLAG_HAS_TYPE_ID_STRING;
 12035                            _stream.writeString(typeId);
 2036                        }
 2037                        else
 2038                        {
 12039                            _current.sliceFlags |= Protocol.FLAG_HAS_TYPE_ID_INDEX;
 12040                            _stream.writeSize(index);
 2041                        }
 2042                    }
 2043                }
 2044            }
 2045            else
 2046            {
 12047                _stream.writeString(typeId);
 2048            }
 2049
 12050            if ((_current.sliceFlags & Protocol.FLAG_HAS_SLICE_SIZE) != 0)
 2051            {
 12052                _stream.writeInt(0); // Placeholder for the slice length.
 2053            }
 2054
 12055            _current.writeSlice = _stream.pos();
 12056            _current.firstSlice = false;
 12057        }
 2058
 2059        internal override void endSlice()
 2060        {
 2061            //
 2062            // Write the optional member end marker if some optional members
 2063            // were encoded. Note that the optional members are encoded before
 2064            // the indirection table and are included in the slice size.
 2065            //
 12066            if ((_current!.sliceFlags & Protocol.FLAG_HAS_OPTIONAL_MEMBERS) != 0)
 2067            {
 12068                _stream.writeByte(Protocol.OPTIONAL_END_MARKER);
 2069            }
 2070
 2071            //
 2072            // Write the slice length if necessary.
 2073            //
 12074            if ((_current.sliceFlags & Protocol.FLAG_HAS_SLICE_SIZE) != 0)
 2075            {
 12076                int sz = _stream.pos() - _current.writeSlice + 4;
 12077                _stream.rewriteInt(sz, _current.writeSlice - 4);
 2078            }
 2079
 2080            //
 2081            // Only write the indirection table if it contains entries.
 2082            //
 12083            if (_current.indirectionTable != null && _current.indirectionTable.Count > 0)
 2084            {
 2085                Debug.Assert(_encaps.format == FormatType.SlicedFormat);
 12086                _current.sliceFlags |= Protocol.FLAG_HAS_INDIRECTION_TABLE;
 2087
 2088                //
 2089                // Write the indirect instance table.
 2090                //
 12091                _stream.writeSize(_current.indirectionTable.Count);
 12092                foreach (Value v in _current.indirectionTable)
 2093                {
 12094                    writeInstance(v);
 2095                }
 12096                _current.indirectionTable.Clear();
 12097                _current.indirectionMap!.Clear();
 2098            }
 2099
 2100            //
 2101            // Finally, update the slice flags.
 2102            //
 12103            _stream.rewriteByte(_current.sliceFlags, _current.sliceFlagsPos);
 12104        }
 2105
 2106        internal override bool writeOptional(int tag, OptionalFormat format)
 2107        {
 12108            if (_current == null)
 2109            {
 12110                return _stream.writeOptionalImpl(tag, format);
 2111            }
 2112            else
 2113            {
 12114                if (_stream.writeOptionalImpl(tag, format))
 2115                {
 12116                    _current.sliceFlags |= Protocol.FLAG_HAS_OPTIONAL_MEMBERS;
 12117                    return true;
 2118                }
 2119                else
 2120                {
 02121                    return false;
 2122                }
 2123            }
 2124        }
 2125
 2126        private void writeSlicedData(SlicedData slicedData)
 2127        {
 2128            Debug.Assert(slicedData != null);
 2129
 2130            //
 2131            // We only remarshal preserved slices if we are using the sliced
 2132            // format. Otherwise, we ignore the preserved slices, which
 2133            // essentially "slices" the instance into the most-derived type
 2134            // known by the sender.
 2135            //
 12136            if (_encaps.format != FormatType.SlicedFormat)
 2137            {
 02138                return;
 2139            }
 2140
 12141            foreach (SliceInfo info in slicedData.slices)
 2142            {
 12143                startSlice(info.typeId, info.compactId, info.isLastSlice);
 2144
 2145                //
 2146                // Write the bytes associated with this slice.
 2147                //
 12148                _stream.writeBlob(info.bytes);
 2149
 12150                if (info.hasOptionalMembers)
 2151                {
 12152                    _current!.sliceFlags |= Protocol.FLAG_HAS_OPTIONAL_MEMBERS;
 2153                }
 2154
 2155                //
 2156                // Make sure to also re-write the instance indirection table.
 2157                //
 12158                if (info.instances != null && info.instances.Length > 0)
 2159                {
 12160                    if (_current!.indirectionTable == null)
 2161                    {
 12162                        _current.indirectionTable = new List<Value>();
 12163                        _current.indirectionMap = new Dictionary<Value, int>();
 2164                    }
 12165                    foreach (Value o in info.instances)
 2166                    {
 12167                        _current.indirectionTable.Add(o);
 2168                    }
 2169                }
 2170
 12171                endSlice();
 2172            }
 12173        }
 2174
 2175        private void writeInstance(Value v)
 2176        {
 2177            Debug.Assert(v != null);
 2178
 2179            //
 2180            // If the instance was already marshaled, just write it's ID.
 2181            //
 12182            if (_marshaledMap.TryGetValue(v, out int p))
 2183            {
 12184                _stream.writeSize(p);
 12185                return;
 2186            }
 2187
 2188            //
 2189            // We haven't seen this instance previously, create a new ID,
 2190            // insert it into the marshaled map, and write the instance.
 2191            //
 12192            _marshaledMap.Add(v, ++_valueIdIndex);
 2193
 12194            v.ice_preMarshal();
 12195            _stream.writeSize(1); // Object instance marker.
 12196            v.iceWrite(_stream);
 12197        }
 2198
 2199        private sealed class InstanceData
 2200        {
 12201            internal InstanceData(InstanceData? previous)
 2202            {
 12203                if (previous != null)
 2204                {
 12205                    previous.next = this;
 2206                }
 12207                this.previous = previous;
 12208                next = null;
 12209            }
 2210
 2211            // Instance attributes
 2212            internal SliceType sliceType;
 2213            internal bool firstSlice;
 2214
 2215            // Slice attributes
 2216            internal byte sliceFlags;
 2217            internal int writeSlice;    // Position of the slice data members
 2218            internal int sliceFlagsPos; // Position of the slice flags
 2219            internal List<Value>? indirectionTable;
 2220            internal Dictionary<Value, int>? indirectionMap;
 2221
 2222            internal InstanceData? previous;
 2223            internal InstanceData? next;
 2224        }
 2225
 2226        private InstanceData? _current;
 2227
 2228        private int _valueIdIndex; // The ID of the next instance to marshal
 2229    }
 2230
 2231    private sealed class Encaps
 2232    {
 12233        internal void reset() => encoder = null;
 2234
 2235        internal void setEncoding(EncodingVersion encoding)
 2236        {
 12237            this.encoding = encoding;
 12238            encoding_1_0 = encoding.Equals(Util.Encoding_1_0);
 12239        }
 2240
 2241        internal int start;
 2242        internal EncodingVersion encoding;
 2243        internal bool encoding_1_0;
 2244        internal FormatType format;
 2245
 2246        internal EncapsEncoder? encoder;
 2247
 2248        internal Encaps? next;
 2249    }
 2250
 2251    //
 2252    // The encoding version to use when there's no encapsulation to
 2253    // read from or write to. This is for example used to read message
 2254    // headers or when the user is using the streaming API with no
 2255    // encapsulation.
 2256    //
 2257    private EncodingVersion _encoding;
 2258
 2259    private bool isEncoding_1_0() =>
 12260        _encapsStack != null ? _encapsStack.encoding_1_0 : _encoding.Equals(Util.Encoding_1_0);
 2261
 2262    private Encaps? _encapsStack;
 2263    private Encaps? _encapsCache;
 2264
 2265    private void initEncaps()
 2266    {
 12267        if (_encapsStack == null) // Lazy initialization
 2268        {
 12269            _encapsStack = _encapsCache;
 12270            if (_encapsStack != null)
 2271            {
 02272                _encapsCache = _encapsCache!.next;
 2273            }
 2274            else
 2275            {
 12276                _encapsStack = new Encaps();
 2277            }
 12278            _encapsStack.setEncoding(_encoding);
 2279        }
 2280
 12281        if (_encapsStack.encoder == null) // Lazy initialization.
 2282        {
 12283            if (_encapsStack.encoding_1_0)
 2284            {
 12285                _encapsStack.encoder = new EncapsEncoder10(this, _encapsStack);
 2286            }
 2287            else
 2288            {
 12289                _encapsStack.encoder = new EncapsEncoder11(this, _encapsStack);
 2290            }
 2291        }
 12292    }
 2293}

Methods/Properties

.ctor(System.Nullable<Ice.EncodingVersion>, Ice.FormatType)
.ctor(Ice.Communicator)
.ctor(Ice.Internal.Buffer, System.Nullable<Ice.EncodingVersion>, Ice.FormatType)
reset()
clear()
finished()
swap(Ice.OutputStream)
resetEncapsulation()
resize(int)
startValue(Ice.SlicedData)
endValue()
startException()
endException()
startEncapsulation()
startEncapsulation(Ice.EncodingVersion, System.Nullable<Ice.FormatType>)
endEncapsulation()
writeEmptyEncapsulation(Ice.EncodingVersion)
writeEncapsulation(byte[])
getEncoding()
startSlice(string, int, bool)
endSlice()
writePendingValues()
writeSize(int)
startSize()
endSize(int)
writeBlob(byte[])
writeBlob(byte[], int, int)
writeOptional(int, Ice.OptionalFormat)
writeByte(byte)
writeByte(int, System.Nullable<byte>)
writeByte(int, byte)
rewriteByte(byte, int)
writeByteSeq(byte[])
writeByteSeq(int, System.Collections.Generic.IEnumerable<byte>)
writeByteSeq(int, byte[])
writeByteSeq(int, int, System.Collections.Generic.IEnumerable<byte>)
writeBool(bool)
writeBool(int, System.Nullable<bool>)
writeBool(int, bool)
rewriteBool(bool, int)
writeBoolSeq(bool[])
writeBoolSeq(int, System.Collections.Generic.IEnumerable<bool>)
writeBoolSeq(int, bool[])
writeBoolSeq(int, int, System.Collections.Generic.IEnumerable<bool>)
writeShort(short)
writeShort(int, System.Nullable<short>)
writeShort(int, short)
writeShortSeq(short[])
writeShortSeq(int, System.Collections.Generic.IEnumerable<short>)
writeShortSeq(int, short[])
writeShortSeq(int, int, System.Collections.Generic.IEnumerable<short>)
writeInt(int)
writeInt(int, System.Nullable<int>)
writeInt(int, int)
rewriteInt(int, int)
writeIntSeq(int[])
writeIntSeq(int, System.Collections.Generic.IEnumerable<int>)
writeIntSeq(int, int[])
writeIntSeq(int, int, System.Collections.Generic.IEnumerable<int>)
writeLong(long)
writeLong(int, System.Nullable<long>)
writeLong(int, long)
writeLongSeq(long[])
writeLongSeq(int, System.Collections.Generic.IEnumerable<long>)
writeLongSeq(int, long[])
writeLongSeq(int, int, System.Collections.Generic.IEnumerable<long>)
writeFloat(float)
writeFloat(int, System.Nullable<float>)
writeFloat(int, float)
writeFloatSeq(float[])
writeFloatSeq(int, System.Collections.Generic.IEnumerable<float>)
writeFloatSeq(int, float[])
writeFloatSeq(int, int, System.Collections.Generic.IEnumerable<float>)
writeDouble(double)
writeDouble(int, System.Nullable<double>)
writeDouble(int, double)
writeDoubleSeq(double[])
writeDoubleSeq(int, System.Collections.Generic.IEnumerable<double>)
writeDoubleSeq(int, double[])
writeDoubleSeq(int, int, System.Collections.Generic.IEnumerable<double>)
.cctor()
writeString(string)
writeString(int, string)
writeStringSeq(string[])
writeStringSeq(int, System.Collections.Generic.IEnumerable<string>)
writeStringSeq(int, string[])
writeStringSeq(int, int, System.Collections.Generic.IEnumerable<string>)
writeProxy(Ice.ObjectPrx)
writeProxy(int, Ice.ObjectPrx)
writeEnum(int, int)
writeEnum(int, int, int)
writeValue(Ice.Value)
writeException(Ice.UserException)
writeOptionalImpl(int, Ice.OptionalFormat)
pos()
pos(int)
size()
isEmpty()
expand(int)
prepareWrite()
getBuffer()
.ctor(Ice.OutputStream, Ice.OutputStream.Encaps)
writeOptional(int, Ice.OptionalFormat)
writePendingValues()
registerTypeId(string)
.ctor(Ice.OutputStream, Ice.OutputStream.Encaps)
writeValue(Ice.Value)
writeException(Ice.UserException)
startInstance(Ice.OutputStream.SliceType, Ice.SlicedData)
endInstance()
startSlice(string, int, bool)
endSlice()
writePendingValues()
registerValue(Ice.Value)
.ctor(Ice.OutputStream, Ice.OutputStream.Encaps)
writeValue(Ice.Value)
writeException(Ice.UserException)
startInstance(Ice.OutputStream.SliceType, Ice.SlicedData)
endInstance()
startSlice(string, int, bool)
endSlice()
writeOptional(int, Ice.OptionalFormat)
writeSlicedData(Ice.SlicedData)
writeInstance(Ice.Value)
.ctor(Ice.OutputStream.EncapsEncoder11.InstanceData)
reset()
setEncoding(Ice.EncodingVersion)
isEncoding_1_0()
initEncaps()