Skip to content
Merged
15 changes: 15 additions & 0 deletions core/Extensions/TextExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,21 @@ public static long GetLongHashCode(this string text)
}
}

public static long GetLongHashCode(this Span<char> text)
{
unchecked
{
long hash = 3074457345618258791;
for (int i = 0; i < text.Length; i++)
{
hash += text[i];
hash *= 3074457345618258799;
}

return hash;
}
}

public static long GetLongHashCode(this ReadOnlySpan<char> text)
{
unchecked
Expand Down
135 changes: 135 additions & 0 deletions core/Field.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
using System;

namespace Types
{
/// <summary>
/// Describes a field declared in a <see cref="Types.Type"/>.
/// </summary>
public readonly struct Field : IEquatable<Field>
{
internal readonly long typeHash;
internal readonly long nameHash;

/// <summary>
/// The type of the field.
/// </summary>
public readonly Type Type => MetadataRegistry.GetType(typeHash);

/// <summary>
/// Name of the field.
/// </summary>
public readonly ReadOnlySpan<char> Name => TypeNames.Get(nameHash);

/// <summary>
/// Size of the field in bytes.
/// </summary>
public readonly ushort Size => Type.size;

#if NET
/// <summary>
/// Not supported.
/// </summary>
[Obsolete("Default constructor not supported", true)]
public Field()
{
}
#endif

internal Field(long typeHash, long nameHash)
{
this.typeHash = typeHash;
this.nameHash = nameHash;
}

/// <summary>
/// Creates a new field with the given <paramref name="fieldName"/> and <paramref name="fullTypeName"/>.
/// </summary>
public Field(string fieldName, string fullTypeName)
{
nameHash = TypeNames.Set(fieldName);
typeHash = fullTypeName.GetLongHashCode();
}

/// <summary>
/// Creates a new field with the given <paramref name="fieldName"/> and <paramref name="fullTypeName"/>.
/// </summary>
public Field(ReadOnlySpan<char> fieldName, ReadOnlySpan<char> fullTypeName)
{
nameHash = TypeNames.Set(fieldName);
typeHash = fullTypeName.GetLongHashCode();
}

/// <summary>
/// Creates a new field with the given <paramref name="fieldName"/> and <paramref name="typeHash"/>.
/// </summary>
public Field(string fieldName, int typeHash)
{
nameHash = TypeNames.Set(fieldName);
this.typeHash = typeHash;
}

/// <inheritdoc/>
public readonly override string ToString()
{
Span<char> buffer = stackalloc char[256];
int length = ToString(buffer);
return buffer.Slice(0, length).ToString();
}

/// <summary>
/// Builds a string representation of this field and writes it to <paramref name="buffer"/>.
/// </summary>
/// <returns>Amount of characters written.</returns>
public readonly int ToString(Span<char> buffer)
{
Type type = Type;
type.Name.CopyTo(buffer);
int length = type.Name.Length;
buffer[length++] = '=';
Name.CopyTo(buffer.Slice(length));
length += Name.Length;
return length;
}

/// <inheritdoc/>
public readonly override bool Equals(object? obj)
{
return obj is Field field && Equals(field);
}

/// <inheritdoc/>
public readonly bool Equals(Field other)
{
return nameHash == other.nameHash && typeHash == other.typeHash;
}

/// <inheritdoc/>
public readonly override int GetHashCode()
{
unchecked
{
int hashCode = 17;
ReadOnlySpan<char> name = Name;
for (int i = 0; i < name.Length; i++)
{
hashCode = hashCode * 31 + name[i];
}

hashCode = hashCode * 31 + (int)typeHash;
return hashCode;
}
}

/// <inheritdoc/>
public static bool operator ==(Field left, Field right)
{
return left.Equals(right);
}

/// <inheritdoc/>
public static bool operator !=(Field left, Field right)
{
return !(left == right);
}
}
}
59 changes: 59 additions & 0 deletions core/FieldBuffer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using System;
using System.Diagnostics;

namespace Types
{
/// <summary>
/// Buffer for storing <see cref="Field"/> values.
/// </summary>
public unsafe struct FieldBuffer
{
/// <summary>
/// Maximum amount that can be stored.
/// </summary>
public const int Capacity = 32;

private fixed long buffer[Capacity];

/// <summary>
/// Indexer for accessing the value at the given <paramref name="index"/>.
/// </summary>
public Field this[int index]
{
readonly get
{
long typeHash = buffer[index * 2 + 0];
long nameHash = buffer[index * 2 + 1];
return new(typeHash, nameHash);
}
set
{
buffer[index * 2 + 0] = value.typeHash;
buffer[index * 2 + 1] = value.nameHash;
}
}

/// <summary>
/// Creates a new buffer containing the given <paramref name="fields"/>.
/// </summary>
public FieldBuffer(ReadOnlySpan<Field> fields)
{
ThrowIfCantFit(fields.Length);

for (int i = 0; i < fields.Length; i++)
{
buffer[i * 2 + 0] = fields[i].typeHash;
buffer[i * 2 + 1] = fields[i].nameHash;
}
}

[Conditional("DEBUG")]
private static void ThrowIfCantFit(int length)
{
if (length > Capacity)
{
throw new ArgumentOutOfRangeException(nameof(length), $"Cannot fit {length} types into a buffer of capacity {Capacity}");
}
}
}
}
66 changes: 0 additions & 66 deletions core/Functions/Register.cs

This file was deleted.

76 changes: 76 additions & 0 deletions core/Functions/RegisterFunction.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
using System;

namespace Types.Functions
{
/// <summary>
/// Function to register a type.
/// </summary>
public readonly struct RegisterFunction
{
/// <summary>
/// Registers a type with the given <paramref name="variables"/> and <paramref name="interfaces"/>.
/// </summary>
public unsafe readonly void RegisterType<T>(ReadOnlySpan<Field> variables, ReadOnlySpan<Interface> interfaces) where T : unmanaged
{
Type type = new(MetadataRegistry.GetFullName<T>(), (ushort)sizeof(T), variables, interfaces);
MetadataRegistry.RegisterType(type, RuntimeTypeTable.GetHandle<T>());
TypeInstanceCreator.Initialize<T>(type);
}

/// <summary>
/// Registers a type with the given <paramref name="variables"/> and <paramref name="interfaces"/>.
/// </summary>
public unsafe readonly void RegisterType<T>(FieldBuffer variables, byte variableCount, InterfaceTypeBuffer interfaces, byte interfaceCount) where T : unmanaged
{
Type type = new(MetadataRegistry.GetFullName<T>(), (ushort)sizeof(T), variables, variableCount, interfaces, interfaceCount);
MetadataRegistry.RegisterType(type, RuntimeTypeTable.GetHandle<T>());
TypeInstanceCreator.Initialize<T>(type);
}

/// <summary>
/// Registers a type without variables specified.
/// </summary>
public unsafe readonly void RegisterType<T>() where T : unmanaged
{
Type type = new(MetadataRegistry.GetFullName<T>(), (ushort)sizeof(T));
MetadataRegistry.RegisterType(type, RuntimeTypeTable.GetHandle<T>());
TypeInstanceCreator.Initialize<T>(type);
}

/// <summary>
/// Registers a type without variables specified.
/// </summary>
public readonly void RegisterInterface<T>()
{
Interface interfaceValue = new(MetadataRegistry.GetFullName<T>());
MetadataRegistry.RegisterInterface(interfaceValue, RuntimeTypeTable.GetHandle<T>());
}

/// <summary>
/// Input parameter.
/// </summary>
public readonly struct Input
{
/// <summary>
/// Metadata of the type.
/// </summary>
public readonly Type type;

private readonly nint handle;

/// <summary>
/// Handle of the registering type.
/// </summary>
public readonly RuntimeTypeHandle Handle => RuntimeTypeTable.GetHandle(handle);

/// <summary>
/// Creates the input argument.
/// </summary>
public Input(Type type, RuntimeTypeHandle handle)
{
this.type = type;
this.handle = RuntimeTypeTable.GetAddress(handle);
}
}
}
}
4 changes: 2 additions & 2 deletions core/ITypeBank.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ namespace Types
public interface ITypeBank
{
/// <summary>
/// Loads type metadata into <see cref="TypeRegistry"/>.
/// Loads type metadata into <see cref="MetadataRegistry"/>.
/// </summary>
void Load(Register register);
void Load(RegisterFunction register);
}
}
Loading