Hey guys, I have a generic class where I’m accepting a key and value for a nativeparallelhashmap.
public class Hashmap<TKey, TValue> where TKey : struct where TValue : unmanaged
{
unsafe public void Save(string folder, string file, NativeParallelHashMap<TKey, TValue> nodes)
{
// save our node data to binary file in our map folder
Function.HashmapAdapter<TKey, TValue> adapter = new();
BinarySerializationParameters prams = new() { UserDefinedAdapters = new() { adapter } };
var buffer = new UnsafeAppendBuffer(nodes.Count(), UnsafeUtility.AlignOf<byte>(), Allocator.Temp);
try {
BinarySerialization.ToBinary(&buffer, nodes, prams);
File.WriteAllBytes(folder + file, buffer.ToBytesNBC());
}
finally { buffer.Dispose(); }
}
}
But I get an error on the TKey part.
The type 'TKey' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'TKey' in the generic type or method 'HashmapAdapter<TKey, TValue>'
I feel like the struct constraint should ensure its non nullable value type right?
Here are the constraints on the hashmap adapter.
unsafe class HashmapAdapter<TKey, TValue> : IBinaryAdapter<NativeParallelHashMap<TKey, TValue>> where TKey : unmanaged, IEquatable<TKey> where TValue : unmanaged
The error is describing a requirement for an unmanaged value type. struct only requires a value type, with no requirement that there are no reference type fields.
TKey constraint has to be unmanaged just like TValue. You’re matching your adapter type which currently already specifies unmanaged for TKey.
Thanks for reply Spy-Master, ya I tried unmanaged for TKey but it still gave me the error. It only gives it to me for TKey and not TValue for some reason.
unsafe public NativeParallelHashMap<TKey, TValue> Load<TKey, TValue>(string folder, string file) where TKey : unmanaged where TValue : unmanaged
{
// load our nodes from map binary data file and return
Function.HashmapAdapter<TKey, TValue> adapter = new();
BinarySerializationParameters prams = new() { UserDefinedAdapters = new() { adapter } };
byte[] data = File.ReadAllBytes(folder + file);
fixed (void* buffer = data)
{
var reader = new UnsafeAppendBuffer.Reader(buffer, data.Length);
return BinarySerialization.FromBinary<NativeParallelHashMap<TKey, TValue>>(&reader, prams);
}
}
unsafe class HashmapAdapter<TKey, TValue> : IBinaryAdapter<NativeParallelHashMap<TKey, TValue>> where TKey : unmanaged, IEquatable<TKey> where TValue : unmanaged
{
public void Serialize(in BinarySerializationContext<NativeParallelHashMap<TKey, TValue>> context, NativeParallelHashMap<TKey, TValue> value)
{
var copy = value.GetKeyValueArrays(Allocator.Temp);
try { context.Writer->Add(copy.Keys); context.Writer->Add(copy.Values); }
finally { copy.Dispose(); }
}
public NativeParallelHashMap<TKey, TValue> Deserialize(in BinaryDeserializationContext<NativeParallelHashMap<TKey, TValue>> context)
{
NativeArray<TKey> keys = default;
NativeArray<TValue> values = default;
try {
context.Reader->ReadNext<TKey>(out keys, Allocator.Temp);
context.Reader->ReadNext<TValue>(out values, Allocator.Temp);
var map = new NativeParallelHashMap<TKey, TValue>(keys.Length, Allocator.Persistent);
for (int index = 0; index < keys.Length; index++) { map.Add(keys[index], values[index]); }
return map;
}
finally {
if (keys.IsCreated) { keys.Dispose(); }
if (values.IsCreated) { values.Dispose(); }
}
}
}
Woops, I just found new error related to boxing conversion.
The type 'TKey' cannot be used as type parameter 'TKey' in the generic type or method 'NativeParallelHashMap<TKey, TValue>'. There is no boxing conversion or type parameter conversion from 'TKey' to 'System.IEquatable<TKey>'.
You need to retain generic type parameter constraints like required interfaces on other generic types/methods that use it. This means you need to specify the IEquatable constraint on TKey for the Load method as well.