blob: 3d41bd26e1a113c32b9cbcc943f02b9b192d4f81 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
using System.Collections.Immutable;
namespace Apache.Fory;
internal static class PrimitiveCollectionHeader
{
public static void WriteListHeader(WriteContext context, int count, bool hasGenerics, TypeId elementTypeId, bool hasNull)
{
context.Writer.WriteVarUInt32((uint)count);
if (count == 0)
{
return;
}
bool declared = hasGenerics && !TypeResolver.NeedToWriteTypeInfoForField(elementTypeId);
byte header = CollectionBits.SameType;
if (hasNull)
{
header |= CollectionBits.HasNull;
}
if (declared)
{
header |= CollectionBits.DeclaredElementType;
}
context.Writer.WriteUInt8(header);
if (!declared)
{
context.Writer.WriteUInt8((byte)elementTypeId);
}
}
}
internal sealed class ListBoolSerializer : Serializer<List<bool>>
{
private static readonly ListSerializer<bool> Fallback = new();
public override List<bool> DefaultValue => null!;
public override void WriteData(WriteContext context, in List<bool> value, bool hasGenerics)
{
List<bool> list = value ?? [];
PrimitiveCollectionHeader.WriteListHeader(context, list.Count, hasGenerics, TypeId.Bool, false);
for (int i = 0; i < list.Count; i++)
{
context.Writer.WriteUInt8(list[i] ? (byte)1 : (byte)0);
}
}
public override List<bool> ReadData(ReadContext context)
{
return Fallback.ReadData(context);
}
}
internal sealed class ListInt8Serializer : Serializer<List<sbyte>>
{
private static readonly ListSerializer<sbyte> Fallback = new();
public override List<sbyte> DefaultValue => null!;
public override void WriteData(WriteContext context, in List<sbyte> value, bool hasGenerics)
{
List<sbyte> list = value ?? [];
PrimitiveCollectionHeader.WriteListHeader(context, list.Count, hasGenerics, TypeId.Int8, false);
for (int i = 0; i < list.Count; i++)
{
context.Writer.WriteInt8(list[i]);
}
}
public override List<sbyte> ReadData(ReadContext context)
{
return Fallback.ReadData(context);
}
}
internal sealed class ListInt16Serializer : Serializer<List<short>>
{
private static readonly ListSerializer<short> Fallback = new();
public override List<short> DefaultValue => null!;
public override void WriteData(WriteContext context, in List<short> value, bool hasGenerics)
{
List<short> list = value ?? [];
PrimitiveCollectionHeader.WriteListHeader(context, list.Count, hasGenerics, TypeId.Int16, false);
for (int i = 0; i < list.Count; i++)
{
context.Writer.WriteInt16(list[i]);
}
}
public override List<short> ReadData(ReadContext context)
{
return Fallback.ReadData(context);
}
}
internal sealed class ListIntSerializer : Serializer<List<int>>
{
private static readonly ListSerializer<int> Fallback = new();
public override List<int> DefaultValue => null!;
public override void WriteData(WriteContext context, in List<int> value, bool hasGenerics)
{
List<int> list = value ?? [];
PrimitiveCollectionHeader.WriteListHeader(context, list.Count, hasGenerics, TypeId.VarInt32, false);
for (int i = 0; i < list.Count; i++)
{
context.Writer.WriteVarInt32(list[i]);
}
}
public override List<int> ReadData(ReadContext context)
{
return Fallback.ReadData(context);
}
}
internal sealed class ListLongSerializer : Serializer<List<long>>
{
private static readonly ListSerializer<long> Fallback = new();
public override List<long> DefaultValue => null!;
public override void WriteData(WriteContext context, in List<long> value, bool hasGenerics)
{
List<long> list = value ?? [];
PrimitiveCollectionHeader.WriteListHeader(context, list.Count, hasGenerics, TypeId.VarInt64, false);
for (int i = 0; i < list.Count; i++)
{
context.Writer.WriteVarInt64(list[i]);
}
}
public override List<long> ReadData(ReadContext context)
{
return Fallback.ReadData(context);
}
}
internal sealed class ListUInt8Serializer : Serializer<List<byte>>
{
private static readonly ListSerializer<byte> Fallback = new();
public override List<byte> DefaultValue => null!;
public override void WriteData(WriteContext context, in List<byte> value, bool hasGenerics)
{
List<byte> list = value ?? [];
PrimitiveCollectionHeader.WriteListHeader(context, list.Count, hasGenerics, TypeId.UInt8, false);
for (int i = 0; i < list.Count; i++)
{
context.Writer.WriteUInt8(list[i]);
}
}
public override List<byte> ReadData(ReadContext context)
{
return Fallback.ReadData(context);
}
}
internal sealed class ListUInt16Serializer : Serializer<List<ushort>>
{
private static readonly ListSerializer<ushort> Fallback = new();
public override List<ushort> DefaultValue => null!;
public override void WriteData(WriteContext context, in List<ushort> value, bool hasGenerics)
{
List<ushort> list = value ?? [];
PrimitiveCollectionHeader.WriteListHeader(context, list.Count, hasGenerics, TypeId.UInt16, false);
for (int i = 0; i < list.Count; i++)
{
context.Writer.WriteUInt16(list[i]);
}
}
public override List<ushort> ReadData(ReadContext context)
{
return Fallback.ReadData(context);
}
}
internal sealed class ListUIntSerializer : Serializer<List<uint>>
{
private static readonly ListSerializer<uint> Fallback = new();
public override List<uint> DefaultValue => null!;
public override void WriteData(WriteContext context, in List<uint> value, bool hasGenerics)
{
List<uint> list = value ?? [];
PrimitiveCollectionHeader.WriteListHeader(context, list.Count, hasGenerics, TypeId.VarUInt32, false);
for (int i = 0; i < list.Count; i++)
{
context.Writer.WriteVarUInt32(list[i]);
}
}
public override List<uint> ReadData(ReadContext context)
{
return Fallback.ReadData(context);
}
}
internal sealed class ListULongSerializer : Serializer<List<ulong>>
{
private static readonly ListSerializer<ulong> Fallback = new();
public override List<ulong> DefaultValue => null!;
public override void WriteData(WriteContext context, in List<ulong> value, bool hasGenerics)
{
List<ulong> list = value ?? [];
PrimitiveCollectionHeader.WriteListHeader(context, list.Count, hasGenerics, TypeId.VarUInt64, false);
for (int i = 0; i < list.Count; i++)
{
context.Writer.WriteVarUInt64(list[i]);
}
}
public override List<ulong> ReadData(ReadContext context)
{
return Fallback.ReadData(context);
}
}
internal sealed class ListFloatSerializer : Serializer<List<float>>
{
private static readonly ListSerializer<float> Fallback = new();
public override List<float> DefaultValue => null!;
public override void WriteData(WriteContext context, in List<float> value, bool hasGenerics)
{
List<float> list = value ?? [];
PrimitiveCollectionHeader.WriteListHeader(context, list.Count, hasGenerics, TypeId.Float32, false);
for (int i = 0; i < list.Count; i++)
{
context.Writer.WriteFloat32(list[i]);
}
}
public override List<float> ReadData(ReadContext context)
{
return Fallback.ReadData(context);
}
}
internal sealed class ListDoubleSerializer : Serializer<List<double>>
{
private static readonly ListSerializer<double> Fallback = new();
public override List<double> DefaultValue => null!;
public override void WriteData(WriteContext context, in List<double> value, bool hasGenerics)
{
List<double> list = value ?? [];
PrimitiveCollectionHeader.WriteListHeader(context, list.Count, hasGenerics, TypeId.Float64, false);
for (int i = 0; i < list.Count; i++)
{
context.Writer.WriteFloat64(list[i]);
}
}
public override List<double> ReadData(ReadContext context)
{
return Fallback.ReadData(context);
}
}
internal sealed class ListStringSerializer : Serializer<List<string>>
{
private static readonly ListSerializer<string> Fallback = new();
public override List<string> DefaultValue => null!;
public override void WriteData(WriteContext context, in List<string> value, bool hasGenerics)
{
List<string> list = value ?? [];
bool hasNull = false;
for (int i = 0; i < list.Count; i++)
{
if (list[i] is null)
{
hasNull = true;
break;
}
}
PrimitiveCollectionHeader.WriteListHeader(context, list.Count, hasGenerics, TypeId.String, hasNull);
if (hasNull)
{
for (int i = 0; i < list.Count; i++)
{
string? item = list[i];
if (item is null)
{
context.Writer.WriteInt8((sbyte)RefFlag.Null);
continue;
}
context.Writer.WriteInt8((sbyte)RefFlag.NotNullValue);
StringSerializer.WriteString(context, item);
}
return;
}
for (int i = 0; i < list.Count; i++)
{
StringSerializer.WriteString(context, list[i]);
}
}
public override List<string> ReadData(ReadContext context)
{
return Fallback.ReadData(context);
}
}
internal sealed class SetInt8Serializer : Serializer<HashSet<sbyte>>
{
private static readonly SetSerializer<sbyte> Fallback = new();
public override HashSet<sbyte> DefaultValue => null!;
public override void WriteData(WriteContext context, in HashSet<sbyte> value, bool hasGenerics)
{
HashSet<sbyte> set = value ?? [];
PrimitiveCollectionHeader.WriteListHeader(context, set.Count, hasGenerics, TypeId.Int8, false);
foreach (sbyte item in set)
{
context.Writer.WriteInt8(item);
}
}
public override HashSet<sbyte> ReadData(ReadContext context)
{
return Fallback.ReadData(context);
}
}
internal sealed class SetInt16Serializer : Serializer<HashSet<short>>
{
private static readonly SetSerializer<short> Fallback = new();
public override HashSet<short> DefaultValue => null!;
public override void WriteData(WriteContext context, in HashSet<short> value, bool hasGenerics)
{
HashSet<short> set = value ?? [];
PrimitiveCollectionHeader.WriteListHeader(context, set.Count, hasGenerics, TypeId.Int16, false);
foreach (short item in set)
{
context.Writer.WriteInt16(item);
}
}
public override HashSet<short> ReadData(ReadContext context)
{
return Fallback.ReadData(context);
}
}
internal sealed class SetIntSerializer : Serializer<HashSet<int>>
{
private static readonly SetSerializer<int> Fallback = new();
public override HashSet<int> DefaultValue => null!;
public override void WriteData(WriteContext context, in HashSet<int> value, bool hasGenerics)
{
HashSet<int> set = value ?? [];
PrimitiveCollectionHeader.WriteListHeader(context, set.Count, hasGenerics, TypeId.VarInt32, false);
foreach (int item in set)
{
context.Writer.WriteVarInt32(item);
}
}
public override HashSet<int> ReadData(ReadContext context)
{
return Fallback.ReadData(context);
}
}
internal sealed class SetLongSerializer : Serializer<HashSet<long>>
{
private static readonly SetSerializer<long> Fallback = new();
public override HashSet<long> DefaultValue => null!;
public override void WriteData(WriteContext context, in HashSet<long> value, bool hasGenerics)
{
HashSet<long> set = value ?? [];
PrimitiveCollectionHeader.WriteListHeader(context, set.Count, hasGenerics, TypeId.VarInt64, false);
foreach (long item in set)
{
context.Writer.WriteVarInt64(item);
}
}
public override HashSet<long> ReadData(ReadContext context)
{
return Fallback.ReadData(context);
}
}
internal sealed class SetUInt8Serializer : Serializer<HashSet<byte>>
{
private static readonly SetSerializer<byte> Fallback = new();
public override HashSet<byte> DefaultValue => null!;
public override void WriteData(WriteContext context, in HashSet<byte> value, bool hasGenerics)
{
HashSet<byte> set = value ?? [];
PrimitiveCollectionHeader.WriteListHeader(context, set.Count, hasGenerics, TypeId.UInt8, false);
foreach (byte item in set)
{
context.Writer.WriteUInt8(item);
}
}
public override HashSet<byte> ReadData(ReadContext context)
{
return Fallback.ReadData(context);
}
}
internal sealed class SetUInt16Serializer : Serializer<HashSet<ushort>>
{
private static readonly SetSerializer<ushort> Fallback = new();
public override HashSet<ushort> DefaultValue => null!;
public override void WriteData(WriteContext context, in HashSet<ushort> value, bool hasGenerics)
{
HashSet<ushort> set = value ?? [];
PrimitiveCollectionHeader.WriteListHeader(context, set.Count, hasGenerics, TypeId.UInt16, false);
foreach (ushort item in set)
{
context.Writer.WriteUInt16(item);
}
}
public override HashSet<ushort> ReadData(ReadContext context)
{
return Fallback.ReadData(context);
}
}
internal sealed class SetUIntSerializer : Serializer<HashSet<uint>>
{
private static readonly SetSerializer<uint> Fallback = new();
public override HashSet<uint> DefaultValue => null!;
public override void WriteData(WriteContext context, in HashSet<uint> value, bool hasGenerics)
{
HashSet<uint> set = value ?? [];
PrimitiveCollectionHeader.WriteListHeader(context, set.Count, hasGenerics, TypeId.VarUInt32, false);
foreach (uint item in set)
{
context.Writer.WriteVarUInt32(item);
}
}
public override HashSet<uint> ReadData(ReadContext context)
{
return Fallback.ReadData(context);
}
}
internal sealed class SetULongSerializer : Serializer<HashSet<ulong>>
{
private static readonly SetSerializer<ulong> Fallback = new();
public override HashSet<ulong> DefaultValue => null!;
public override void WriteData(WriteContext context, in HashSet<ulong> value, bool hasGenerics)
{
HashSet<ulong> set = value ?? [];
PrimitiveCollectionHeader.WriteListHeader(context, set.Count, hasGenerics, TypeId.VarUInt64, false);
foreach (ulong item in set)
{
context.Writer.WriteVarUInt64(item);
}
}
public override HashSet<ulong> ReadData(ReadContext context)
{
return Fallback.ReadData(context);
}
}
internal sealed class SetFloatSerializer : Serializer<HashSet<float>>
{
private static readonly SetSerializer<float> Fallback = new();
public override HashSet<float> DefaultValue => null!;
public override void WriteData(WriteContext context, in HashSet<float> value, bool hasGenerics)
{
HashSet<float> set = value ?? [];
PrimitiveCollectionHeader.WriteListHeader(context, set.Count, hasGenerics, TypeId.Float32, false);
foreach (float item in set)
{
context.Writer.WriteFloat32(item);
}
}
public override HashSet<float> ReadData(ReadContext context)
{
return Fallback.ReadData(context);
}
}
internal sealed class SetDoubleSerializer : Serializer<HashSet<double>>
{
private static readonly SetSerializer<double> Fallback = new();
public override HashSet<double> DefaultValue => null!;
public override void WriteData(WriteContext context, in HashSet<double> value, bool hasGenerics)
{
HashSet<double> set = value ?? [];
PrimitiveCollectionHeader.WriteListHeader(context, set.Count, hasGenerics, TypeId.Float64, false);
foreach (double item in set)
{
context.Writer.WriteFloat64(item);
}
}
public override HashSet<double> ReadData(ReadContext context)
{
return Fallback.ReadData(context);
}
}
internal class PrimitiveLinkedListSerializer<T, TCodec> : Serializer<LinkedList<T>>
where TCodec : struct, IPrimitiveDictionaryCodec<T>
{
private static readonly LinkedListSerializer<T> Fallback = new();
public override LinkedList<T> DefaultValue => null!;
public override void WriteData(WriteContext context, in LinkedList<T> value, bool hasGenerics)
{
if (TCodec.IsNullable)
{
throw new InvalidDataException("nullable primitive codecs are not supported for linked-list fast path");
}
LinkedList<T> list = value ?? new LinkedList<T>();
PrimitiveCollectionHeader.WriteListHeader(context, list.Count, hasGenerics, TCodec.WireTypeId, false);
foreach (T item in list)
{
TCodec.Write(context, item);
}
}
public override LinkedList<T> ReadData(ReadContext context)
{
return Fallback.ReadData(context);
}
}
internal class PrimitiveQueueSerializer<T, TCodec> : Serializer<Queue<T>>
where TCodec : struct, IPrimitiveDictionaryCodec<T>
{
private static readonly QueueSerializer<T> Fallback = new();
public override Queue<T> DefaultValue => null!;
public override void WriteData(WriteContext context, in Queue<T> value, bool hasGenerics)
{
if (TCodec.IsNullable)
{
throw new InvalidDataException("nullable primitive codecs are not supported for queue fast path");
}
Queue<T> queue = value ?? new Queue<T>();
PrimitiveCollectionHeader.WriteListHeader(context, queue.Count, hasGenerics, TCodec.WireTypeId, false);
foreach (T item in queue)
{
TCodec.Write(context, item);
}
}
public override Queue<T> ReadData(ReadContext context)
{
return Fallback.ReadData(context);
}
}
internal class PrimitiveStackSerializer<T, TCodec> : Serializer<Stack<T>>
where TCodec : struct, IPrimitiveDictionaryCodec<T>
{
private static readonly StackSerializer<T> Fallback = new();
public override Stack<T> DefaultValue => null!;
public override void WriteData(WriteContext context, in Stack<T> value, bool hasGenerics)
{
if (TCodec.IsNullable)
{
throw new InvalidDataException("nullable primitive codecs are not supported for stack fast path");
}
Stack<T> stack = value ?? new Stack<T>();
PrimitiveCollectionHeader.WriteListHeader(context, stack.Count, hasGenerics, TCodec.WireTypeId, false);
if (stack.Count == 0)
{
return;
}
T[] topToBottom = stack.ToArray();
for (int i = topToBottom.Length - 1; i >= 0; i--)
{
TCodec.Write(context, topToBottom[i]);
}
}
public override Stack<T> ReadData(ReadContext context)
{
return Fallback.ReadData(context);
}
}
internal class PrimitiveSortedSetSerializer<T, TCodec> : Serializer<SortedSet<T>>
where T : notnull
where TCodec : struct, IPrimitiveDictionaryCodec<T>
{
private static readonly SortedSetSerializer<T> Fallback = new();
public override SortedSet<T> DefaultValue => null!;
public override void WriteData(WriteContext context, in SortedSet<T> value, bool hasGenerics)
{
if (TCodec.IsNullable)
{
throw new InvalidDataException("nullable primitive codecs are not supported for sorted-set fast path");
}
SortedSet<T> set = value ?? new SortedSet<T>();
PrimitiveCollectionHeader.WriteListHeader(context, set.Count, hasGenerics, TCodec.WireTypeId, false);
foreach (T item in set)
{
TCodec.Write(context, item);
}
}
public override SortedSet<T> ReadData(ReadContext context)
{
return Fallback.ReadData(context);
}
}
internal class PrimitiveImmutableHashSetSerializer<T, TCodec> : Serializer<ImmutableHashSet<T>>
where T : notnull
where TCodec : struct, IPrimitiveDictionaryCodec<T>
{
private static readonly ImmutableHashSetSerializer<T> Fallback = new();
public override ImmutableHashSet<T> DefaultValue => null!;
public override void WriteData(WriteContext context, in ImmutableHashSet<T> value, bool hasGenerics)
{
if (TCodec.IsNullable)
{
throw new InvalidDataException("nullable primitive codecs are not supported for immutable-hash-set fast path");
}
ImmutableHashSet<T> set = value ?? ImmutableHashSet<T>.Empty;
PrimitiveCollectionHeader.WriteListHeader(context, set.Count, hasGenerics, TCodec.WireTypeId, false);
foreach (T item in set)
{
TCodec.Write(context, item);
}
}
public override ImmutableHashSet<T> ReadData(ReadContext context)
{
return Fallback.ReadData(context);
}
}