Skip to content

Commit

Permalink
release v3.0.4
Browse files Browse the repository at this point in the history
## Nino.Serialization v3.0.4
- [Fix] Skip collecting static public members
- [Feat] Support \`ReadOnlySpan<byte>\` for deserialization
  • Loading branch information
JasonXuDeveloper committed Nov 16, 2024
1 parent b0200ee commit 1855374
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 20 deletions.
19 changes: 8 additions & 11 deletions src/Nino.Core/Reader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ namespace Nino.Core
{
public ref struct Reader
{
private Span<byte> _data;
private ReadOnlySpan<byte> _data;

public Reader(Span<byte> buffer)
public Reader(ReadOnlySpan<byte> buffer)
{
_data = buffer;
}
Expand Down Expand Up @@ -50,7 +50,7 @@ public bool ReadCollectionHeader(out int length)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Read<T>(out T value) where T : unmanaged
{
value = Unsafe.ReadUnaligned<T>(ref _data[0]);
value = Unsafe.ReadUnaligned<T>(ref MemoryMarshal.GetReference(_data));
_data = _data.Slice(Unsafe.SizeOf<T>());
}

Expand Down Expand Up @@ -84,7 +84,7 @@ public void Read<T>(out T[] ret) where T : unmanaged
ret = new T[length];
#endif
ref byte first = ref Unsafe.As<T, byte>(ref ret[0]);
Unsafe.CopyBlockUnaligned(ref first, ref bytes[0], (uint)bytes.Length);
Unsafe.CopyBlockUnaligned(ref first, ref MemoryMarshal.GetReference(bytes), (uint)bytes.Length);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
Expand Down Expand Up @@ -123,7 +123,7 @@ public void Read<T>(out List<T> ret) where T : unmanaged
var arr = new T[length];
#endif
ref byte first = ref Unsafe.As<T, byte>(ref arr[0]);
Unsafe.CopyBlockUnaligned(ref first, ref bytes[0], (uint)bytes.Length);
Unsafe.CopyBlockUnaligned(ref first, ref MemoryMarshal.GetReference(bytes), (uint)bytes.Length);
lst._items = arr;
}

Expand Down Expand Up @@ -213,7 +213,7 @@ public void ReadUtf8(out string ret)
#if NET5_0_OR_GREATER
unsafe
{
ret = string.Create(length, (IntPtr)Unsafe.AsPointer(ref utf8Bytes[0]),
ret = string.Create(length, (IntPtr)Unsafe.AsPointer(ref MemoryMarshal.GetReference(utf8Bytes)),
(dst, ptr) =>
{
var src = new Span<byte>((byte*)ptr, length);
Expand Down Expand Up @@ -245,17 +245,14 @@ public void Read(out string ret)

GetBytes(length * sizeof(char), out var utf16Bytes);
#if NET5_0_OR_GREATER
ret = new string(
MemoryMarshal.CreateReadOnlySpan(
ref Unsafe.As<byte, char>(ref utf16Bytes[0]),
length));
ret = new string(MemoryMarshal.Cast<byte, char>(utf16Bytes));
#else
ret = MemoryMarshal.Cast<byte, char>(utf16Bytes).ToString();
#endif
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void GetBytes(int length, out Span<byte> bytes)
private void GetBytes(int length, out ReadOnlySpan<byte> bytes)
{
bytes = _data.Slice(0, length);
_data = _data.Slice(length);
Expand Down
4 changes: 2 additions & 2 deletions src/Nino.Generator/DeserializerGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,9 @@ public static partial class Deserializer
{{GeneratePrivateDeserializeImplMethodBody("T", " ", "<T>", "where T : unmanaged")}}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Deserialize<T>(Span<byte> data, out T value) where T : unmanaged
public static void Deserialize<T>(ReadOnlySpan<byte> data, out T value) where T : unmanaged
{
value = Unsafe.ReadUnaligned<T>(ref data[0]);
value = Unsafe.ReadUnaligned<T>(ref MemoryMarshal.GetReference(data));
}
{{GeneratePrivateDeserializeImplMethodBody("T[]", " ", "<T>", "where T : unmanaged")}}
Expand Down
21 changes: 14 additions & 7 deletions src/Nino.Generator/NinoTypeHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,7 @@ public static string GeneratePublicDeserializeMethodBody(this string typeName, s
{
var ret = $$"""
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Deserialize{{typeParam}}(Span<byte> data, out {{typeName}} value) {{genericConstraint}}
public static void Deserialize{{typeParam}}(ReadOnlySpan<byte> data, out {{typeName}} value) {{genericConstraint}}
{
var reader = new Reader(data);
Deserialize(out value, ref reader);
Expand Down Expand Up @@ -698,16 +698,18 @@ public static List<NinoMember> GetNinoTypeMembers(

if (m is IFieldSymbol fieldSymbol)
{
//has to be public
return fieldSymbol.DeclaredAccessibility == Accessibility.Public;
//has to be public and not static
return fieldSymbol.DeclaredAccessibility == Accessibility.Public &&
!fieldSymbol.IsStatic;
}

if (m is IPropertySymbol propertySymbol)
{
//has to be public and has getter and setter
//has to be public and has getter and setter and not static
return propertySymbol.DeclaredAccessibility == Accessibility.Public &&
propertySymbol.GetMethod != null &&
propertySymbol.SetMethod != null;
propertySymbol.SetMethod != null &&
!propertySymbol.IsStatic;
}

return false;
Expand All @@ -718,7 +720,10 @@ public static List<NinoMember> GetNinoTypeMembers(
{
// Retrieve all public instance constructors
var publicConstructors = namedTypeSymbol.InstanceConstructors
.Where(c => c.DeclaredAccessibility == Accessibility.Public && !c.IsImplicitlyDeclared)
.Where(c => c.DeclaredAccessibility == Accessibility.Public
&& !c.IsImplicitlyDeclared
&& !c.IsStatic
)
.ToList();

foreach (var constructor in publicConstructors)
Expand All @@ -728,7 +733,9 @@ public static List<NinoMember> GetNinoTypeMembers(
{
var matchingProperty = namedTypeSymbol.GetMembers()
.OfType<IPropertySymbol>()
.FirstOrDefault(p => p.Name.Equals(parameter.Name, StringComparison.OrdinalIgnoreCase));
.FirstOrDefault(p =>
p.Name.Equals(parameter.Name, StringComparison.OrdinalIgnoreCase)
&& !p.IsStatic);

// If any parameter does not have a matching readonly property, it’s likely not a primary constructor
if (matchingProperty == null || !matchingProperty.IsReadOnly)
Expand Down

0 comments on commit 1855374

Please sign in to comment.