|
3 | 3 |
|
4 | 4 | using System.Collections; |
5 | 5 | using System.Runtime.CompilerServices; |
| 6 | +#if NANOCLR_REFLECTION |
| 7 | +using System.Collections.Generic; |
| 8 | +using System.Diagnostics; |
| 9 | +#endif // NANOCLR_REFLECTION |
6 | 10 |
|
7 | 11 | namespace System |
8 | 12 | { |
@@ -429,5 +433,153 @@ public void Reset() |
429 | 433 | _index = _startIndex - 1; |
430 | 434 | } |
431 | 435 | } |
| 436 | + |
| 437 | +#if NANOCLR_REFLECTION |
| 438 | +#pragma warning disable CA1822 // Mark members as static |
| 439 | + //---------------------------------------------------------------------------------------- |
| 440 | + // ! READ THIS BEFORE YOU WORK ON THIS CLASS. |
| 441 | + // |
| 442 | + // The methods on this class must be written VERY carefully to avoid introducing security holes. |
| 443 | + // That's because they are invoked with special "this"! The "this" object |
| 444 | + // for all of these methods are not SZArrayHelper objects. Rather, they are of type U[] |
| 445 | + // where U[] is castable to T[]. No actual SZArrayHelper object is ever instantiated. Thus, you will |
| 446 | + // see a lot of expressions that cast "this" "T[]". |
| 447 | + // |
| 448 | + // This class is needed to allow an SZ array of type T[] to expose IList<T>, |
| 449 | + // IList<T.BaseType>, etc., etc. all the way up to IList<Object>. When the following call is |
| 450 | + // made: |
| 451 | + // |
| 452 | + // ((IList<T>) (new U[n])).SomeIListMethod() |
| 453 | + // |
| 454 | + // the interface stub dispatcher treats this as a special case, loads up SZArrayHelper, |
| 455 | + // finds the corresponding generic method (matched simply by method name), instantiates |
| 456 | + // it for type <T> and executes it. |
| 457 | + // |
| 458 | + // The "T" will reflect the interface used to invoke the method. The actual runtime "this" will be |
| 459 | + // array that is castable to "T[]" (i.e. for primitives and valuetypes, it will be exactly |
| 460 | + // "T[]" - for orefs, it may be a "U[]" where U derives from T.) |
| 461 | + //---------------------------------------------------------------------------------------- |
| 462 | + internal sealed class SZArrayHelper |
| 463 | + { |
| 464 | + // It is never legal to instantiate this class. |
| 465 | + private SZArrayHelper() |
| 466 | + { |
| 467 | + Debug.Assert(false, "Hey! How'd I get here?"); |
| 468 | + } |
| 469 | + |
| 470 | + internal IEnumerator<T> GetEnumerator<T>() |
| 471 | + { |
| 472 | + // ! Warning: "this" is an array, not an SZArrayHelper. See comments above |
| 473 | + // ! or you may introduce a security hole! |
| 474 | + T[] @this = Unsafe.As<T[]>(this); |
| 475 | + int length = @this.Length; |
| 476 | + return length == 0 ? SZGenericArrayEnumerator<T>.Empty : new SZGenericArrayEnumerator<T>(@this, length); |
| 477 | + } |
| 478 | + |
| 479 | + private void CopyTo<T>(T[] array, int index) |
| 480 | + { |
| 481 | + // ! Warning: "this" is an array, not an SZArrayHelper. See comments above |
| 482 | + // ! or you may introduce a security hole! |
| 483 | + |
| 484 | + T[] @this = Unsafe.As<T[]>(this); |
| 485 | + Array.Copy(@this, 0, array, index, @this.Length); |
| 486 | + } |
| 487 | + |
| 488 | + internal int get_Count<T>() |
| 489 | + { |
| 490 | + // ! Warning: "this" is an array, not an SZArrayHelper. See comments above |
| 491 | + // ! or you may introduce a security hole! |
| 492 | + T[] @this = Unsafe.As<T[]>(this); |
| 493 | + return @this.Length; |
| 494 | + } |
| 495 | + |
| 496 | + internal T get_Item<T>(int index) |
| 497 | + { |
| 498 | + // ! Warning: "this" is an array, not an SZArrayHelper. See comments above |
| 499 | + // ! or you may introduce a security hole! |
| 500 | + |
| 501 | + T[] @this = Unsafe.As<T[]>(this); |
| 502 | + if ((uint)index >= (uint)@this.Length) |
| 503 | + { |
| 504 | +#pragma warning disable S3928 // Parameter names used into ArgumentException constructors should match an existing one |
| 505 | + throw new ArgumentOutOfRangeException(); |
| 506 | +#pragma warning restore S3928 // Parameter names used into ArgumentException constructors should match an existing one |
| 507 | + } |
| 508 | + |
| 509 | + return @this[index]; |
| 510 | + } |
| 511 | + |
| 512 | + internal void set_Item<T>(int index, T value) |
| 513 | + { |
| 514 | + // ! Warning: "this" is an array, not an SZArrayHelper. See comments above |
| 515 | + // ! or you may introduce a security hole! |
| 516 | + T[] @this = Unsafe.As<T[]>(this); |
| 517 | + if ((uint)index >= (uint)@this.Length) |
| 518 | + { |
| 519 | +#pragma warning disable S3928 // Parameter names used into ArgumentException constructors should match an existing one |
| 520 | + throw new ArgumentOutOfRangeException(); |
| 521 | +#pragma warning restore S3928 // Parameter names used into ArgumentException constructors should match an existing one |
| 522 | + } |
| 523 | + |
| 524 | + @this[index] = value; |
| 525 | + } |
| 526 | + |
| 527 | + private void Add<T>(T _) |
| 528 | + { |
| 529 | + // Not meaningful for arrays. |
| 530 | + throw new NotSupportedException(); |
| 531 | + } |
| 532 | + |
| 533 | + private bool Contains<T>(T value) |
| 534 | + { |
| 535 | + // ! Warning: "this" is an array, not an SZArrayHelper. See comments above |
| 536 | + // ! or you may introduce a security hole! |
| 537 | + T[] @this = Unsafe.As<T[]>(this); |
| 538 | + return Array.IndexOf(@this, value, 0, @this.Length) >= 0; |
| 539 | + } |
| 540 | + |
| 541 | + private bool get_IsReadOnly<T>() |
| 542 | + { |
| 543 | + return true; |
| 544 | + } |
| 545 | + |
| 546 | + private void Clear<T>() |
| 547 | + { |
| 548 | + // ! Warning: "this" is an array, not an SZArrayHelper. See comments above |
| 549 | + // ! or you may introduce a security hole! |
| 550 | + |
| 551 | + throw new NotSupportedException(); |
| 552 | + } |
| 553 | + |
| 554 | + private int IndexOf<T>(T value) |
| 555 | + { |
| 556 | + // ! Warning: "this" is an array, not an SZArrayHelper. See comments above |
| 557 | + // ! or you may introduce a security hole! |
| 558 | + T[] @this = Unsafe.As<T[]>(this); |
| 559 | + return Array.IndexOf(@this, value, 0, @this.Length); |
| 560 | + } |
| 561 | + |
| 562 | + private void Insert<T>(int _, T _1) |
| 563 | + { |
| 564 | + // Not meaningful for arrays |
| 565 | + throw new NotSupportedException(); |
| 566 | + } |
| 567 | + |
| 568 | + private bool Remove<T>(T _) |
| 569 | + { |
| 570 | + // Not meaningful for arrays |
| 571 | + throw new NotSupportedException(); |
| 572 | + return default; |
| 573 | + } |
| 574 | + |
| 575 | + private void RemoveAt<T>(int _) |
| 576 | + { |
| 577 | + // Not meaningful for arrays |
| 578 | + throw new NotSupportedException(); |
| 579 | + } |
| 580 | + } |
| 581 | +#pragma warning restore CA1822 |
| 582 | + |
| 583 | +#endif |
432 | 584 | } |
433 | 585 | } |
0 commit comments