diff --git a/Build/N20/FontAtlas/FontAtlas.csproj b/Build/N20/FontAtlas/FontAtlas.csproj
deleted file mode 100644
index 9ec8f2d6..00000000
--- a/Build/N20/FontAtlas/FontAtlas.csproj
+++ /dev/null
@@ -1,59 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {B2667A10-2969-493F-8E7B-23F21CBFB886}
- Library
- Properties
- FontAtlas
- FontAtlas
- v2.0
- 512
-
-
- true
- full
- false
- bin\Debug\
- TRACE;DEBUG;NET20
- prompt
- 4
- true
-
-
- pdbonly
- true
- bin\Release\
- TRACE;NET20
- prompt
- 4
- true
-
-
-
-
-
-
-
-
-
- {fb5f78f5-c921-405d-8f21-42f7c15c2ad9}
- PixelFarm.MiniAgg.One
-
-
- {c6807d05-09be-4313-9f8b-bd2d51c55819}
- Typography.GlyphLayout
-
-
- {f7d71e61-9342-4dd7-9afd-69045f2ec98b}
- Typography.OpenFont
-
-
- {bc10cc51-a795-40d0-96f0-f87585d59d02}
- Typography.TextBreak
-
-
-
-
\ No newline at end of file
diff --git a/Build/N20/FontAtlas/Properties/AssemblyInfo.cs b/Build/N20/FontAtlas/Properties/AssemblyInfo.cs
deleted file mode 100644
index 73f45f1e..00000000
--- a/Build/N20/FontAtlas/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("FontAtlas")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("FontAtlas")]
-[assembly: AssemblyCopyright("Copyright © 2018")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("b2667a10-2969-493f-8e7b-23f21cbfb886")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Build/N20/Typography.Contours/Properties/AssemblyInfo.cs b/Build/N20/Typography.Contours/Properties/AssemblyInfo.cs
deleted file mode 100644
index 82860c2d..00000000
--- a/Build/N20/Typography.Contours/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("Typography.Contours")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("Typography.Contours")]
-[assembly: AssemblyCopyright("Copyright © 2018")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("b999f927-08c5-4328-b07e-69acc1392da4")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Build/N20/Typography.Contours/Typography.Contours.csproj b/Build/N20/Typography.Contours/Typography.Contours.csproj
deleted file mode 100644
index 94363907..00000000
--- a/Build/N20/Typography.Contours/Typography.Contours.csproj
+++ /dev/null
@@ -1,56 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {B999F927-08C5-4328-B07E-69ACC1392DA4}
- Library
- Properties
- Typography.Contours
- Typography.Contours
- v2.0
- 512
-
-
- true
- full
- false
- bin\Debug\
- TRACE;DEBUG;NET20
- prompt
- 4
- true
-
-
- pdbonly
- true
- bin\Release\
- TRACE;NET20
- prompt
- 4
- true
-
-
-
-
-
-
-
-
-
- {c5e5802d-6a45-4fe9-bae7-5f0ae91d72c1}
- BackEnd.Triangulation
-
-
- {c6807d05-09be-4313-9f8b-bd2d51c55819}
- Typography.GlyphLayout
-
-
- {f7d71e61-9342-4dd7-9afd-69045f2ec98b}
- Typography.OpenFont
-
-
-
-
-
\ No newline at end of file
diff --git a/Build/N20/Typography.GlyphLayout/Properties/AssemblyInfo.cs b/Build/N20/Typography.GlyphLayout/Properties/AssemblyInfo.cs
deleted file mode 100644
index 2326984f..00000000
--- a/Build/N20/Typography.GlyphLayout/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("PixelFarm.GlyphLayout")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("Microsoft")]
-[assembly: AssemblyProduct("PixelFarm.GlyphLayout")]
-[assembly: AssemblyCopyright("Copyright © Microsoft 2017")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("c6807d05-09be-4313-9f8b-bd2d51c55819")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Build/N20/Typography.GlyphLayout/Typography.GlyphLayout.csproj b/Build/N20/Typography.GlyphLayout/Typography.GlyphLayout.csproj
deleted file mode 100644
index f3d083e6..00000000
--- a/Build/N20/Typography.GlyphLayout/Typography.GlyphLayout.csproj
+++ /dev/null
@@ -1,50 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {C6807D05-09BE-4313-9F8B-BD2D51C55819}
- Library
- Typography.GlyphLayout
- Typography.GlyphLayout
- v2.0
- 512
-
-
- AnyCPU
- true
- full
- false
- bin\Debug\
- TRACE;DEBUG;NET20
- prompt
- 4
-
-
- AnyCPU
- pdbonly
- true
- bin\Release\
- TRACE;NET20
- prompt
- 4
-
-
-
-
-
-
-
-
-
-
-
-
- {f7d71e61-9342-4dd7-9afd-69045f2ec98b}
- Typography.OpenFont
-
-
-
-
-
\ No newline at end of file
diff --git a/Build/N20/Typography.MsdfGen/Properties/AssemblyInfo.cs b/Build/N20/Typography.MsdfGen/Properties/AssemblyInfo.cs
deleted file mode 100644
index 2a7225ba..00000000
--- a/Build/N20/Typography.MsdfGen/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("Typography.MsdfGen")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("Typography.MsdfGen")]
-[assembly: AssemblyCopyright("Copyright © 2018")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("9a3b8b84-56be-4aa1-8d90-1b3b3fef1f71")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Build/N20/Typography.MsdfGen/Typography.MsdfGen.csproj b/Build/N20/Typography.MsdfGen/Typography.MsdfGen.csproj
deleted file mode 100644
index a2868d01..00000000
--- a/Build/N20/Typography.MsdfGen/Typography.MsdfGen.csproj
+++ /dev/null
@@ -1,57 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {9A3B8B84-56BE-4AA1-8D90-1B3B3FEF1F71}
- Library
- Properties
- Typography.MsdfGen
- Typography.MsdfGen
- v2.0
- 512
-
-
- true
- full
- false
- bin\Debug\
- TRACE;DEBUG;NET20
- prompt
- 4
-
-
- pdbonly
- true
- bin\Release\
- TRACE;NET20
- prompt
- 4
-
-
-
- BasicElements.cs
-
-
- EdgeColor.cs
-
-
- EdgeColoring.cs
-
-
- EdgeSegment.cs
-
-
- EquationSolver.cs
-
-
- MsdfGen.cs
-
-
- SignedDistance.cs
-
-
-
-
-
\ No newline at end of file
diff --git a/Build/N20/Typography.OpenFont/Properties/AssemblyInfo.cs b/Build/N20/Typography.OpenFont/Properties/AssemblyInfo.cs
deleted file mode 100644
index 551fe386..00000000
--- a/Build/N20/Typography.OpenFont/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("Typography.OpenFont")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("Microsoft")]
-[assembly: AssemblyProduct("Typography.OpenFont")]
-[assembly: AssemblyCopyright("Copyright © Microsoft 2017")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("f7d71e61-9342-4dd7-9afd-69045f2ec98b")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Build/N20/Typography.OpenFont/Typography.OpenFont.csproj b/Build/N20/Typography.OpenFont/Typography.OpenFont.csproj
deleted file mode 100644
index 0e33626f..00000000
--- a/Build/N20/Typography.OpenFont/Typography.OpenFont.csproj
+++ /dev/null
@@ -1,44 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {F7D71E61-9342-4DD7-9AFD-69045F2EC98B}
- Library
- Properties
- Typography.OpenFont
- Typography.OpenFont
- v2.0
- 512
-
-
- true
- full
- false
- bin\Debug\
- TRACE;DEBUG;NET20
- prompt
- 4
- true
-
-
- pdbonly
- true
- bin\Release\
- TRACE;NET20
- prompt
- 4
- true
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Build/N20/Typography.TextBreak/ExtensionAttribute.cs b/Build/N20/Typography.TextBreak/ExtensionAttribute.cs
deleted file mode 100644
index b460eeca..00000000
--- a/Build/N20/Typography.TextBreak/ExtensionAttribute.cs
+++ /dev/null
@@ -1,4 +0,0 @@
-namespace System.Runtime.CompilerServices
-{
- public partial class ExtensionAttribute : Attribute { }
-}
\ No newline at end of file
diff --git a/Build/N20/Typography.TextBreak/Properties/AssemblyInfo.cs b/Build/N20/Typography.TextBreak/Properties/AssemblyInfo.cs
deleted file mode 100644
index 1a7f3f24..00000000
--- a/Build/N20/Typography.TextBreak/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("Typography.TextBreak")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("Typography.TextBreak")]
-[assembly: AssemblyCopyright("Copyright © 2018")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("bc10cc51-a795-40d0-96f0-f87585d59d02")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Build/N20/Typography.TextBreak/Typography.TextBreak.csproj b/Build/N20/Typography.TextBreak/Typography.TextBreak.csproj
deleted file mode 100644
index a07808cb..00000000
--- a/Build/N20/Typography.TextBreak/Typography.TextBreak.csproj
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {BC10CC51-A795-40D0-96F0-F87585D59D02}
- Library
- Properties
- Typography.TextBreak
- Typography.TextBreak
- v2.0
- 512
-
-
- true
- full
- false
- bin\Debug\
- TRACE;DEBUG;NET20
- prompt
- 4
-
-
- pdbonly
- true
- bin\Release\
- TRACE;NET20
- prompt
- 4
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Build/N20/Typography.TextFlow/Properties/AssemblyInfo.cs b/Build/N20/Typography.TextFlow/Properties/AssemblyInfo.cs
deleted file mode 100644
index b33a54de..00000000
--- a/Build/N20/Typography.TextFlow/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("Typography.TextFlow")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("Typography.TextFlow")]
-[assembly: AssemblyCopyright("Copyright © 2018")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("333f3209-8da9-4d33-a560-299ed4c6dfa5")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Build/N20/Typography.TextFlow/Typography.TextFlow.csproj b/Build/N20/Typography.TextFlow/Typography.TextFlow.csproj
deleted file mode 100644
index e1a3326c..00000000
--- a/Build/N20/Typography.TextFlow/Typography.TextFlow.csproj
+++ /dev/null
@@ -1,50 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {333F3209-8DA9-4D33-A560-299ED4C6DFA5}
- Library
- Properties
- Typography.TextFlow
- Typography.TextFlow
- v2.0
- 512
-
-
- true
- full
- false
- bin\Debug\
- TRACE;DEBUG;NET20
- prompt
- 4
-
-
- pdbonly
- true
- bin\Release\
- TRACE;NET20
- prompt
- 4
-
-
-
-
-
-
-
-
-
- {c6807d05-09be-4313-9f8b-bd2d51c55819}
- Typography.GlyphLayout
-
-
- {f7d71e61-9342-4dd7-9afd-69045f2ec98b}
- Typography.OpenFont
-
-
-
-
-
\ No newline at end of file
diff --git a/Build/N20/Typography.TextServices/Properties/AssemblyInfo.cs b/Build/N20/Typography.TextServices/Properties/AssemblyInfo.cs
deleted file mode 100644
index 1be60487..00000000
--- a/Build/N20/Typography.TextServices/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("Typography.TextServices")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("Typography.TextServices")]
-[assembly: AssemblyCopyright("Copyright © 2018")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("6b0e034b-0ebd-4907-ad7f-437de66d78d4")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Build/N20/Typography.TextServices/Typography.TextServices.csproj b/Build/N20/Typography.TextServices/Typography.TextServices.csproj
deleted file mode 100644
index e5c23520..00000000
--- a/Build/N20/Typography.TextServices/Typography.TextServices.csproj
+++ /dev/null
@@ -1,52 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {6B0E034B-0EBD-4907-AD7F-437DE66D78D4}
- Library
- Properties
- Typography.TextServices
- Typography.TextServices
- v2.0
- 512
-
-
- true
- full
- false
- bin\Debug\
- TRACE;DEBUG;NET20
- prompt
- 4
-
-
- pdbonly
- true
- bin\Release\
- TRACE;NET20
- prompt
- 4
-
-
-
-
-
-
-
-
-
- {c6807d05-09be-4313-9f8b-bd2d51c55819}
- Typography.GlyphLayout
-
-
- {f7d71e61-9342-4dd7-9afd-69045f2ec98b}
- Typography.OpenFont
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Build/N20/Unpack/Unpack.csproj b/Build/N20/Unpack/Unpack.csproj
deleted file mode 100644
index 4cf0da83..00000000
--- a/Build/N20/Unpack/Unpack.csproj
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {901A60ED-BAEF-45F6-8919-6E07EE6BAD8D}
- Library
- Properties
- Unpack
- Unpack
- v2.0
- 512
- true
-
-
- true
- full
- false
- bin\Debug\
- TRACE;DEBUG;NET20
- prompt
- 4
- true
-
-
- pdbonly
- true
- bin\Release\
- TRACE;NET20
- prompt
- 4
- true
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Build/N20/Typography.OpenFont/ExtensionAttribute.cs b/Build/NET20/ExtensionAttribute.cs
similarity index 100%
rename from Build/N20/Typography.OpenFont/ExtensionAttribute.cs
rename to Build/NET20/ExtensionAttribute.cs
diff --git a/PixelFarm/PixelFarm.Painter/0_Base/ForNet20.cs b/Build/NET20/ForNet20.cs
similarity index 96%
rename from PixelFarm/PixelFarm.Painter/0_Base/ForNet20.cs
rename to Build/NET20/ForNet20.cs
index d7cea46b..6a72ef72 100644
--- a/PixelFarm/PixelFarm.Painter/0_Base/ForNet20.cs
+++ b/Build/NET20/ForNet20.cs
@@ -1,12 +1,10 @@
-
-//for .NET 2.0
+//for .NET 2.0
namespace System
{
//public delegate R Func();
//public delegate R Func(T t1);
//public delegate R Func(T1 t1, T2 t2);
//public delegate R Func(T1 t1, T2 t2, T3 t3);
-#if !NETSTANDARD
public delegate void Action(T1 arg1, T2 arg2);
public delegate void Action(T1 arg1, T2 arg2, T3 arg3);
public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
@@ -24,7 +22,6 @@ namespace System
public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6);
public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7);
public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8);
-#endif
}
namespace System.Runtime.InteropServices
@@ -43,7 +40,7 @@ public partial class ExtensionAttribute : Attribute { }
namespace System.Collections.Generic
{
- public class HashSet : IEnumerable, ICollection
+ public class HashSet : IEnumerable, ICollection where T : notnull
{
//for .NET 2.0
Dictionary _dic = new Dictionary();
@@ -173,9 +170,9 @@ public static System.Collections.Generic.Dictionary ToDictionary
}
public static bool Contains(this T[] arr, T elem)
{
- for (int i = 0; i < arr.Length; ++i)
+ foreach (T v in arr)
{
- if (arr[i].Equals(elem))
+ if (v == null && elem == null || v != null && v.Equals(elem))
{
return true;
}
@@ -183,11 +180,11 @@ public static bool Contains(this T[] arr, T elem)
return false;
}
- public static bool Contains(this IEnumerable list, T value)
+ public static bool Contains(this IEnumerable list, T elem)
{
- foreach (T elem in list)
+ foreach (T v in list)
{
- if (elem.Equals(value))
+ if (v == null && elem == null || v != null && v.Equals(elem))
{
return true;
}
@@ -284,6 +281,7 @@ public static int Max(this IEnumerable list, Func evalFunc)
}
return max;
}
+ [return: System.Diagnostics.CodeAnalysis.MaybeNull]
public static T ElementAt(this IEnumerable list, int index)
{
if (list is T[] arr)
@@ -406,6 +404,7 @@ public static bool Any(this IEnumerable list, Func predicate)
}
return false;
}
+ [return: System.Diagnostics.CodeAnalysis.MaybeNull]
public static T FirstOrDefault(this IEnumerable list, Func predicate)
{
foreach (T t in list)
@@ -417,6 +416,7 @@ public static T FirstOrDefault(this IEnumerable list, Func predic
}
return default(T);
}
+ [return: System.Diagnostics.CodeAnalysis.MaybeNull]
public static T First(this T[] arr, Func predicate)
{
for (int i = 0; i < arr.Length; ++i)
@@ -432,6 +432,7 @@ public static T Last(this T[] arr)
{
return arr[arr.Length - 1];
}
+ [return: System.Diagnostics.CodeAnalysis.MaybeNull]
public static T First(this IEnumerable list, Func predicate)
{
foreach (T t in list)
@@ -443,6 +444,7 @@ public static T First(this IEnumerable list, Func predicate)
}
return default(T);
}
+ [return: System.Diagnostics.CodeAnalysis.MaybeNull]
public static T First(this IEnumerable list)
{
@@ -491,6 +493,7 @@ public static T First(this IEnumerable list)
}
}
+ [return: System.Diagnostics.CodeAnalysis.MaybeNull]
public static T Last(this IEnumerable list)
{
if (list is T[] arr)
@@ -537,6 +540,7 @@ public static T Last(this IEnumerable list)
return lastOne;
}
}
+ [return: System.Diagnostics.CodeAnalysis.MaybeNull]
public static T LastOrDefault(this IEnumerable list)
{
if (list is T[] arr)
@@ -691,6 +695,7 @@ public static T[] ToArray(IEnumerable list)
{
return list.ToArray();
}
+ [return: System.Diagnostics.CodeAnalysis.MaybeNull]
public static T ElementAt(IEnumerable list, int index)
{
return list.ElementAt(index);
@@ -719,5 +724,4 @@ public static IEnumerable Where(IEnumerable list, Func validat
}
-}
-
+}
\ No newline at end of file
diff --git a/Build/NET20/HashCode.cs b/Build/NET20/HashCode.cs
new file mode 100644
index 00000000..76a8b0f2
--- /dev/null
+++ b/Build/NET20/HashCode.cs
@@ -0,0 +1,462 @@
+// https://github.com/dotnet/runtime/blob/master/src/libraries/System.Private.CoreLib/src/System/HashCode.cs
+
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*
+
+The xxHash32 implementation is based on the code published by Yann Collet:
+https://raw.githubusercontent.com/Cyan4973/xxHash/5c174cfa4e45a42f94082dc0d4539b39696afea1/xxhash.c
+
+ xxHash - Fast Hash algorithm
+ Copyright (C) 2012-2016, Yann Collet
+
+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with the
+ distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ You can contact the author at :
+ - xxHash homepage: http://www.xxhash.com
+ - xxHash source repository : https://github.com/Cyan4973/xxHash
+
+*/
+
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Numerics;
+using System.Runtime.CompilerServices;
+
+namespace System
+{
+ // xxHash32 is used for the hash code.
+ // https://github.com/Cyan4973/xxHash
+
+ public struct HashCode
+ {
+ private static readonly uint s_seed = GenerateGlobalSeed();
+
+ private const uint Prime1 = 2654435761U;
+ private const uint Prime2 = 2246822519U;
+ private const uint Prime3 = 3266489917U;
+ private const uint Prime4 = 668265263U;
+ private const uint Prime5 = 374761393U;
+
+ private uint _v1, _v2, _v3, _v4;
+ private uint _queue1, _queue2, _queue3;
+ private uint _length;
+
+ private static uint GenerateGlobalSeed()
+ {
+ return (uint)new Random().Next();
+ }
+
+ public static int Combine(T1 value1)
+ {
+ // Provide a way of diffusing bits from something with a limited
+ // input hash space. For example, many enums only have a few
+ // possible hashes, only using the bottom few bits of the code. Some
+ // collections are built on the assumption that hashes are spread
+ // over a larger space, so diffusing the bits may help the
+ // collection work more efficiently.
+
+ uint hc1 = (uint)(value1?.GetHashCode() ?? 0);
+
+ uint hash = MixEmptyState();
+ hash += 4;
+
+ hash = QueueRound(hash, hc1);
+
+ hash = MixFinal(hash);
+ return (int)hash;
+ }
+
+ public static int Combine(T1 value1, T2 value2)
+ {
+ uint hc1 = (uint)(value1?.GetHashCode() ?? 0);
+ uint hc2 = (uint)(value2?.GetHashCode() ?? 0);
+
+ uint hash = MixEmptyState();
+ hash += 8;
+
+ hash = QueueRound(hash, hc1);
+ hash = QueueRound(hash, hc2);
+
+ hash = MixFinal(hash);
+ return (int)hash;
+ }
+
+ public static int Combine(T1 value1, T2 value2, T3 value3)
+ {
+ uint hc1 = (uint)(value1?.GetHashCode() ?? 0);
+ uint hc2 = (uint)(value2?.GetHashCode() ?? 0);
+ uint hc3 = (uint)(value3?.GetHashCode() ?? 0);
+
+ uint hash = MixEmptyState();
+ hash += 12;
+
+ hash = QueueRound(hash, hc1);
+ hash = QueueRound(hash, hc2);
+ hash = QueueRound(hash, hc3);
+
+ hash = MixFinal(hash);
+ return (int)hash;
+ }
+
+ public static int Combine(T1 value1, T2 value2, T3 value3, T4 value4)
+ {
+ uint hc1 = (uint)(value1?.GetHashCode() ?? 0);
+ uint hc2 = (uint)(value2?.GetHashCode() ?? 0);
+ uint hc3 = (uint)(value3?.GetHashCode() ?? 0);
+ uint hc4 = (uint)(value4?.GetHashCode() ?? 0);
+
+ Initialize(out uint v1, out uint v2, out uint v3, out uint v4);
+
+ v1 = Round(v1, hc1);
+ v2 = Round(v2, hc2);
+ v3 = Round(v3, hc3);
+ v4 = Round(v4, hc4);
+
+ uint hash = MixState(v1, v2, v3, v4);
+ hash += 16;
+
+ hash = MixFinal(hash);
+ return (int)hash;
+ }
+
+ public static int Combine(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5)
+ {
+ uint hc1 = (uint)(value1?.GetHashCode() ?? 0);
+ uint hc2 = (uint)(value2?.GetHashCode() ?? 0);
+ uint hc3 = (uint)(value3?.GetHashCode() ?? 0);
+ uint hc4 = (uint)(value4?.GetHashCode() ?? 0);
+ uint hc5 = (uint)(value5?.GetHashCode() ?? 0);
+
+ Initialize(out uint v1, out uint v2, out uint v3, out uint v4);
+
+ v1 = Round(v1, hc1);
+ v2 = Round(v2, hc2);
+ v3 = Round(v3, hc3);
+ v4 = Round(v4, hc4);
+
+ uint hash = MixState(v1, v2, v3, v4);
+ hash += 20;
+
+ hash = QueueRound(hash, hc5);
+
+ hash = MixFinal(hash);
+ return (int)hash;
+ }
+
+ public static int Combine(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6)
+ {
+ uint hc1 = (uint)(value1?.GetHashCode() ?? 0);
+ uint hc2 = (uint)(value2?.GetHashCode() ?? 0);
+ uint hc3 = (uint)(value3?.GetHashCode() ?? 0);
+ uint hc4 = (uint)(value4?.GetHashCode() ?? 0);
+ uint hc5 = (uint)(value5?.GetHashCode() ?? 0);
+ uint hc6 = (uint)(value6?.GetHashCode() ?? 0);
+
+ Initialize(out uint v1, out uint v2, out uint v3, out uint v4);
+
+ v1 = Round(v1, hc1);
+ v2 = Round(v2, hc2);
+ v3 = Round(v3, hc3);
+ v4 = Round(v4, hc4);
+
+ uint hash = MixState(v1, v2, v3, v4);
+ hash += 24;
+
+ hash = QueueRound(hash, hc5);
+ hash = QueueRound(hash, hc6);
+
+ hash = MixFinal(hash);
+ return (int)hash;
+ }
+
+ public static int Combine(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7)
+ {
+ uint hc1 = (uint)(value1?.GetHashCode() ?? 0);
+ uint hc2 = (uint)(value2?.GetHashCode() ?? 0);
+ uint hc3 = (uint)(value3?.GetHashCode() ?? 0);
+ uint hc4 = (uint)(value4?.GetHashCode() ?? 0);
+ uint hc5 = (uint)(value5?.GetHashCode() ?? 0);
+ uint hc6 = (uint)(value6?.GetHashCode() ?? 0);
+ uint hc7 = (uint)(value7?.GetHashCode() ?? 0);
+
+ Initialize(out uint v1, out uint v2, out uint v3, out uint v4);
+
+ v1 = Round(v1, hc1);
+ v2 = Round(v2, hc2);
+ v3 = Round(v3, hc3);
+ v4 = Round(v4, hc4);
+
+ uint hash = MixState(v1, v2, v3, v4);
+ hash += 28;
+
+ hash = QueueRound(hash, hc5);
+ hash = QueueRound(hash, hc6);
+ hash = QueueRound(hash, hc7);
+
+ hash = MixFinal(hash);
+ return (int)hash;
+ }
+
+ public static int Combine(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7, T8 value8)
+ {
+ uint hc1 = (uint)(value1?.GetHashCode() ?? 0);
+ uint hc2 = (uint)(value2?.GetHashCode() ?? 0);
+ uint hc3 = (uint)(value3?.GetHashCode() ?? 0);
+ uint hc4 = (uint)(value4?.GetHashCode() ?? 0);
+ uint hc5 = (uint)(value5?.GetHashCode() ?? 0);
+ uint hc6 = (uint)(value6?.GetHashCode() ?? 0);
+ uint hc7 = (uint)(value7?.GetHashCode() ?? 0);
+ uint hc8 = (uint)(value8?.GetHashCode() ?? 0);
+
+ Initialize(out uint v1, out uint v2, out uint v3, out uint v4);
+
+ v1 = Round(v1, hc1);
+ v2 = Round(v2, hc2);
+ v3 = Round(v3, hc3);
+ v4 = Round(v4, hc4);
+
+ v1 = Round(v1, hc5);
+ v2 = Round(v2, hc6);
+ v3 = Round(v3, hc7);
+ v4 = Round(v4, hc8);
+
+ uint hash = MixState(v1, v2, v3, v4);
+ hash += 32;
+
+ hash = MixFinal(hash);
+ return (int)hash;
+ }
+
+ private static void Initialize(out uint v1, out uint v2, out uint v3, out uint v4)
+ {
+ v1 = s_seed + Prime1 + Prime2;
+ v2 = s_seed + Prime2;
+ v3 = s_seed;
+ v4 = s_seed - Prime1;
+ }
+
+ private static uint Round(uint hash, uint input)
+ {
+ return RotateLeft(hash + input * Prime2, 13) * Prime1;
+ }
+
+ private static uint QueueRound(uint hash, uint queuedValue)
+ {
+ return RotateLeft(hash + queuedValue * Prime3, 17) * Prime4;
+ }
+
+ private static uint MixState(uint v1, uint v2, uint v3, uint v4)
+ {
+ return RotateLeft(v1, 1) + RotateLeft(v2, 7) + RotateLeft(v3, 12) + RotateLeft(v4, 18);
+ }
+
+ private static uint MixEmptyState()
+ {
+ return s_seed + Prime5;
+ }
+
+ private static uint MixFinal(uint hash)
+ {
+ hash ^= hash >> 15;
+ hash *= Prime2;
+ hash ^= hash >> 13;
+ hash *= Prime3;
+ hash ^= hash >> 16;
+ return hash;
+ }
+
+ public void Add(T value)
+ {
+ Add(value?.GetHashCode() ?? 0);
+ }
+
+ public void Add(T value, IEqualityComparer? comparer)
+ {
+ Add(value is null ? 0 : (comparer?.GetHashCode(value) ?? value.GetHashCode()));
+ }
+
+ private void Add(int value)
+ {
+ // The original xxHash works as follows:
+ // 0. Initialize immediately. We can't do this in a struct (no
+ // default ctor).
+ // 1. Accumulate blocks of length 16 (4 uints) into 4 accumulators.
+ // 2. Accumulate remaining blocks of length 4 (1 uint) into the
+ // hash.
+ // 3. Accumulate remaining blocks of length 1 into the hash.
+
+ // There is no need for #3 as this type only accepts ints. _queue1,
+ // _queue2 and _queue3 are basically a buffer so that when
+ // ToHashCode is called we can execute #2 correctly.
+
+ // We need to initialize the xxHash32 state (_v1 to _v4) lazily (see
+ // #0) nd the last place that can be done if you look at the
+ // original code is just before the first block of 16 bytes is mixed
+ // in. The xxHash32 state is never used for streams containing fewer
+ // than 16 bytes.
+
+ // To see what's really going on here, have a look at the Combine
+ // methods.
+
+ uint val = (uint)value;
+
+ // Storing the value of _length locally shaves of quite a few bytes
+ // in the resulting machine code.
+ uint previousLength = _length++;
+ uint position = previousLength % 4;
+
+ // Switch can't be inlined.
+
+ if (position == 0)
+ _queue1 = val;
+ else if (position == 1)
+ _queue2 = val;
+ else if (position == 2)
+ _queue3 = val;
+ else // position == 3
+ {
+ if (previousLength == 3)
+ Initialize(out _v1, out _v2, out _v3, out _v4);
+
+ _v1 = Round(_v1, _queue1);
+ _v2 = Round(_v2, _queue2);
+ _v3 = Round(_v3, _queue3);
+ _v4 = Round(_v4, val);
+ }
+ }
+
+ public int ToHashCode()
+ {
+ // Storing the value of _length locally shaves of quite a few bytes
+ // in the resulting machine code.
+ uint length = _length;
+
+ // position refers to the *next* queue position in this method, so
+ // position == 1 means that _queue1 is populated; _queue2 would have
+ // been populated on the next call to Add.
+ uint position = length % 4;
+
+ // If the length is less than 4, _v1 to _v4 don't contain anything
+ // yet. xxHash32 treats this differently.
+
+ uint hash = length < 4 ? MixEmptyState() : MixState(_v1, _v2, _v3, _v4);
+
+ // _length is incremented once per Add(Int32) and is therefore 4
+ // times too small (xxHash length is in bytes, not ints).
+
+ hash += length * 4;
+
+ // Mix what remains in the queue
+
+ // Switch can't be inlined right now, so use as few branches as
+ // possible by manually excluding impossible scenarios (position > 1
+ // is always false if position is not > 0).
+ if (position > 0)
+ {
+ hash = QueueRound(hash, _queue1);
+ if (position > 1)
+ {
+ hash = QueueRound(hash, _queue2);
+ if (position > 2)
+ hash = QueueRound(hash, _queue3);
+ }
+ }
+
+ hash = MixFinal(hash);
+ return (int)hash;
+ }
+
+#pragma warning disable 0809
+ // Obsolete member 'memberA' overrides non-obsolete member 'memberB'.
+ // Disallowing GetHashCode and Equals is by design
+
+ // * We decided to not override GetHashCode() to produce the hash code
+ // as this would be weird, both naming-wise as well as from a
+ // behavioral standpoint (GetHashCode() should return the object's
+ // hash code, not the one being computed).
+
+ // * Even though ToHashCode() can be called safely multiple times on
+ // this implementation, it is not part of the contract. If the
+ // implementation has to change in the future we don't want to worry
+ // about people who might have incorrectly used this type.
+
+ [Obsolete("HashCode is a mutable struct and should not be compared with other HashCodes. Use ToHashCode to retrieve the computed hash code.", error: true)]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public override int GetHashCode() => throw new NotSupportedException("HashCode is a mutable struct and should not be compared with other HashCodes. Use ToHashCode to retrieve the computed hash code.");
+
+ [Obsolete("HashCode is a mutable struct and should not be compared with other HashCodes.", error: true)]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public override bool Equals(object? obj) => throw new NotSupportedException("HashCode is a mutable struct and should not be compared with other HashCodes.");
+#pragma warning restore 0809
+
+ ///
+ /// Rotates the specified value left by the specified number of bits.
+ /// Similar in behavior to the x86 instruction ROL.
+ ///
+ /// The value to rotate.
+ /// The number of bits to rotate by.
+ /// Any value outside the range [0..31] is treated as congruent mod 32.
+ /// The rotated value.
+ private static uint RotateLeft(uint value, int offset)
+ => (value << offset) | (value >> (32 - offset));
+
+ ///
+ /// Rotates the specified value left by the specified number of bits.
+ /// Similar in behavior to the x86 instruction ROL.
+ ///
+ /// The value to rotate.
+ /// The number of bits to rotate by.
+ /// Any value outside the range [0..63] is treated as congruent mod 64.
+ /// The rotated value.
+ private static ulong RotateLeft(ulong value, int offset)
+ => (value << offset) | (value >> (64 - offset));
+
+ ///
+ /// Rotates the specified value right by the specified number of bits.
+ /// Similar in behavior to the x86 instruction ROR.
+ ///
+ /// The value to rotate.
+ /// The number of bits to rotate by.
+ /// Any value outside the range [0..31] is treated as congruent mod 32.
+ /// The rotated value.
+ private static uint RotateRight(uint value, int offset)
+ => (value >> offset) | (value << (32 - offset));
+
+ ///
+ /// Rotates the specified value right by the specified number of bits.
+ /// Similar in behavior to the x86 instruction ROR.
+ ///
+ /// The value to rotate.
+ /// The number of bits to rotate by.
+ /// Any value outside the range [0..63] is treated as congruent mod 64.
+ /// The rotated value.
+ private static ulong RotateRight(ulong value, int offset)
+ => (value >> offset) | (value << (64 - offset));
+ }
+}
\ No newline at end of file
diff --git a/Build/N20/Typography.OpenFont/System.Numerics.ForNet20.cs b/Build/NET20/System.Numerics.ForNet20.cs
similarity index 100%
rename from Build/N20/Typography.OpenFont/System.Numerics.ForNet20.cs
rename to Build/NET20/System.Numerics.ForNet20.cs
diff --git a/Build/NET20/TupleElementNames.cs b/Build/NET20/TupleElementNames.cs
new file mode 100644
index 00000000..541069b6
--- /dev/null
+++ b/Build/NET20/TupleElementNames.cs
@@ -0,0 +1,58 @@
+// https://github.com/dotnet/runtime/blob/master/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/TupleElementNamesAttribute.cs
+
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+
+namespace System.Runtime.CompilerServices
+{
+ ///
+ /// Indicates that the use of on a member is meant to be treated as a tuple with element names.
+ ///
+ [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Event)]
+ public sealed class TupleElementNamesAttribute : Attribute
+ {
+ private readonly string?[] _transformNames;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// Specifies, in a pre-order depth-first traversal of a type's
+ /// construction, which occurrences are
+ /// meant to carry element names.
+ ///
+ ///
+ /// This constructor is meant to be used on types that contain an
+ /// instantiation of that contains
+ /// element names. For instance, if C is a generic type with
+ /// two type parameters, then a use of the constructed type C{, might be intended to
+ /// treat the first type argument as a tuple with element names and the
+ /// second as a tuple without element names. In which case, the
+ /// appropriate attribute specification should use a
+ /// transformNames value of { "name1", "name2", null, null,
+ /// null }.
+ ///
+ public TupleElementNamesAttribute(string?[] transformNames)
+ {
+ if (transformNames == null)
+ {
+ throw new ArgumentNullException(nameof(transformNames));
+ }
+
+ _transformNames = transformNames;
+ }
+
+ ///
+ /// Specifies, in a pre-order depth-first traversal of a type's
+ /// construction, which elements are
+ /// meant to carry element names.
+ ///
+ public IList TransformNames => _transformNames;
+ }
+}
\ No newline at end of file
diff --git a/Build/NET20/ValueTuple.cs b/Build/NET20/ValueTuple.cs
new file mode 100644
index 00000000..81601112
--- /dev/null
+++ b/Build/NET20/ValueTuple.cs
@@ -0,0 +1,1691 @@
+// https://github.com/dotnet/runtime/blob/master/src/libraries/System.Private.CoreLib/src/System/ValueTuple.cs
+
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#pragma warning disable SA1141 // explicitly not using tuple syntax in tuple implementation
+
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+namespace System
+{
+ ///
+ /// Helper so we can call some tuple methods recursively without knowing the underlying types.
+ ///
+ internal interface IValueTupleInternal
+ {
+ int Length { get; }
+ int GetHashCode(IEqualityComparer comparer);
+ string ToStringEnd();
+ }
+
+ ///
+ /// The ValueTuple types (from arity 0 to 8) comprise the runtime implementation that underlies tuples in C# and struct tuples in F#.
+ /// Aside from created via language syntax, they are most easily created via the ValueTuple.Create factory methods.
+ /// The System.ValueTuple types differ from the System.Tuple types in that:
+ /// - they are structs rather than classes,
+ /// - they are mutable rather than readonly, and
+ /// - their members (such as Item1, Item2, etc) are fields rather than properties.
+ ///
+ [Serializable]
+ public struct ValueTuple
+ : IEquatable, IComparable, IComparable, IValueTupleInternal
+ {
+ ///
+ /// Returns a value that indicates whether the current instance is equal to a specified object.
+ ///
+ /// The object to compare with this instance.
+ /// if is a .
+ public override bool Equals(object? obj)
+ {
+ return obj is ValueTuple;
+ }
+
+ /// Returns a value indicating whether this instance is equal to a specified value.
+ /// An instance to compare to this instance.
+ /// true if has the same value as this instance; otherwise, false.
+ public bool Equals(ValueTuple other)
+ {
+ return true;
+ }
+
+ int IComparable.CompareTo(object? other)
+ {
+ if (other == null) return 1;
+
+ if (!(other is ValueTuple))
+ {
+ throw new ArgumentException("Object to compare is not a ValueTuple", nameof(other));
+ }
+
+ return 0;
+ }
+
+ /// Compares this instance to a specified instance and returns an indication of their relative values.
+ /// An instance to compare.
+ ///
+ /// A signed number indicating the relative values of this instance and .
+ /// Returns less than zero if this instance is less than , zero if this
+ /// instance is equal to , and greater than zero if this instance is greater
+ /// than .
+ ///
+ public int CompareTo(ValueTuple other)
+ {
+ return 0;
+ }
+
+ /// Returns the hash code for this instance.
+ /// A 32-bit signed integer hash code.
+ public override int GetHashCode()
+ {
+ return 0;
+ }
+
+ int IValueTupleInternal.Length => 0;
+ int IValueTupleInternal.GetHashCode(IEqualityComparer comparer)
+ {
+ return 0;
+ }
+
+ ///
+ /// Returns a string that represents the value of this instance.
+ ///
+ /// The string representation of this instance.
+ ///
+ /// The string returned by this method takes the form ().
+ ///
+ public override string ToString()
+ {
+ return "()";
+ }
+
+ string IValueTupleInternal.ToStringEnd()
+ {
+ return ")";
+ }
+
+ /// Creates a new struct 0-tuple.
+ /// A 0-tuple.
+ public static ValueTuple Create() =>
+ default;
+
+ /// Creates a new struct 1-tuple, or singleton.
+ /// The type of the first component of the tuple.
+ /// The value of the first component of the tuple.
+ /// A 1-tuple (singleton) whose value is (item1).
+ public static ValueTuple Create(T1 item1) =>
+ new ValueTuple(item1);
+
+ /// Creates a new struct 2-tuple, or pair.
+ /// The type of the first component of the tuple.
+ /// The type of the second component of the tuple.
+ /// The value of the first component of the tuple.
+ /// The value of the second component of the tuple.
+ /// A 2-tuple (pair) whose value is (item1, item2).
+ public static ValueTuple Create(T1 item1, T2 item2) =>
+ new ValueTuple(item1, item2);
+
+ /// Creates a new struct 3-tuple, or triple.
+ /// The type of the first component of the tuple.
+ /// The type of the second component of the tuple.
+ /// The type of the third component of the tuple.
+ /// The value of the first component of the tuple.
+ /// The value of the second component of the tuple.
+ /// The value of the third component of the tuple.
+ /// A 3-tuple (triple) whose value is (item1, item2, item3).
+ public static ValueTuple Create(T1 item1, T2 item2, T3 item3) =>
+ new ValueTuple(item1, item2, item3);
+
+ /// Creates a new struct 4-tuple, or quadruple.
+ /// The type of the first component of the tuple.
+ /// The type of the second component of the tuple.
+ /// The type of the third component of the tuple.
+ /// The type of the fourth component of the tuple.
+ /// The value of the first component of the tuple.
+ /// The value of the second component of the tuple.
+ /// The value of the third component of the tuple.
+ /// The value of the fourth component of the tuple.
+ /// A 4-tuple (quadruple) whose value is (item1, item2, item3, item4).
+ public static ValueTuple Create(T1 item1, T2 item2, T3 item3, T4 item4) =>
+ new ValueTuple(item1, item2, item3, item4);
+
+ /// Creates a new struct 5-tuple, or quintuple.
+ /// The type of the first component of the tuple.
+ /// The type of the second component of the tuple.
+ /// The type of the third component of the tuple.
+ /// The type of the fourth component of the tuple.
+ /// The type of the fifth component of the tuple.
+ /// The value of the first component of the tuple.
+ /// The value of the second component of the tuple.
+ /// The value of the third component of the tuple.
+ /// The value of the fourth component of the tuple.
+ /// The value of the fifth component of the tuple.
+ /// A 5-tuple (quintuple) whose value is (item1, item2, item3, item4, item5).
+ public static ValueTuple Create(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5) =>
+ new ValueTuple(item1, item2, item3, item4, item5);
+
+ /// Creates a new struct 6-tuple, or sextuple.
+ /// The type of the first component of the tuple.
+ /// The type of the second component of the tuple.
+ /// The type of the third component of the tuple.
+ /// The type of the fourth component of the tuple.
+ /// The type of the fifth component of the tuple.
+ /// The type of the sixth component of the tuple.
+ /// The value of the first component of the tuple.
+ /// The value of the second component of the tuple.
+ /// The value of the third component of the tuple.
+ /// The value of the fourth component of the tuple.
+ /// The value of the fifth component of the tuple.
+ /// The value of the sixth component of the tuple.
+ /// A 6-tuple (sextuple) whose value is (item1, item2, item3, item4, item5, item6).
+ public static ValueTuple Create(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6) =>
+ new ValueTuple(item1, item2, item3, item4, item5, item6);
+
+ /// Creates a new struct 7-tuple, or septuple.
+ /// The type of the first component of the tuple.
+ /// The type of the second component of the tuple.
+ /// The type of the third component of the tuple.
+ /// The type of the fourth component of the tuple.
+ /// The type of the fifth component of the tuple.
+ /// The type of the sixth component of the tuple.
+ /// The type of the seventh component of the tuple.
+ /// The value of the first component of the tuple.
+ /// The value of the second component of the tuple.
+ /// The value of the third component of the tuple.
+ /// The value of the fourth component of the tuple.
+ /// The value of the fifth component of the tuple.
+ /// The value of the sixth component of the tuple.
+ /// The value of the seventh component of the tuple.
+ /// A 7-tuple (septuple) whose value is (item1, item2, item3, item4, item5, item6, item7).
+ public static ValueTuple Create(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7) =>
+ new ValueTuple(item1, item2, item3, item4, item5, item6, item7);
+
+ /// Creates a new struct 8-tuple, or octuple.
+ /// The type of the first component of the tuple.
+ /// The type of the second component of the tuple.
+ /// The type of the third component of the tuple.
+ /// The type of the fourth component of the tuple.
+ /// The type of the fifth component of the tuple.
+ /// The type of the sixth component of the tuple.
+ /// The type of the seventh component of the tuple.
+ /// The type of the eighth component of the tuple.
+ /// The value of the first component of the tuple.
+ /// The value of the second component of the tuple.
+ /// The value of the third component of the tuple.
+ /// The value of the fourth component of the tuple.
+ /// The value of the fifth component of the tuple.
+ /// The value of the sixth component of the tuple.
+ /// The value of the seventh component of the tuple.
+ /// The value of the eighth component of the tuple.
+ /// An 8-tuple (octuple) whose value is (item1, item2, item3, item4, item5, item6, item7, item8).
+ public static ValueTuple> Create(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, T8 item8) =>
+ new ValueTuple>(item1, item2, item3, item4, item5, item6, item7, ValueTuple.Create(item8));
+ }
+
+ /// Represents a 1-tuple, or singleton, as a value type.
+ /// The type of the tuple's only component.
+ [Serializable]
+ public struct ValueTuple
+ : IEquatable>, IComparable, IComparable>, IValueTupleInternal
+ {
+ ///
+ /// The current instance's first component.
+ ///
+ public T1 Item1;
+
+ ///
+ /// Initializes a new instance of the value type.
+ ///
+ /// The value of the tuple's first component.
+ public ValueTuple(T1 item1)
+ {
+ Item1 = item1;
+ }
+
+ ///
+ /// Returns a value that indicates whether the current instance is equal to a specified object.
+ ///
+ /// The object to compare with this instance.
+ /// if the current instance is equal to the specified object; otherwise, .
+ ///
+ /// The parameter is considered to be equal to the current instance under the following conditions:
+ ///
+ /// - It is a value type.
+ /// - Its components are of the same types as those of the current instance.
+ /// - Its components are equal to those of the current instance. Equality is determined by the default object equality comparer for each component.
+ ///
+ ///
+ public override bool Equals(object? obj)
+ {
+ return obj is ValueTuple && Equals((ValueTuple)obj);
+ }
+
+ ///
+ /// Returns a value that indicates whether the current
+ /// instance is equal to a specified .
+ ///
+ /// The tuple to compare with this instance.
+ /// if the current instance is equal to the specified tuple; otherwise, .
+ ///
+ /// The parameter is considered to be equal to the current instance if each of its field
+ /// is equal to that of the current instance, using the default comparer for that field's type.
+ ///
+ public bool Equals(ValueTuple other)
+ {
+ return EqualityComparer.Default.Equals(Item1, other.Item1);
+ }
+
+ int IComparable.CompareTo(object? other)
+ {
+ if (other == null) return 1;
+
+ if (!(other is ValueTuple))
+ {
+ throw new ArgumentException("Object to compare is not a ValueTuple", nameof(other));
+ }
+
+ var objTuple = (ValueTuple)other;
+
+ return Comparer.Default.Compare(Item1, objTuple.Item1);
+ }
+
+ /// Compares this instance to a specified instance and returns an indication of their relative values.
+ /// An instance to compare.
+ ///
+ /// A signed number indicating the relative values of this instance and .
+ /// Returns less than zero if this instance is less than , zero if this
+ /// instance is equal to , and greater than zero if this instance is greater
+ /// than .
+ ///
+ public int CompareTo(ValueTuple other)
+ {
+ return Comparer.Default.Compare(Item1, other.Item1);
+ }
+
+ ///
+ /// Returns the hash code for the current instance.
+ ///
+ /// A 32-bit signed integer hash code.
+ public override int GetHashCode()
+ {
+ return Item1?.GetHashCode() ?? 0;
+ }
+
+ int IValueTupleInternal.Length => 1;
+ int IValueTupleInternal.GetHashCode(IEqualityComparer comparer)
+ {
+ return comparer.GetHashCode(Item1!);
+ }
+
+ ///
+ /// Returns a string that represents the value of this instance.
+ ///
+ /// The string representation of this instance.
+ ///
+ /// The string returned by this method takes the form (Item1),
+ /// where Item1 represents the value of . If the field is ,
+ /// it is represented as .
+ ///
+ public override string ToString()
+ {
+ return "(" + Item1?.ToString() + ")";
+ }
+
+ string IValueTupleInternal.ToStringEnd()
+ {
+ return Item1?.ToString() + ")";
+ }
+ }
+
+ ///
+ /// Represents a 2-tuple, or pair, as a value type.
+ ///
+ /// The type of the tuple's first component.
+ /// The type of the tuple's second component.
+ [Serializable]
+ [StructLayout(LayoutKind.Auto)]
+ public struct ValueTuple
+ : IEquatable>, IComparable, IComparable>, IValueTupleInternal
+ {
+ ///
+ /// The current instance's first component.
+ ///
+ public T1 Item1;
+
+ ///
+ /// The current instance's second component.
+ ///
+ public T2 Item2;
+
+ ///
+ /// Initializes a new instance of the value type.
+ ///
+ /// The value of the tuple's first component.
+ /// The value of the tuple's second component.
+ public ValueTuple(T1 item1, T2 item2)
+ {
+ Item1 = item1;
+ Item2 = item2;
+ }
+
+ ///
+ /// Returns a value that indicates whether the current instance is equal to a specified object.
+ ///
+ /// The object to compare with this instance.
+ /// if the current instance is equal to the specified object; otherwise, .
+ ///
+ ///
+ /// The parameter is considered to be equal to the current instance under the following conditions:
+ ///
+ /// - It is a value type.
+ /// - Its components are of the same types as those of the current instance.
+ /// - Its components are equal to those of the current instance. Equality is determined by the default object equality comparer for each component.
+ ///
+ ///
+ public override bool Equals(object? obj)
+ {
+ return obj is ValueTuple && Equals((ValueTuple)obj);
+ }
+
+ ///
+ /// Returns a value that indicates whether the current instance is equal to a specified .
+ ///
+ /// The tuple to compare with this instance.
+ /// if the current instance is equal to the specified tuple; otherwise, .
+ ///
+ /// The parameter is considered to be equal to the current instance if each of its fields
+ /// are equal to that of the current instance, using the default comparer for that field's type.
+ ///
+ public bool Equals(ValueTuple other)
+ {
+ return EqualityComparer.Default.Equals(Item1, other.Item1)
+ && EqualityComparer.Default.Equals(Item2, other.Item2);
+ }
+
+ int IComparable.CompareTo(object? other)
+ {
+ if (other == null) return 1;
+
+ if (!(other is ValueTuple))
+ {
+ throw new ArgumentException("Object to compare is not a ValueTuple", nameof(other));
+ }
+
+ return CompareTo((ValueTuple)other);
+ }
+
+ /// Compares this instance to a specified instance and returns an indication of their relative values.
+ /// An instance to compare.
+ ///
+ /// A signed number indicating the relative values of this instance and .
+ /// Returns less than zero if this instance is less than , zero if this
+ /// instance is equal to , and greater than zero if this instance is greater
+ /// than .
+ ///
+ public int CompareTo(ValueTuple other)
+ {
+ int c = Comparer.Default.Compare(Item1, other.Item1);
+ if (c != 0) return c;
+
+ return Comparer.Default.Compare(Item2, other.Item2);
+ }
+
+ ///
+ /// Returns the hash code for the current instance.
+ ///
+ /// A 32-bit signed integer hash code.
+ public override int GetHashCode()
+ {
+ return HashCode.Combine(Item1?.GetHashCode() ?? 0,
+ Item2?.GetHashCode() ?? 0);
+ }
+
+ private int GetHashCodeCore(IEqualityComparer comparer)
+ {
+ return HashCode.Combine(comparer.GetHashCode(Item1!),
+ comparer.GetHashCode(Item2!));
+ }
+
+ int IValueTupleInternal.Length => 1;
+ int IValueTupleInternal.GetHashCode(IEqualityComparer comparer)
+ {
+ return GetHashCodeCore(comparer);
+ }
+
+ ///
+ /// Returns a string that represents the value of this instance.
+ ///
+ /// The string representation of this instance.
+ ///
+ /// The string returned by this method takes the form (Item1, Item2),
+ /// where Item1 and Item2 represent the values of the
+ /// and fields. If either field value is ,
+ /// it is represented as .
+ ///
+ public override string ToString()
+ {
+ return "(" + Item1?.ToString() + ", " + Item2?.ToString() + ")";
+ }
+
+ string IValueTupleInternal.ToStringEnd()
+ {
+ return Item1?.ToString() + ", " + Item2?.ToString() + ")";
+ }
+ }
+
+ ///
+ /// Represents a 3-tuple, or triple, as a value type.
+ ///
+ /// The type of the tuple's first component.
+ /// The type of the tuple's second component.
+ /// The type of the tuple's third component.
+ [Serializable]
+ [StructLayout(LayoutKind.Auto)]
+ public struct ValueTuple
+ : IEquatable>, IComparable, IComparable>, IValueTupleInternal
+ {
+ ///
+ /// The current instance's first component.
+ ///
+ public T1 Item1;
+ ///
+ /// The current instance's second component.
+ ///
+ public T2 Item2;
+ ///
+ /// The current instance's third component.
+ ///
+ public T3 Item3;
+
+ ///
+ /// Initializes a new instance of the value type.
+ ///
+ /// The value of the tuple's first component.
+ /// The value of the tuple's second component.
+ /// The value of the tuple's third component.
+ public ValueTuple(T1 item1, T2 item2, T3 item3)
+ {
+ Item1 = item1;
+ Item2 = item2;
+ Item3 = item3;
+ }
+
+ ///
+ /// Returns a value that indicates whether the current instance is equal to a specified object.
+ ///
+ /// The object to compare with this instance.
+ /// if the current instance is equal to the specified object; otherwise, .
+ ///
+ /// The parameter is considered to be equal to the current instance under the following conditions:
+ ///
+ /// - It is a value type.
+ /// - Its components are of the same types as those of the current instance.
+ /// - Its components are equal to those of the current instance. Equality is determined by the default object equality comparer for each component.
+ ///
+ ///
+ public override bool Equals(object? obj)
+ {
+ return obj is ValueTuple && Equals((ValueTuple)obj);
+ }
+
+ ///
+ /// Returns a value that indicates whether the current
+ /// instance is equal to a specified .
+ ///
+ /// The tuple to compare with this instance.
+ /// if the current instance is equal to the specified tuple; otherwise, .
+ ///
+ /// The parameter is considered to be equal to the current instance if each of its fields
+ /// are equal to that of the current instance, using the default comparer for that field's type.
+ ///
+ public bool Equals(ValueTuple other)
+ {
+ return EqualityComparer.Default.Equals(Item1, other.Item1)
+ && EqualityComparer.Default.Equals(Item2, other.Item2)
+ && EqualityComparer.Default.Equals(Item3, other.Item3);
+ }
+
+ int IComparable.CompareTo(object? other)
+ {
+ if (other == null) return 1;
+
+ if (!(other is ValueTuple))
+ {
+ throw new ArgumentException("Object to compare is not a ValueTuple", nameof(other));
+ }
+
+ return CompareTo((ValueTuple)other);
+ }
+
+ /// Compares this instance to a specified instance and returns an indication of their relative values.
+ /// An instance to compare.
+ ///
+ /// A signed number indicating the relative values of this instance and .
+ /// Returns less than zero if this instance is less than , zero if this
+ /// instance is equal to , and greater than zero if this instance is greater
+ /// than .
+ ///
+ public int CompareTo(ValueTuple other)
+ {
+ int c = Comparer.Default.Compare(Item1, other.Item1);
+ if (c != 0) return c;
+
+ c = Comparer.Default.Compare(Item2, other.Item2);
+ if (c != 0) return c;
+
+ return Comparer.Default.Compare(Item3, other.Item3);
+ }
+
+ ///
+ /// Returns the hash code for the current instance.
+ ///
+ /// A 32-bit signed integer hash code.
+ public override int GetHashCode()
+ {
+ return HashCode.Combine(Item1?.GetHashCode() ?? 0,
+ Item2?.GetHashCode() ?? 0,
+ Item3?.GetHashCode() ?? 0);
+ }
+
+ private int GetHashCodeCore(IEqualityComparer comparer)
+ {
+ return HashCode.Combine(comparer.GetHashCode(Item1!),
+ comparer.GetHashCode(Item2!),
+ comparer.GetHashCode(Item3!));
+ }
+
+ int IValueTupleInternal.Length => 2;
+ int IValueTupleInternal.GetHashCode(IEqualityComparer comparer)
+ {
+ return GetHashCodeCore(comparer);
+ }
+
+ ///
+ /// Returns a string that represents the value of this instance.
+ ///
+ /// The string representation of this instance.
+ ///
+ /// The string returned by this method takes the form (Item1, Item2, Item3).
+ /// If any field value is , it is represented as .
+ ///
+ public override string ToString()
+ {
+ return "(" + Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ")";
+ }
+
+ string IValueTupleInternal.ToStringEnd()
+ {
+ return Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ")";
+ }
+ }
+
+ ///
+ /// Represents a 4-tuple, or quadruple, as a value type.
+ ///
+ /// The type of the tuple's first component.
+ /// The type of the tuple's second component.
+ /// The type of the tuple's third component.
+ /// The type of the tuple's fourth component.
+ [Serializable]
+ [StructLayout(LayoutKind.Auto)]
+ public struct ValueTuple
+ : IEquatable>, IComparable, IComparable>, IValueTupleInternal
+ {
+ ///
+ /// The current instance's first component.
+ ///
+ public T1 Item1;
+ ///
+ /// The current instance's second component.
+ ///
+ public T2 Item2;
+ ///
+ /// The current instance's third component.
+ ///
+ public T3 Item3;
+ ///
+ /// The current instance's fourth component.
+ ///
+ public T4 Item4;
+
+ ///
+ /// Initializes a new instance of the value type.
+ ///
+ /// The value of the tuple's first component.
+ /// The value of the tuple's second component.
+ /// The value of the tuple's third component.
+ /// The value of the tuple's fourth component.
+ public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4)
+ {
+ Item1 = item1;
+ Item2 = item2;
+ Item3 = item3;
+ Item4 = item4;
+ }
+
+ ///
+ /// Returns a value that indicates whether the current instance is equal to a specified object.
+ ///
+ /// The object to compare with this instance.
+ /// if the current instance is equal to the specified object; otherwise, .
+ ///
+ /// The parameter is considered to be equal to the current instance under the following conditions:
+ ///
+ /// - It is a value type.
+ /// - Its components are of the same types as those of the current instance.
+ /// - Its components are equal to those of the current instance. Equality is determined by the default object equality comparer for each component.
+ ///
+ ///
+ public override bool Equals(object? obj)
+ {
+ return obj is ValueTuple && Equals((ValueTuple)obj);
+ }
+
+ ///
+ /// Returns a value that indicates whether the current
+ /// instance is equal to a specified .
+ ///
+ /// The tuple to compare with this instance.
+ /// if the current instance is equal to the specified tuple; otherwise, .
+ ///
+ /// The parameter is considered to be equal to the current instance if each of its fields
+ /// are equal to that of the current instance, using the default comparer for that field's type.
+ ///
+ public bool Equals(ValueTuple other)
+ {
+ return EqualityComparer.Default.Equals(Item1, other.Item1)
+ && EqualityComparer.Default.Equals(Item2, other.Item2)
+ && EqualityComparer.Default.Equals(Item3, other.Item3)
+ && EqualityComparer.Default.Equals(Item4, other.Item4);
+ }
+
+ int IComparable.CompareTo(object? other)
+ {
+ if (other == null) return 1;
+
+ if (!(other is ValueTuple))
+ {
+ throw new ArgumentException("Object to compare is not a ValueTuple", nameof(other));
+ }
+
+ return CompareTo((ValueTuple)other);
+ }
+
+ /// Compares this instance to a specified instance and returns an indication of their relative values.
+ /// An instance to compare.
+ ///
+ /// A signed number indicating the relative values of this instance and .
+ /// Returns less than zero if this instance is less than , zero if this
+ /// instance is equal to , and greater than zero if this instance is greater
+ /// than .
+ ///
+ public int CompareTo(ValueTuple other)
+ {
+ int c = Comparer.Default.Compare(Item1, other.Item1);
+ if (c != 0) return c;
+
+ c = Comparer.Default.Compare(Item2, other.Item2);
+ if (c != 0) return c;
+
+ c = Comparer.Default.Compare(Item3, other.Item3);
+ if (c != 0) return c;
+
+ return Comparer.Default.Compare(Item4, other.Item4);
+ }
+
+ ///
+ /// Returns the hash code for the current instance.
+ ///
+ /// A 32-bit signed integer hash code.
+ public override int GetHashCode()
+ {
+ return HashCode.Combine(Item1?.GetHashCode() ?? 0,
+ Item2?.GetHashCode() ?? 0,
+ Item3?.GetHashCode() ?? 0,
+ Item4?.GetHashCode() ?? 0);
+ }
+
+ private int GetHashCodeCore(IEqualityComparer comparer)
+ {
+ return HashCode.Combine(comparer.GetHashCode(Item1!),
+ comparer.GetHashCode(Item2!),
+ comparer.GetHashCode(Item3!),
+ comparer.GetHashCode(Item4!));
+ }
+
+ int IValueTupleInternal.Length => 3;
+ int IValueTupleInternal.GetHashCode(IEqualityComparer comparer)
+ {
+ return GetHashCodeCore(comparer);
+ }
+
+ ///
+ /// Returns a string that represents the value of this instance.
+ ///
+ /// The string representation of this instance.
+ ///
+ /// The string returned by this method takes the form (Item1, Item2, Item3, Item4).
+ /// If any field value is , it is represented as .
+ ///
+ public override string ToString()
+ {
+ return "(" + Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ")";
+ }
+
+ string IValueTupleInternal.ToStringEnd()
+ {
+ return Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ")";
+ }
+ }
+
+ ///
+ /// Represents a 5-tuple, or quintuple, as a value type.
+ ///
+ /// The type of the tuple's first component.
+ /// The type of the tuple's second component.
+ /// The type of the tuple's third component.
+ /// The type of the tuple's fourth component.
+ /// The type of the tuple's fifth component.
+ [Serializable]
+ [StructLayout(LayoutKind.Auto)]
+ public struct ValueTuple
+ : IEquatable>, IComparable, IComparable>, IValueTupleInternal
+ {
+ ///
+ /// The current instance's first component.
+ ///
+ public T1 Item1;
+ ///
+ /// The current instance's second component.
+ ///
+ public T2 Item2;
+ ///
+ /// The current instance's third component.
+ ///
+ public T3 Item3;
+ ///
+ /// The current instance's fourth component.
+ ///
+ public T4 Item4;
+ ///
+ /// The current instance's fifth component.
+ ///
+ public T5 Item5;
+
+ ///
+ /// Initializes a new instance of the value type.
+ ///
+ /// The value of the tuple's first component.
+ /// The value of the tuple's second component.
+ /// The value of the tuple's third component.
+ /// The value of the tuple's fourth component.
+ /// The value of the tuple's fifth component.
+ public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5)
+ {
+ Item1 = item1;
+ Item2 = item2;
+ Item3 = item3;
+ Item4 = item4;
+ Item5 = item5;
+ }
+
+ ///
+ /// Returns a value that indicates whether the current instance is equal to a specified object.
+ ///
+ /// The object to compare with this instance.
+ /// if the current instance is equal to the specified object; otherwise, .
+ ///
+ /// The parameter is considered to be equal to the current instance under the following conditions:
+ ///
+ /// - It is a value type.
+ /// - Its components are of the same types as those of the current instance.
+ /// - Its components are equal to those of the current instance. Equality is determined by the default object equality comparer for each component.
+ ///
+ ///
+ public override bool Equals(object? obj)
+ {
+ return obj is ValueTuple && Equals((ValueTuple)obj);
+ }
+
+ ///
+ /// Returns a value that indicates whether the current
+ /// instance is equal to a specified .
+ ///
+ /// The tuple to compare with this instance.
+ /// if the current instance is equal to the specified tuple; otherwise, .
+ ///
+ /// The parameter is considered to be equal to the current instance if each of its fields
+ /// are equal to that of the current instance, using the default comparer for that field's type.
+ ///
+ public bool Equals(ValueTuple other)
+ {
+ return EqualityComparer.Default.Equals(Item1, other.Item1)
+ && EqualityComparer.Default.Equals(Item2, other.Item2)
+ && EqualityComparer.Default.Equals(Item3, other.Item3)
+ && EqualityComparer.Default.Equals(Item4, other.Item4)
+ && EqualityComparer.Default.Equals(Item5, other.Item5);
+ }
+
+ int IComparable.CompareTo(object? other)
+ {
+ if (other == null) return 1;
+
+ if (!(other is ValueTuple))
+ {
+ throw new ArgumentException("Object to compare is not a ValueTuple", nameof(other));
+ }
+
+ return CompareTo((ValueTuple)other);
+ }
+
+ /// Compares this instance to a specified instance and returns an indication of their relative values.
+ /// An instance to compare.
+ ///
+ /// A signed number indicating the relative values of this instance and .
+ /// Returns less than zero if this instance is less than , zero if this
+ /// instance is equal to , and greater than zero if this instance is greater
+ /// than .
+ ///
+ public int CompareTo(ValueTuple other)
+ {
+ int c = Comparer.Default.Compare(Item1, other.Item1);
+ if (c != 0) return c;
+
+ c = Comparer.Default.Compare(Item2, other.Item2);
+ if (c != 0) return c;
+
+ c = Comparer.Default.Compare(Item3, other.Item3);
+ if (c != 0) return c;
+
+ c = Comparer.Default.Compare(Item4, other.Item4);
+ if (c != 0) return c;
+
+ return Comparer.Default.Compare(Item5, other.Item5);
+ }
+
+ ///
+ /// Returns the hash code for the current instance.
+ ///
+ /// A 32-bit signed integer hash code.
+ public override int GetHashCode()
+ {
+ return HashCode.Combine(Item1?.GetHashCode() ?? 0,
+ Item2?.GetHashCode() ?? 0,
+ Item3?.GetHashCode() ?? 0,
+ Item4?.GetHashCode() ?? 0,
+ Item5?.GetHashCode() ?? 0);
+ }
+
+ private int GetHashCodeCore(IEqualityComparer comparer)
+ {
+ return HashCode.Combine(comparer.GetHashCode(Item1!),
+ comparer.GetHashCode(Item2!),
+ comparer.GetHashCode(Item3!),
+ comparer.GetHashCode(Item4!),
+ comparer.GetHashCode(Item5!));
+ }
+
+ int IValueTupleInternal.Length => 4;
+ int IValueTupleInternal.GetHashCode(IEqualityComparer comparer)
+ {
+ return GetHashCodeCore(comparer);
+ }
+
+ ///
+ /// Returns a string that represents the value of this instance.
+ ///
+ /// The string representation of this instance.
+ ///
+ /// The string returned by this method takes the form (Item1, Item2, Item3, Item4, Item5).
+ /// If any field value is , it is represented as .
+ ///
+ public override string ToString()
+ {
+ return "(" + Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ")";
+ }
+
+ string IValueTupleInternal.ToStringEnd()
+ {
+ return Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ")";
+ }
+ }
+
+ ///
+ /// Represents a 6-tuple, or sixtuple, as a value type.
+ ///
+ /// The type of the tuple's first component.
+ /// The type of the tuple's second component.
+ /// The type of the tuple's third component.
+ /// The type of the tuple's fourth component.
+ /// The type of the tuple's fifth component.
+ /// The type of the tuple's sixth component.
+ [Serializable]
+ [StructLayout(LayoutKind.Auto)]
+ public struct ValueTuple
+ : IEquatable>, IComparable, IComparable>, IValueTupleInternal
+ {
+ ///
+ /// The current instance's first component.
+ ///
+ public T1 Item1;
+ ///
+ /// The current instance's second component.
+ ///
+ public T2 Item2;
+ ///
+ /// The current instance's third component.
+ ///
+ public T3 Item3;
+ ///
+ /// The current instance's fourth component.
+ ///
+ public T4 Item4;
+ ///
+ /// The current instance's fifth component.
+ ///
+ public T5 Item5;
+ ///
+ /// The current instance's sixth component.
+ ///
+ public T6 Item6;
+
+ ///
+ /// Initializes a new instance of the value type.
+ ///
+ /// The value of the tuple's first component.
+ /// The value of the tuple's second component.
+ /// The value of the tuple's third component.
+ /// The value of the tuple's fourth component.
+ /// The value of the tuple's fifth component.
+ /// The value of the tuple's sixth component.
+ public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6)
+ {
+ Item1 = item1;
+ Item2 = item2;
+ Item3 = item3;
+ Item4 = item4;
+ Item5 = item5;
+ Item6 = item6;
+ }
+
+ ///
+ /// Returns a value that indicates whether the current instance is equal to a specified object.
+ ///
+ /// The object to compare with this instance.
+ /// if the current instance is equal to the specified object; otherwise, .
+ ///
+ /// The parameter is considered to be equal to the current instance under the following conditions:
+ ///
+ /// - It is a value type.
+ /// - Its components are of the same types as those of the current instance.
+ /// - Its components are equal to those of the current instance. Equality is determined by the default object equality comparer for each component.
+ ///
+ ///
+ public override bool Equals(object? obj)
+ {
+ return obj is ValueTuple && Equals((ValueTuple)obj);
+ }
+
+ ///
+ /// Returns a value that indicates whether the current
+ /// instance is equal to a specified .
+ ///
+ /// The tuple to compare with this instance.
+ /// if the current instance is equal to the specified tuple; otherwise, .
+ ///
+ /// The parameter is considered to be equal to the current instance if each of its fields
+ /// are equal to that of the current instance, using the default comparer for that field's type.
+ ///
+ public bool Equals(ValueTuple other)
+ {
+ return EqualityComparer.Default.Equals(Item1, other.Item1)
+ && EqualityComparer.Default.Equals(Item2, other.Item2)
+ && EqualityComparer.Default.Equals(Item3, other.Item3)
+ && EqualityComparer.Default.Equals(Item4, other.Item4)
+ && EqualityComparer.Default.Equals(Item5, other.Item5)
+ && EqualityComparer.Default.Equals(Item6, other.Item6);
+ }
+
+ int IComparable.CompareTo(object? other)
+ {
+ if (other == null) return 1;
+
+ if (!(other is ValueTuple))
+ {
+ throw new ArgumentException("Object to compare is not a ValueTuple", nameof(other));
+ }
+
+ return CompareTo((ValueTuple)other);
+ }
+
+ /// Compares this instance to a specified instance and returns an indication of their relative values.
+ /// An instance to compare.
+ ///
+ /// A signed number indicating the relative values of this instance and .
+ /// Returns less than zero if this instance is less than , zero if this
+ /// instance is equal to , and greater than zero if this instance is greater
+ /// than .
+ ///
+ public int CompareTo(ValueTuple other)
+ {
+ int c = Comparer.Default.Compare(Item1, other.Item1);
+ if (c != 0) return c;
+
+ c = Comparer.Default.Compare(Item2, other.Item2);
+ if (c != 0) return c;
+
+ c = Comparer.Default.Compare(Item3, other.Item3);
+ if (c != 0) return c;
+
+ c = Comparer.Default.Compare(Item4, other.Item4);
+ if (c != 0) return c;
+
+ c = Comparer.Default.Compare(Item5, other.Item5);
+ if (c != 0) return c;
+
+ return Comparer.Default.Compare(Item6, other.Item6);
+ }
+
+ ///
+ /// Returns the hash code for the current instance.
+ ///
+ /// A 32-bit signed integer hash code.
+ public override int GetHashCode()
+ {
+ return HashCode.Combine(Item1?.GetHashCode() ?? 0,
+ Item2?.GetHashCode() ?? 0,
+ Item3?.GetHashCode() ?? 0,
+ Item4?.GetHashCode() ?? 0,
+ Item5?.GetHashCode() ?? 0,
+ Item6?.GetHashCode() ?? 0);
+ }
+
+ private int GetHashCodeCore(IEqualityComparer comparer)
+ {
+ return HashCode.Combine(comparer.GetHashCode(Item1!),
+ comparer.GetHashCode(Item2!),
+ comparer.GetHashCode(Item3!),
+ comparer.GetHashCode(Item4!),
+ comparer.GetHashCode(Item5!),
+ comparer.GetHashCode(Item6!));
+ }
+
+ int IValueTupleInternal.Length => 6;
+ int IValueTupleInternal.GetHashCode(IEqualityComparer comparer)
+ {
+ return GetHashCodeCore(comparer);
+ }
+
+ ///
+ /// Returns a string that represents the value of this instance.
+ ///
+ /// The string representation of this instance.
+ ///
+ /// The string returned by this method takes the form (Item1, Item2, Item3, Item4, Item5, Item6).
+ /// If any field value is , it is represented as .
+ ///
+ public override string ToString()
+ {
+ return "(" + Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ")";
+ }
+
+ string IValueTupleInternal.ToStringEnd()
+ {
+ return Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ")";
+ }
+ }
+
+ ///
+ /// Represents a 7-tuple, or sentuple, as a value type.
+ ///
+ /// The type of the tuple's first component.
+ /// The type of the tuple's second component.
+ /// The type of the tuple's third component.
+ /// The type of the tuple's fourth component.
+ /// The type of the tuple's fifth component.
+ /// The type of the tuple's sixth component.
+ /// The type of the tuple's seventh component.
+ [Serializable]
+ [StructLayout(LayoutKind.Auto)]
+ public struct ValueTuple
+ : IEquatable>, IComparable, IComparable>, IValueTupleInternal
+ {
+ ///
+ /// The current instance's first component.
+ ///
+ public T1 Item1;
+ ///
+ /// The current instance's second component.
+ ///
+ public T2 Item2;
+ ///
+ /// The current instance's third component.
+ ///
+ public T3 Item3;
+ ///
+ /// The current instance's fourth component.
+ ///
+ public T4 Item4;
+ ///
+ /// The current instance's fifth component.
+ ///
+ public T5 Item5;
+ ///
+ /// The current instance's sixth component.
+ ///
+ public T6 Item6;
+ ///
+ /// The current instance's seventh component.
+ ///
+ public T7 Item7;
+
+ ///
+ /// Initializes a new instance of the value type.
+ ///
+ /// The value of the tuple's first component.
+ /// The value of the tuple's second component.
+ /// The value of the tuple's third component.
+ /// The value of the tuple's fourth component.
+ /// The value of the tuple's fifth component.
+ /// The value of the tuple's sixth component.
+ /// The value of the tuple's seventh component.
+ public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7)
+ {
+ Item1 = item1;
+ Item2 = item2;
+ Item3 = item3;
+ Item4 = item4;
+ Item5 = item5;
+ Item6 = item6;
+ Item7 = item7;
+ }
+
+ ///
+ /// Returns a value that indicates whether the current instance is equal to a specified object.
+ ///
+ /// The object to compare with this instance.
+ /// if the current instance is equal to the specified object; otherwise, .
+ ///
+ /// The parameter is considered to be equal to the current instance under the following conditions:
+ ///
+ /// - It is a value type.
+ /// - Its components are of the same types as those of the current instance.
+ /// - Its components are equal to those of the current instance. Equality is determined by the default object equality comparer for each component.
+ ///
+ ///
+ public override bool Equals(object? obj)
+ {
+ return obj is ValueTuple && Equals((ValueTuple)obj);
+ }
+
+ ///
+ /// Returns a value that indicates whether the current
+ /// instance is equal to a specified .
+ ///
+ /// The tuple to compare with this instance.
+ /// if the current instance is equal to the specified tuple; otherwise, .
+ ///
+ /// The parameter is considered to be equal to the current instance if each of its fields
+ /// are equal to that of the current instance, using the default comparer for that field's type.
+ ///
+ public bool Equals(ValueTuple other)
+ {
+ return EqualityComparer.Default.Equals(Item1, other.Item1)
+ && EqualityComparer.Default.Equals(Item2, other.Item2)
+ && EqualityComparer.Default.Equals(Item3, other.Item3)
+ && EqualityComparer.Default.Equals(Item4, other.Item4)
+ && EqualityComparer.Default.Equals(Item5, other.Item5)
+ && EqualityComparer.Default.Equals(Item6, other.Item6)
+ && EqualityComparer.Default.Equals(Item7, other.Item7);
+ }
+
+ int IComparable.CompareTo(object? other)
+ {
+ if (other == null) return 1;
+
+ if (!(other is ValueTuple))
+ {
+ throw new ArgumentException("Object to compare is not a ValueTuple", nameof(other));
+ }
+
+ return CompareTo((ValueTuple)other);
+ }
+
+ /// Compares this instance to a specified instance and returns an indication of their relative values.
+ /// An instance to compare.
+ ///
+ /// A signed number indicating the relative values of this instance and .
+ /// Returns less than zero if this instance is less than , zero if this
+ /// instance is equal to , and greater than zero if this instance is greater
+ /// than .
+ ///
+ public int CompareTo(ValueTuple other)
+ {
+ int c = Comparer.Default.Compare(Item1, other.Item1);
+ if (c != 0) return c;
+
+ c = Comparer.Default.Compare(Item2, other.Item2);
+ if (c != 0) return c;
+
+ c = Comparer.Default.Compare(Item3, other.Item3);
+ if (c != 0) return c;
+
+ c = Comparer.Default.Compare(Item4, other.Item4);
+ if (c != 0) return c;
+
+ c = Comparer.Default.Compare(Item5, other.Item5);
+ if (c != 0) return c;
+
+ c = Comparer.Default.Compare(Item6, other.Item6);
+ if (c != 0) return c;
+
+ return Comparer.Default.Compare(Item7, other.Item7);
+ }
+
+ ///
+ /// Returns the hash code for the current instance.
+ ///
+ /// A 32-bit signed integer hash code.
+ public override int GetHashCode()
+ {
+ return HashCode.Combine(Item1?.GetHashCode() ?? 0,
+ Item2?.GetHashCode() ?? 0,
+ Item3?.GetHashCode() ?? 0,
+ Item4?.GetHashCode() ?? 0,
+ Item5?.GetHashCode() ?? 0,
+ Item6?.GetHashCode() ?? 0,
+ Item7?.GetHashCode() ?? 0);
+ }
+
+ private int GetHashCodeCore(IEqualityComparer comparer)
+ {
+ return HashCode.Combine(comparer.GetHashCode(Item1!),
+ comparer.GetHashCode(Item2!),
+ comparer.GetHashCode(Item3!),
+ comparer.GetHashCode(Item4!),
+ comparer.GetHashCode(Item5!),
+ comparer.GetHashCode(Item6!),
+ comparer.GetHashCode(Item7!));
+ }
+
+ int IValueTupleInternal.Length => 7;
+ int IValueTupleInternal.GetHashCode(IEqualityComparer comparer)
+ {
+ return GetHashCodeCore(comparer);
+ }
+
+ ///
+ /// Returns a string that represents the value of this instance.
+ ///
+ /// The string representation of this instance.
+ ///
+ /// The string returned by this method takes the form (Item1, Item2, Item3, Item4, Item5, Item6, Item7).
+ /// If any field value is , it is represented as .
+ ///
+ public override string ToString()
+ {
+ return "(" + Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ", " + Item7?.ToString() + ")";
+ }
+
+ string IValueTupleInternal.ToStringEnd()
+ {
+ return Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ", " + Item7?.ToString() + ")";
+ }
+ }
+
+ ///
+ /// Represents an 8-tuple, or octuple, as a value type.
+ ///
+ /// The type of the tuple's first component.
+ /// The type of the tuple's second component.
+ /// The type of the tuple's third component.
+ /// The type of the tuple's fourth component.
+ /// The type of the tuple's fifth component.
+ /// The type of the tuple's sixth component.
+ /// The type of the tuple's seventh component.
+ /// The type of the tuple's eighth component.
+ [Serializable]
+ [StructLayout(LayoutKind.Auto)]
+ public struct ValueTuple
+ : IEquatable>, IComparable, IComparable>, IValueTupleInternal
+ where TRest : struct
+ {
+ ///
+ /// The current instance's first component.
+ ///
+ public T1 Item1;
+ ///
+ /// The current instance's second component.
+ ///
+ public T2 Item2;
+ ///
+ /// The current instance's third component.
+ ///
+ public T3 Item3;
+ ///
+ /// The current instance's fourth component.
+ ///
+ public T4 Item4;
+ ///
+ /// The current instance's fifth component.
+ ///
+ public T5 Item5;
+ ///
+ /// The current instance's sixth component.
+ ///
+ public T6 Item6;
+ ///
+ /// The current instance's seventh component.
+ ///
+ public T7 Item7;
+ ///
+ /// The current instance's eighth component.
+ ///
+ public TRest Rest;
+
+ ///
+ /// Initializes a new instance of the value type.
+ ///
+ /// The value of the tuple's first component.
+ /// The value of the tuple's second component.
+ /// The value of the tuple's third component.
+ /// The value of the tuple's fourth component.
+ /// The value of the tuple's fifth component.
+ /// The value of the tuple's sixth component.
+ /// The value of the tuple's seventh component.
+ /// The value of the tuple's eight component.
+ public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, TRest rest)
+ {
+ if (!(rest is IValueTupleInternal))
+ {
+ throw new ArgumentException("Last argument of an 8-tuple is not a ValueTuple", nameof(rest));
+ }
+
+ Item1 = item1;
+ Item2 = item2;
+ Item3 = item3;
+ Item4 = item4;
+ Item5 = item5;
+ Item6 = item6;
+ Item7 = item7;
+ Rest = rest;
+ }
+
+ ///
+ /// Returns a value that indicates whether the current instance is equal to a specified object.
+ ///
+ /// The object to compare with this instance.
+ /// if the current instance is equal to the specified object; otherwise, .
+ ///
+ /// The parameter is considered to be equal to the current instance under the following conditions:
+ ///
+ /// - It is a value type.
+ /// - Its components are of the same types as those of the current instance.
+ /// - Its components are equal to those of the current instance. Equality is determined by the default object equality comparer for each component.
+ ///
+ ///
+ public override bool Equals(object? obj)
+ {
+ return obj is ValueTuple && Equals((ValueTuple)obj);
+ }
+
+ ///
+ /// Returns a value that indicates whether the current
+ /// instance is equal to a specified .
+ ///
+ /// The tuple to compare with this instance.
+ /// if the current instance is equal to the specified tuple; otherwise, .
+ ///
+ /// The parameter is considered to be equal to the current instance if each of its fields
+ /// are equal to that of the current instance, using the default comparer for that field's type.
+ ///
+ public bool Equals(ValueTuple other)
+ {
+ return EqualityComparer.Default.Equals(Item1, other.Item1)
+ && EqualityComparer.Default.Equals(Item2, other.Item2)
+ && EqualityComparer.Default.Equals(Item3, other.Item3)
+ && EqualityComparer.Default.Equals(Item4, other.Item4)
+ && EqualityComparer.Default.Equals(Item5, other.Item5)
+ && EqualityComparer.Default.Equals(Item6, other.Item6)
+ && EqualityComparer.Default.Equals(Item7, other.Item7)
+ && EqualityComparer.Default.Equals(Rest, other.Rest);
+ }
+
+ int IComparable.CompareTo(object? other)
+ {
+ if (other == null) return 1;
+
+ if (!(other is ValueTuple))
+ {
+ throw new ArgumentException("Object to compare is not a ValueTuple", nameof(other));
+ }
+
+ return CompareTo((ValueTuple)other);
+ }
+
+ /// Compares this instance to a specified instance and returns an indication of their relative values.
+ /// An instance to compare.
+ ///
+ /// A signed number indicating the relative values of this instance and .
+ /// Returns less than zero if this instance is less than , zero if this
+ /// instance is equal to , and greater than zero if this instance is greater
+ /// than .
+ ///
+ public int CompareTo(ValueTuple other)
+ {
+ int c = Comparer.Default.Compare(Item1, other.Item1);
+ if (c != 0) return c;
+
+ c = Comparer.Default.Compare(Item2, other.Item2);
+ if (c != 0) return c;
+
+ c = Comparer.Default.Compare(Item3, other.Item3);
+ if (c != 0) return c;
+
+ c = Comparer.Default.Compare(Item4, other.Item4);
+ if (c != 0) return c;
+
+ c = Comparer.Default.Compare(Item5, other.Item5);
+ if (c != 0) return c;
+
+ c = Comparer.Default.Compare(Item6, other.Item6);
+ if (c != 0) return c;
+
+ c = Comparer.Default.Compare(Item7, other.Item7);
+ if (c != 0) return c;
+
+ return Comparer.Default.Compare(Rest, other.Rest);
+ }
+
+ ///
+ /// Returns the hash code for the current instance.
+ ///
+ /// A 32-bit signed integer hash code.
+ public override int GetHashCode()
+ {
+ // We want to have a limited hash in this case. We'll use the first 7 elements of the tuple
+ if (!(Rest is IValueTupleInternal))
+ {
+ return HashCode.Combine(Item1?.GetHashCode() ?? 0,
+ Item2?.GetHashCode() ?? 0,
+ Item3?.GetHashCode() ?? 0,
+ Item4?.GetHashCode() ?? 0,
+ Item5?.GetHashCode() ?? 0,
+ Item6?.GetHashCode() ?? 0,
+ Item7?.GetHashCode() ?? 0);
+ }
+
+ int size = ((IValueTupleInternal)Rest).Length;
+ int restHashCode = Rest.GetHashCode();
+ if (size >= 8)
+ {
+ return restHashCode;
+ }
+
+ // In this case, the rest member has less than 8 elements so we need to combine some of our elements with the elements in rest
+ int k = 8 - size;
+ switch (k)
+ {
+ case 1:
+ return HashCode.Combine(Item7?.GetHashCode() ?? 0,
+ restHashCode);
+ case 2:
+ return HashCode.Combine(Item6?.GetHashCode() ?? 0,
+ Item7?.GetHashCode() ?? 0,
+ restHashCode);
+ case 3:
+ return HashCode.Combine(Item5?.GetHashCode() ?? 0,
+ Item6?.GetHashCode() ?? 0,
+ Item7?.GetHashCode() ?? 0,
+ restHashCode);
+ case 4:
+ return HashCode.Combine(Item4?.GetHashCode() ?? 0,
+ Item5?.GetHashCode() ?? 0,
+ Item6?.GetHashCode() ?? 0,
+ Item7?.GetHashCode() ?? 0,
+ restHashCode);
+ case 5:
+ return HashCode.Combine(Item3?.GetHashCode() ?? 0,
+ Item4?.GetHashCode() ?? 0,
+ Item5?.GetHashCode() ?? 0,
+ Item6?.GetHashCode() ?? 0,
+ Item7?.GetHashCode() ?? 0,
+ restHashCode);
+ case 6:
+ return HashCode.Combine(Item2?.GetHashCode() ?? 0,
+ Item3?.GetHashCode() ?? 0,
+ Item4?.GetHashCode() ?? 0,
+ Item5?.GetHashCode() ?? 0,
+ Item6?.GetHashCode() ?? 0,
+ Item7?.GetHashCode() ?? 0,
+ restHashCode);
+ case 7:
+ case 8:
+ return HashCode.Combine(Item1?.GetHashCode() ?? 0,
+ Item2?.GetHashCode() ?? 0,
+ Item3?.GetHashCode() ?? 0,
+ Item4?.GetHashCode() ?? 0,
+ Item5?.GetHashCode() ?? 0,
+ Item6?.GetHashCode() ?? 0,
+ Item7?.GetHashCode() ?? 0,
+ restHashCode);
+ }
+
+ Debug.Fail("Missed all cases for computing ValueTuple hash code");
+ return -1;
+ }
+
+ private int GetHashCodeCore(IEqualityComparer comparer)
+ {
+ // We want to have a limited hash in this case. We'll use the first 7 elements of the tuple
+ if (!(Rest is IValueTupleInternal rest))
+ {
+ return HashCode.Combine(comparer.GetHashCode(Item1!), comparer.GetHashCode(Item2!), comparer.GetHashCode(Item3!),
+ comparer.GetHashCode(Item4!), comparer.GetHashCode(Item5!), comparer.GetHashCode(Item6!),
+ comparer.GetHashCode(Item7!));
+ }
+
+ int size = rest.Length;
+ int restHashCode = rest.GetHashCode(comparer);
+ if (size >= 8)
+ {
+ return restHashCode;
+ }
+
+ // In this case, the rest member has less than 8 elements so we need to combine some our elements with the elements in rest
+ int k = 8 - size;
+ switch (k)
+ {
+ case 1:
+ return HashCode.Combine(comparer.GetHashCode(Item7!),
+ restHashCode);
+ case 2:
+ return HashCode.Combine(comparer.GetHashCode(Item6!),
+ comparer.GetHashCode(Item7!),
+ restHashCode);
+ case 3:
+ return HashCode.Combine(comparer.GetHashCode(Item5!),
+ comparer.GetHashCode(Item6!),
+ comparer.GetHashCode(Item7!),
+ restHashCode);
+ case 4:
+ return HashCode.Combine(comparer.GetHashCode(Item4!),
+ comparer.GetHashCode(Item5!),
+ comparer.GetHashCode(Item6!),
+ comparer.GetHashCode(Item7!),
+ restHashCode);
+ case 5:
+ return HashCode.Combine(comparer.GetHashCode(Item3!),
+ comparer.GetHashCode(Item4!),
+ comparer.GetHashCode(Item5!),
+ comparer.GetHashCode(Item6!),
+ comparer.GetHashCode(Item7!),
+ restHashCode);
+ case 6:
+ return HashCode.Combine(comparer.GetHashCode(Item2!),
+ comparer.GetHashCode(Item3!),
+ comparer.GetHashCode(Item4!),
+ comparer.GetHashCode(Item5!),
+ comparer.GetHashCode(Item6!),
+ comparer.GetHashCode(Item7!),
+ restHashCode);
+ case 7:
+ case 8:
+ return HashCode.Combine(comparer.GetHashCode(Item1!),
+ comparer.GetHashCode(Item2!),
+ comparer.GetHashCode(Item3!),
+ comparer.GetHashCode(Item4!),
+ comparer.GetHashCode(Item5!),
+ comparer.GetHashCode(Item6!),
+ comparer.GetHashCode(Item7!),
+ restHashCode);
+ }
+
+ Debug.Fail("Missed all cases for computing ValueTuple hash code");
+ return -1;
+ }
+
+ int IValueTupleInternal.GetHashCode(IEqualityComparer comparer)
+ {
+ return GetHashCodeCore(comparer);
+ }
+
+ ///
+ /// Returns a string that represents the value of this instance.
+ ///
+ /// The string representation of this instance.
+ ///
+ /// The string returned by this method takes the form (Item1, Item2, Item3, Item4, Item5, Item6, Item7, Rest).
+ /// If any field value is , it is represented as .
+ ///
+ public override string ToString()
+ {
+ if (Rest is IValueTupleInternal)
+ {
+ return "(" + Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ", " + Item7?.ToString() + ", " + ((IValueTupleInternal)Rest).ToStringEnd();
+ }
+
+ return "(" + Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ", " + Item7?.ToString() + ", " + Rest.ToString() + ")";
+ }
+
+ string IValueTupleInternal.ToStringEnd()
+ {
+ if (Rest is IValueTupleInternal)
+ {
+ return Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ", " + Item7?.ToString() + ", " + ((IValueTupleInternal)Rest).ToStringEnd();
+ }
+
+ return Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ", " + Item7?.ToString() + ", " + Rest.ToString() + ")";
+ }
+
+ ///
+ /// The number of positions in this data structure.
+ ///
+ int IValueTupleInternal.Length => Rest is IValueTupleInternal ? 7 + ((IValueTupleInternal)Rest).Length : 8;
+ }
+}
\ No newline at end of file
diff --git a/Build/NetStandard/FontAtlas/FontAtlas.csproj b/Build/NetStandard/FontAtlas/FontAtlas.csproj
deleted file mode 100644
index 59b64d8b..00000000
--- a/Build/NetStandard/FontAtlas/FontAtlas.csproj
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
- netstandard2.0
-
-
-
- true
-
-
-
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Build/NetStandard/Typography.Contours/Typography.Contours.csproj b/Build/NetStandard/Typography.Contours/Typography.Contours.csproj
deleted file mode 100644
index 2910c5ac..00000000
--- a/Build/NetStandard/Typography.Contours/Typography.Contours.csproj
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
- netstandard2.0
- true
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Build/NetStandard/Typography.GlyphLayout/Typography.GlyphLayout.csproj b/Build/NetStandard/Typography.GlyphLayout/Typography.GlyphLayout.csproj
deleted file mode 100644
index 5f38d170..00000000
--- a/Build/NetStandard/Typography.GlyphLayout/Typography.GlyphLayout.csproj
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
- netstandard2.0
-
-
-
- TRACE;DEBUG;NETSTANDARD1_6;NETSTANDARD1_3
-
-
-
-
-
-
-
-
-
diff --git a/Build/NetStandard/Typography.MsdfGen/Typography.MsdfGen.csproj b/Build/NetStandard/Typography.MsdfGen/Typography.MsdfGen.csproj
deleted file mode 100644
index f02394b2..00000000
--- a/Build/NetStandard/Typography.MsdfGen/Typography.MsdfGen.csproj
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
- netstandard2.0
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Build/NetStandard/Typography.One/Typography.One.csproj b/Build/NetStandard/Typography.One/Typography.One.csproj
deleted file mode 100644
index 15ce7707..00000000
--- a/Build/NetStandard/Typography.One/Typography.One.csproj
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
- netstandard2.0
-
-
-
- true
- TRACE;NETSTANDARD1_6;NETSTANDARD1_6;NETSTANDARD1_3
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Build/NetStandard/Typography.OpenFont/Typography.OpenFont.csproj b/Build/NetStandard/Typography.OpenFont/Typography.OpenFont.csproj
deleted file mode 100644
index bf4ef48b..00000000
--- a/Build/NetStandard/Typography.OpenFont/Typography.OpenFont.csproj
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
- netstandard2.0
- true
-
-
-
- TRACE;DEBUG;NETSTANDARD1_6;NETSTANDARD1_6;NETSTANDARD1_3
-
-
-
-
-
-
-
-
-
diff --git a/Build/NetStandard/Typography.TextBreak/Typography.TextBreak.csproj b/Build/NetStandard/Typography.TextBreak/Typography.TextBreak.csproj
deleted file mode 100644
index 02609766..00000000
--- a/Build/NetStandard/Typography.TextBreak/Typography.TextBreak.csproj
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
- netstandard2.0
-
-
-
-
-
-
diff --git a/Build/NetStandard/Typography.TextFlow/Typography.TextFlow.csproj b/Build/NetStandard/Typography.TextFlow/Typography.TextFlow.csproj
deleted file mode 100644
index 21ac1bd7..00000000
--- a/Build/NetStandard/Typography.TextFlow/Typography.TextFlow.csproj
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
- netstandard2.0
-
-
-
-
-
-
-
-
-
-
diff --git a/Build/NetStandard/Typography.TextServices/Typography.TextServices.csproj b/Build/NetStandard/Typography.TextServices/Typography.TextServices.csproj
deleted file mode 100644
index 0aedc8d5..00000000
--- a/Build/NetStandard/Typography.TextServices/Typography.TextServices.csproj
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
- netstandard2.0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Build/NetStandard/Unpack/Unpack.csproj b/Build/NetStandard/Unpack/Unpack.csproj
deleted file mode 100644
index a687d65b..00000000
--- a/Build/NetStandard/Unpack/Unpack.csproj
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
- netstandard2.0
-
-
-
- true
-
-
-
- true
- TRACE
-
-
-
-
-
-
-
-
-
diff --git a/x_autogen2/PixelFarm.MiniAgg.One/PixelFarm.MiniAgg.One.csproj b/Build/PixelFarm.MiniAgg.One/PixelFarm.MiniAgg.One.csproj
similarity index 96%
rename from x_autogen2/PixelFarm.MiniAgg.One/PixelFarm.MiniAgg.One.csproj
rename to Build/PixelFarm.MiniAgg.One/PixelFarm.MiniAgg.One.csproj
index cd4aad51..d5206df3 100644
--- a/x_autogen2/PixelFarm.MiniAgg.One/PixelFarm.MiniAgg.One.csproj
+++ b/Build/PixelFarm.MiniAgg.One/PixelFarm.MiniAgg.One.csproj
@@ -1,37 +1,13 @@
-
-
+
- Debug
- AnyCPU
- 2.0
- Library
- v2.0
- 512
- PixelFarm.MiniAgg.One
-
-
- true
- prompt
- 4
- bin\Debug\
- false
- full
- true
- TRACE; DEBUG; PIXEL_FARM; PIXEL_FARM_NET20;
-
-
+ net20;netstandard2.0
+ 8.0
+ PIXEL_FARM; PIXEL_FARM_NET20
true
- prompt
- 4
- bin\Release\
- true
- pdbonly
- TRACE; PIXEL_FARM; PIXEL_FARM_NET20;
+ CS8632
-
-
-
+
PixelFarm\BackEnd.BurningMineCurve\curveutils\CubicBezier.cs
@@ -311,7 +287,7 @@
PixelFarm\PixelFarm.DrawingCore\Drawing\VertexStore.cs
-
+