Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion nanoFramework.CoreLibrary/CoreLibrary.nfproj
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
<Compile Include="System\Collections\Generic\IEnumerator.cs" />
<Compile Include="System\Diagnostics\StackTraceHiddenAttribute.cs" />
<Compile Include="System\Nullable.cs" />
<Compile Include="System\Runtime\CompilerServices\Unsafe.cs" />
<Compile Include="System\Runtime\InteropServices\InAttribute .cs" />
<Compile Include="System\Diagnostics\NativeProfiledAttribute.cs" />
<Compile Include="System\PlatformNotSupportedException.cs" />
Expand Down Expand Up @@ -262,4 +263,4 @@
<Import Project="..\packages\Microsoft.SourceLink.Common.1.1.1\build\Microsoft.SourceLink.Common.targets" Condition="Exists('..\packages\Microsoft.SourceLink.Common.1.1.1\build\Microsoft.SourceLink.Common.targets')" />
<Import Project="..\packages\Microsoft.SourceLink.GitHub.1.1.1\build\Microsoft.SourceLink.GitHub.targets" Condition="Exists('..\packages\Microsoft.SourceLink.GitHub.1.1.1\build\Microsoft.SourceLink.GitHub.targets')" />
<Import Project="..\packages\Nerdbank.GitVersioning.3.7.115\build\Nerdbank.GitVersioning.targets" Condition="Exists('..\packages\Nerdbank.GitVersioning.3.7.115\build\Nerdbank.GitVersioning.targets')" />
</Project>
</Project>
152 changes: 152 additions & 0 deletions nanoFramework.CoreLibrary/System/Array.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@

using System.Collections;
using System.Runtime.CompilerServices;
#if NANOCLR_REFLECTION
using System.Collections.Generic;
using System.Diagnostics;
#endif // NANOCLR_REFLECTION

namespace System
{
Expand Down Expand Up @@ -429,5 +433,153 @@ public void Reset()
_index = _startIndex - 1;
}
}

#if NANOCLR_REFLECTION
#pragma warning disable CA1822 // Mark members as static
//----------------------------------------------------------------------------------------
// ! READ THIS BEFORE YOU WORK ON THIS CLASS.
//
// The methods on this class must be written VERY carefully to avoid introducing security holes.
// That's because they are invoked with special "this"! The "this" object
// for all of these methods are not SZArrayHelper objects. Rather, they are of type U[]
// where U[] is castable to T[]. No actual SZArrayHelper object is ever instantiated. Thus, you will
// see a lot of expressions that cast "this" "T[]".
//
// This class is needed to allow an SZ array of type T[] to expose IList<T>,
// IList<T.BaseType>, etc., etc. all the way up to IList<Object>. When the following call is
// made:
//
// ((IList<T>) (new U[n])).SomeIListMethod()
//
// the interface stub dispatcher treats this as a special case, loads up SZArrayHelper,
// finds the corresponding generic method (matched simply by method name), instantiates
// it for type <T> and executes it.
//
// The "T" will reflect the interface used to invoke the method. The actual runtime "this" will be
// array that is castable to "T[]" (i.e. for primitives and valuetypes, it will be exactly
// "T[]" - for orefs, it may be a "U[]" where U derives from T.)
//----------------------------------------------------------------------------------------
internal sealed class SZArrayHelper
{
// It is never legal to instantiate this class.
private SZArrayHelper()
{
Debug.Assert(false, "Hey! How'd I get here?");
}

internal IEnumerator<T> GetEnumerator<T>()
{
// ! Warning: "this" is an array, not an SZArrayHelper. See comments above
// ! or you may introduce a security hole!
T[] @this = Unsafe.As<T[]>(this);
int length = @this.Length;
return length == 0 ? SZGenericArrayEnumerator<T>.Empty : new SZGenericArrayEnumerator<T>(@this, length);
}

private void CopyTo<T>(T[] array, int index)
{
// ! Warning: "this" is an array, not an SZArrayHelper. See comments above
// ! or you may introduce a security hole!

T[] @this = Unsafe.As<T[]>(this);
Array.Copy(@this, 0, array, index, @this.Length);
}

internal int get_Count<T>()
{
// ! Warning: "this" is an array, not an SZArrayHelper. See comments above
// ! or you may introduce a security hole!
T[] @this = Unsafe.As<T[]>(this);
return @this.Length;
}

internal T get_Item<T>(int index)
{
// ! Warning: "this" is an array, not an SZArrayHelper. See comments above
// ! or you may introduce a security hole!

T[] @this = Unsafe.As<T[]>(this);
if ((uint)index >= (uint)@this.Length)
{
#pragma warning disable S3928 // Parameter names used into ArgumentException constructors should match an existing one
throw new ArgumentOutOfRangeException();
#pragma warning restore S3928 // Parameter names used into ArgumentException constructors should match an existing one
}

return @this[index];
}

internal void set_Item<T>(int index, T value)
{
// ! Warning: "this" is an array, not an SZArrayHelper. See comments above
// ! or you may introduce a security hole!
T[] @this = Unsafe.As<T[]>(this);
if ((uint)index >= (uint)@this.Length)
{
#pragma warning disable S3928 // Parameter names used into ArgumentException constructors should match an existing one
throw new ArgumentOutOfRangeException();
#pragma warning restore S3928 // Parameter names used into ArgumentException constructors should match an existing one
}

@this[index] = value;
}

private void Add<T>(T _)
{
// Not meaningful for arrays.
throw new NotSupportedException();
}

private bool Contains<T>(T value)
{
// ! Warning: "this" is an array, not an SZArrayHelper. See comments above
// ! or you may introduce a security hole!
T[] @this = Unsafe.As<T[]>(this);
return Array.IndexOf(@this, value, 0, @this.Length) >= 0;
}

private bool get_IsReadOnly<T>()
{
return true;
}

private void Clear<T>()
{
// ! Warning: "this" is an array, not an SZArrayHelper. See comments above
// ! or you may introduce a security hole!

throw new NotSupportedException();
}

private int IndexOf<T>(T value)
{
// ! Warning: "this" is an array, not an SZArrayHelper. See comments above
// ! or you may introduce a security hole!
T[] @this = Unsafe.As<T[]>(this);
return Array.IndexOf(@this, value, 0, @this.Length);
}

private void Insert<T>(int _, T _1)
{
// Not meaningful for arrays
throw new NotSupportedException();
}

private bool Remove<T>(T _)
{
// Not meaningful for arrays
throw new NotSupportedException();
return default;
}

private void RemoveAt<T>(int _)
{
// Not meaningful for arrays
throw new NotSupportedException();
}
}
#pragma warning restore CA1822

#endif
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#if NANOCLR_REFLECTION
#nullable enable

namespace System.Runtime.CompilerServices
{
/// <summary>
/// Contains generic, low-level functionality for manipulating pointers.
/// </summary>
public static unsafe partial class Unsafe
{
/// <summary>
/// Casts the given object to the specified type, performs no dynamic type checking.
/// </summary>
/// <typeparam name="T">The target reference type. The return value will be of this type.</typeparam>
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern T? As<T>(object? o) where T : class?;
}
}

#endif
Loading