void WriteFirstByte <T>(ref BitTarget target, T data, CompressedDataInfo dataInfo) where T : INumberContainer { bool isExtendedByte = target.FreeBits < 4; bool byteWillHaveFreeSpace = dataInfo.HeaderLen < target.FreeBits; // Write the header target.WriteInteger(dataInfo.Header, dataInfo.HeaderLen); // Handle extended starts (yyy-xxxxxxxx) if (isExtendedByte) { // Write any free "y"s. if (byteWillHaveFreeSpace) { target.WriteInteger((byte)(data.ShiftRight(dataInfo.BitsToGo) >> 8), target.FreeBits); } // The next byte will definitely have some free space, as we can not physically fill all of the remaining "xxxxxxxx"s with the header. // Ensure we're definitely ready for the next byte. if (target.FreeBits == 0) { target.Apply(); } byteWillHaveFreeSpace = true; } if (byteWillHaveFreeSpace) { target.WriteInteger((byte)data.ShiftRight(dataInfo.BitsToGo), target.FreeBits); } target.Apply(); }
void SerializeItemNoSetup(object obj, MapItemInfo info, ref BitTarget header, bool skipHeader) { Converter item = info.Converter; ABSaveUtils.WaitUntilNotGenerating(item); SerializeConverter(obj, info.Converter, ref header, skipHeader); }
void SerializeActualType(object obj, Type type) { MapItemInfo info = GetRuntimeMapItem(type); var newTarget = new BitTarget(this); SerializeItemNoSetup(obj, info, ref newTarget, true); }
public void SerializePossibleNullableItem(object obj, MapItemInfo info, ref BitTarget header) { // Say it's "not null" if it is nullable. if (info.IsNullable) { header.WriteBitOn(); } SerializeItemNoSetup(obj, info, ref header, info.IsNullable); }
// Returns: Whether the type has changed. bool WriteHeaderNullAndInheritance(Type actualType, Converter item, ref BitTarget target) { target.WriteBitOn(); // Null bool sameType = item.ItemType == actualType; target.WriteBitWith(sameType); return(sameType); }
public void WriteUTF8(ReadOnlySpan <char> data, ref BitTarget header) { int maxSize = Encoding.UTF8.GetMaxByteCount(data.Length); Span <byte> buffer = maxSize <= ABSaveUtils.MAX_STACK_SIZE ? stackalloc byte[maxSize] : GetStringBufferFor(maxSize); int actualSize = Encoding.UTF8.GetBytes(data, buffer); WriteCompressedInt((uint)actualSize, ref header); WriteBytes(buffer.Slice(0, actualSize)); }
public void WriteText(ReadOnlySpan <char> chars, ref BitTarget header) { if (Settings.UseUTF8) { WriteUTF8(chars, ref header); } else { WriteCompressedInt((uint)chars.Length); FastWriteShorts(MemoryMarshal.Cast <char, short>(chars)); } }
public void SerializeItem(object?obj, MapItemInfo item, ref BitTarget header) { if (obj == null) { header.WriteBitOff(); header.Apply(); } else { SerializePossibleNullableItem(obj, item, ref header); } }
uint WriteNewVersionInfo(Converter item, ref BitTarget target) { uint targetVersion = 0; // Try to get the custom target version and if there is none use the latest. if (TargetVersions?.TryGetValue(item.ItemType, out targetVersion) != true) { targetVersion = item.HighestVersion; } WriteCompressedInt(targetVersion, ref target); return(targetVersion); }
public void SerializeItem(object?obj, MapItemInfo item) { if (obj == null) { WriteByte(0); } else { var currentHeader = new BitTarget(this); SerializePossibleNullableItem(obj, item, ref currentHeader); } }
void WriteCompressedSlow <T>(T data, ref BitTarget target) where T : INumberContainer { var dataInfo = GetCompressedDataInfo(data, target.FreeBits); // Write the first byte WriteFirstByte(ref target, data, dataInfo); // Write the data in the remaining bytes while (dataInfo.BitsToGo > 0) { dataInfo.BitsToGo -= 8; WriteByte((byte)data.ShiftRight(dataInfo.BitsToGo)); } }
public void WriteString(string?str) { var header = new BitTarget(this); if (str == null) { header.WriteBitOff(); } else { header.WriteBitOn(); WriteNonNullString(str !); } }
void WriteCompressed <T>(T data, ref BitTarget target) where T : INumberContainer { if (target.FreeBits == 0) { target.Apply(); } if (Settings.LazyCompressedWriting) { WriteCompressedLazyFast(data, ref target); } else { WriteCompressedSlow(data, ref target); } }
/// <summary> /// Handles the version info for a given converter. If the version hasn't been written yet, it's written now. If not, nothing is written. /// </summary> /// <returns>Whether the item already exists</returns> internal bool HandleVersionNumber(Converter item, out VersionInfo info, ref BitTarget header) { if (item._instanceId >= _currentVersionInfos.Length) { Array.Resize(ref _currentVersionInfos, (int)Map._highestConverterInstanceId); } // If the version has already been written, do nothing VersionInfo?existingInfo = _currentVersionInfos[item._instanceId]; if (existingInfo != null) { info = existingInfo; return(true); } uint version = WriteNewVersionInfo(item, ref header); info = Map.GetVersionInfo(item, version); _currentVersionInfos[item._instanceId] = info; return(false); }
void SerializeConverter(object obj, Converter converter, ref BitTarget header, bool skipHeader) { Type?actualType = obj.GetType(); bool appliedHeader = true; // Write the null and inheritance bits. bool sameType = true; if (!converter.IsValueItemType && !skipHeader) { sameType = WriteHeaderNullAndInheritance(actualType, converter, ref header); appliedHeader = false; } // Write and get the info for a version, if necessary if (!HandleVersionNumber(converter, out VersionInfo info, ref header)) { appliedHeader = true; } // Handle inheritance if needed. if (info._inheritanceInfo != null && !sameType) { SerializeActualType(obj, info._inheritanceInfo, converter.ItemType, actualType, ref header); return; } // Apply the header if it's not being used and hasn't already been applied. if (!info.UsesHeader && !appliedHeader) { header.Apply(); } var serializeInfo = new Converter.SerializeInfo(obj, actualType, info); converter.Serialize(in serializeInfo, ref header); }
void WriteCompressedLazyFast <T>(T data, ref BitTarget target) where T : INumberContainer { // This should be blazing fast, we're literally just going to write whether the number takes up more than a byte, and that's it. if (data.LessThan(255)) { target.OrAndApply(1); WriteByte(data.ToByte()); } else { target.OrAndApply(0); // This check is optimized away by the JIT. if (typeof(T) == typeof(Int32Container)) { WriteInt32(data.ToInt32()); } else if (typeof(T) == typeof(Int64Container)) { WriteInt64(data.ToInt64()); } } }
public void SerializeExactNonNullItem(object obj, MapItemInfo item, ref BitTarget header) => SerializeItemNoSetup(obj, item, ref header, true);
// NOTE: All uses of "INumberContainer" virtual calls in here are elided by the JIT thanks to generics. public void WriteCompressedInt(uint data, ref BitTarget target) => WriteCompressed(new Int32Container((int)data), ref target);
void WriteKeyInheritance(SaveInheritanceAttribute info, Type baseType, Type actualType, ref BitTarget header) { string key = KeyInheritanceHandler.GetOrAddTypeKeyFromCache(baseType, actualType, info); WriteString(key, ref header); }
bool TryWriteListInheritance(SaveInheritanceAttribute info, Type actualType, bool writeOnIfSuccessful, ref BitTarget header) { if (info.IndexSerializeCache !.TryGetValue(actualType, out uint pos)) { if (writeOnIfSuccessful) { header.WriteBitOn(); } WriteCompressedInt(pos, ref header); return(true); } return(false); }
// Returns: Whether the sub-type was converted in here and we should return now. void SerializeActualType(object obj, SaveInheritanceAttribute info, Type baseType, Type actualType, ref BitTarget header) { switch (info.Mode) { case SaveInheritanceMode.Index: if (!TryWriteListInheritance(info, actualType, false, ref header)) { throw new UnsupportedSubTypeException(baseType, actualType); } break; case SaveInheritanceMode.Key: WriteKeyInheritance(info, baseType, actualType, ref header); break; case SaveInheritanceMode.IndexOrKey: if (!TryWriteListInheritance(info, actualType, true, ref header)) { header.WriteBitOff(); WriteKeyInheritance(info, baseType, actualType, ref header); } break; } // Serialize the actual type now. SerializeItemNoSetup(obj, GetRuntimeMapItem(actualType), ref header, true); }
public void WriteCompressedLong(ulong data, ref BitTarget target) => WriteCompressed(new Int64Container((long)data), ref target);
public void WriteNonNullString(string str) { var header = new BitTarget(this); WriteString(str, ref header); }
public void WriteCompressedLong(ulong data) { var target = new BitTarget(this); WriteCompressedLong(data, ref target); }
public void WriteString(string str, ref BitTarget header) => WriteText(str.AsSpan(), ref header);
public void SerializeExactNonNullItem(object obj, MapItemInfo item) { var currentHeader = new BitTarget(this); SerializeItemNoSetup(obj, item, ref currentHeader, true); }
public void WriteCompressedInt(uint data) { var target = new BitTarget(this); WriteCompressedInt(data, ref target); }