/// <summary>Writes a class instance to the stream.</summary> /// <param name="v">The class instance to write. This instance cannot be null.</param> /// <param name="formalTypeId">The type ID of the formal type of the parameter or data member being written. /// Use null when the type of the parameter/data member is AnyClass.</param> public void WriteClass(AnyClass v, string?formalTypeId) { Debug.Assert(InEncapsulation); if (_current.InstanceType != InstanceType.None && _format == FormatType.Sliced) { // If writing an instance within a slice and using the sliced format, write an index of that slice's // indirection table. if (_current.IndirectionMap != null && _current.IndirectionMap.TryGetValue(v, out int index)) { // Found, index is position in indirection table + 1 Debug.Assert(index > 0); } else { _current.IndirectionTable ??= new List <AnyClass>(); _current.IndirectionMap ??= new Dictionary <AnyClass, int>(); _current.IndirectionTable.Add(v); index = _current.IndirectionTable.Count; // Position + 1 (0 is reserved for null) _current.IndirectionMap.Add(v, index); } WriteSize(index); } else { WriteInstance(v, formalTypeId); // Writes the instance or a reference if already marshaled. } }
internal void FirstSliceInit(AnyClass v, bool setSlicedData) { Debug.Assert(_current != null); // Add the instance to the map/list of instances. This must be done before reading the instances (for // circular references). _instanceMap ??= new List <AnyClass>(); _instanceMap.Add(v); // Read all the deferred indirection tables now that the instance is inserted in _instanceMap. if (_current.DeferredIndirectionTableList?.Count > 0) { int savedPos = _pos; Debug.Assert(_current.Slices?.Count == _current.DeferredIndirectionTableList.Count); for (int i = 0; i < _current.DeferredIndirectionTableList.Count; ++i) { int pos = _current.DeferredIndirectionTableList[i]; if (pos > 0) { _pos = pos; _current.Slices[i].Instances = Array.AsReadOnly(ReadIndirectionTable()); } // else remains empty } _pos = savedPos; } if (setSlicedData) { v.SlicedData = GetSlicedData(); } }
public void IceStartFirstSlice(string typeId, AnyClass v, bool setSlicedData = false) { Debug.Assert(InEncapsulation); Debug.Assert(_current != null && (_current.SliceTypeId == null || _current.SliceTypeId == typeId)); Debug.Assert(_current.InstanceType == InstanceType.Class); FirstSliceInit(v, setSlicedData); ReadIndirectionTableIntoCurrent(); }
/// <summary>Reads an indirection table from the stream, without updating _current.</summary> /// <returns>The indirection table.</returns> private AnyClass[] ReadIndirectionTable() { int size = ReadAndCheckSeqSize(1); if (size == 0) { throw new InvalidDataException("invalid empty indirection table"); } var indirectionTable = new AnyClass[size]; for (int i = 0; i < indirectionTable.Length; ++i) { int index = ReadSize(); if (index < 1) { throw new InvalidDataException($"read invalid index {index} in indirection table"); } indirectionTable[i] = ReadInstance(index, formalTypeId: null); } return(indirectionTable); }