diff --git a/MsgPack.Windows.sln b/MsgPack.Windows.sln
index 69cd979e9..84077c7dd 100644
--- a/MsgPack.Windows.sln
+++ b/MsgPack.Windows.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
-VisualStudioVersion = 14.0.25123.0
+VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "common", "common", "{60EC42E9-D79B-4ADF-8F80-4DCD580061FD}"
ProjectSection(SolutionItems) = preProject
@@ -56,6 +56,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MsgPack.UnitTest.Uwp", "tes
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MsgPack.UnitTest.Uwp.Aot", "test\MsgPack.UnitTest.Uwp.Aot\MsgPack.UnitTest.Uwp.Aot.csproj", "{E4CA9866-6234-49D4-8CDF-1F3A21EFD138}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MsgPack.Core", "src\MsgPack.Core\MsgPack.Core.csproj", "{08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MsgPack.Serialization", "src\MsgPack.Serialization\MsgPack.Serialization.csproj", "{153CED68-9905-4B1F-9790-F463840895E2}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
CodeAnalysis|Any CPU = CodeAnalysis|Any CPU
@@ -377,7 +381,8 @@ Global
{9D65A105-FB03-40DB-9185-8C695B8EE8D6}.Release|Any CPU.Build.0 = Release|Any CPU
{9D65A105-FB03-40DB-9185-8C695B8EE8D6}.Release|ARM.ActiveCfg = Release|ARM
{9D65A105-FB03-40DB-9185-8C695B8EE8D6}.Release|ARM.Build.0 = Release|ARM
- {9D65A105-FB03-40DB-9185-8C695B8EE8D6}.Release|Mixed Platforms.ActiveCfg = Release|x86
+ {9D65A105-FB03-40DB-9185-8C695B8EE8D6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {9D65A105-FB03-40DB-9185-8C695B8EE8D6}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{9D65A105-FB03-40DB-9185-8C695B8EE8D6}.Release|x64.ActiveCfg = Release|x64
{9D65A105-FB03-40DB-9185-8C695B8EE8D6}.Release|x64.Build.0 = Release|x64
{9D65A105-FB03-40DB-9185-8C695B8EE8D6}.Release|x86.ActiveCfg = Release|x86
@@ -524,6 +529,86 @@ Global
{E4CA9866-6234-49D4-8CDF-1F3A21EFD138}.Release|x86.ActiveCfg = Release|x86
{E4CA9866-6234-49D4-8CDF-1F3A21EFD138}.Release|x86.Build.0 = Release|x86
{E4CA9866-6234-49D4-8CDF-1F3A21EFD138}.Release|x86.Deploy.0 = Release|x86
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.CodeAnalysis|Any CPU.ActiveCfg = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.CodeAnalysis|Any CPU.Build.0 = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.CodeAnalysis|ARM.ActiveCfg = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.CodeAnalysis|ARM.Build.0 = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.CodeAnalysis|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.CodeAnalysis|Mixed Platforms.Build.0 = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.CodeAnalysis|x64.ActiveCfg = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.CodeAnalysis|x64.Build.0 = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.CodeAnalysis|x86.ActiveCfg = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.CodeAnalysis|x86.Build.0 = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Debug|ARM.Build.0 = Debug|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Debug|x64.Build.0 = Debug|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Debug|x86.Build.0 = Debug|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.PerformanceTest|Any CPU.ActiveCfg = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.PerformanceTest|Any CPU.Build.0 = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.PerformanceTest|ARM.ActiveCfg = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.PerformanceTest|ARM.Build.0 = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.PerformanceTest|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.PerformanceTest|Mixed Platforms.Build.0 = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.PerformanceTest|x64.ActiveCfg = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.PerformanceTest|x64.Build.0 = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.PerformanceTest|x86.ActiveCfg = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.PerformanceTest|x86.Build.0 = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Release|ARM.ActiveCfg = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Release|ARM.Build.0 = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Release|x64.ActiveCfg = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Release|x64.Build.0 = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Release|x86.ActiveCfg = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Release|x86.Build.0 = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.CodeAnalysis|Any CPU.ActiveCfg = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.CodeAnalysis|Any CPU.Build.0 = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.CodeAnalysis|ARM.ActiveCfg = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.CodeAnalysis|ARM.Build.0 = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.CodeAnalysis|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.CodeAnalysis|Mixed Platforms.Build.0 = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.CodeAnalysis|x64.ActiveCfg = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.CodeAnalysis|x64.Build.0 = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.CodeAnalysis|x86.ActiveCfg = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.CodeAnalysis|x86.Build.0 = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Debug|ARM.Build.0 = Debug|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Debug|x64.Build.0 = Debug|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Debug|x86.Build.0 = Debug|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.PerformanceTest|Any CPU.ActiveCfg = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.PerformanceTest|Any CPU.Build.0 = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.PerformanceTest|ARM.ActiveCfg = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.PerformanceTest|ARM.Build.0 = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.PerformanceTest|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.PerformanceTest|Mixed Platforms.Build.0 = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.PerformanceTest|x64.ActiveCfg = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.PerformanceTest|x64.Build.0 = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.PerformanceTest|x86.ActiveCfg = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.PerformanceTest|x86.Build.0 = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Release|ARM.ActiveCfg = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Release|ARM.Build.0 = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Release|x64.ActiveCfg = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Release|x64.Build.0 = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Release|x86.ActiveCfg = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -548,5 +633,7 @@ Global
{A1B322FC-AA39-4894-AFA8-AB427A3FBA09} = {BFCE0B36-F21B-4EB1-919E-C486E70C8BEA}
{0F930636-458B-401F-9EAF-F4F05E93BCC9} = {7D06945C-638C-4973-B0B6-D0D667FA318F}
{E4CA9866-6234-49D4-8CDF-1F3A21EFD138} = {09C98E72-44F7-4469-B82A-DFA3053652E6}
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F} = {BFCE0B36-F21B-4EB1-919E-C486E70C8BEA}
+ {153CED68-9905-4B1F-9790-F463840895E2} = {BFCE0B36-F21B-4EB1-919E-C486E70C8BEA}
EndGlobalSection
EndGlobal
diff --git a/MsgPack.nuspec b/MsgPack.nuspec
index 714be6825..052c95491 100644
--- a/MsgPack.nuspec
+++ b/MsgPack.nuspec
@@ -19,6 +19,7 @@ This package provides MessagePack serialization/deserialization APIs. This pacak
+
diff --git a/MsgPack.sln b/MsgPack.sln
index 2f81409d1..3458f3bb4 100644
--- a/MsgPack.sln
+++ b/MsgPack.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
-VisualStudioVersion = 14.0.25123.0
+VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "common", "common", "{60EC42E9-D79B-4ADF-8F80-4DCD580061FD}"
ProjectSection(SolutionItems) = preProject
@@ -42,6 +42,22 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".NET45", ".NET45", "{3E9C77
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MsgPack.Net45", "src\MsgPack.Net45\MsgPack.Net45.csproj", "{9C7B55A6-AF7F-4D26-AB5B-297B7FF25B6D}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".NETStandard", ".NETStandard", "{7ED37CCB-869D-4FAC-80F5-3A13B2386B1D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MsgPack.CodeGeneration.Core", "src\MsgPack.CodeGeneration.Core\MsgPack.CodeGeneration.Core.csproj", "{EFE532EA-77C8-4877-96C2-E79FD101B2AB}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MsgPack.Core", "src\MsgPack.Core\MsgPack.Core.csproj", "{08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MsgPack.Serialization", "src\MsgPack.Serialization\MsgPack.Serialization.csproj", "{153CED68-9905-4B1F-9790-F463840895E2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MsgPack.CodeGeneration.CSharp", "src\MsgPack.CodeGeneration.CSharp\MsgPack.CodeGeneration.CSharp.csproj", "{B10240C1-BB07-47A3-B056-CE52B5194D86}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MsgPack.CodeGeneration.VisualBasic", "src\MsgPack.CodeGeneration.VisualBasic\MsgPack.CodeGeneration.VisualBasic.csproj", "{A88D64DB-DE14-4B77-80D8-B765F45EBB8B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MsgPack.UnitTest.CodeTree", "test\MsgPack.UnitTest.CodeTree\MsgPack.UnitTest.CodeTree.csproj", "{D5A4E386-E418-4407-916E-A65092B78693}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CoreCLR", "CoreCLR", "{F7CD1D27-1441-4C2F-AB17-6FF8803460EC}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
CodeAnalysis|Any CPU = CodeAnalysis|Any CPU
@@ -234,6 +250,245 @@ Global
{9C7B55A6-AF7F-4D26-AB5B-297B7FF25B6D}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{9C7B55A6-AF7F-4D26-AB5B-297B7FF25B6D}.Release|x64.ActiveCfg = Release|Any CPU
{9C7B55A6-AF7F-4D26-AB5B-297B7FF25B6D}.Release|x86.ActiveCfg = Release|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.CodeAnalysis|Any CPU.ActiveCfg = Release|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.CodeAnalysis|Any CPU.Build.0 = Release|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.CodeAnalysis|ARM.ActiveCfg = Release|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.CodeAnalysis|ARM.Build.0 = Release|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.CodeAnalysis|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.CodeAnalysis|Mixed Platforms.Build.0 = Release|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.CodeAnalysis|x64.ActiveCfg = Release|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.CodeAnalysis|x64.Build.0 = Release|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.CodeAnalysis|x86.ActiveCfg = Release|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.CodeAnalysis|x86.Build.0 = Release|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.Debug|ARM.Build.0 = Debug|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.Debug|x64.Build.0 = Debug|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.Debug|x86.Build.0 = Debug|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.PerformanceTest|Any CPU.ActiveCfg = Release|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.PerformanceTest|Any CPU.Build.0 = Release|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.PerformanceTest|ARM.ActiveCfg = Release|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.PerformanceTest|ARM.Build.0 = Release|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.PerformanceTest|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.PerformanceTest|Mixed Platforms.Build.0 = Release|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.PerformanceTest|x64.ActiveCfg = Release|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.PerformanceTest|x64.Build.0 = Release|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.PerformanceTest|x86.ActiveCfg = Release|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.PerformanceTest|x86.Build.0 = Release|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.Release|ARM.ActiveCfg = Release|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.Release|ARM.Build.0 = Release|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.Release|x64.ActiveCfg = Release|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.Release|x64.Build.0 = Release|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.Release|x86.ActiveCfg = Release|Any CPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}.Release|x86.Build.0 = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.CodeAnalysis|Any CPU.ActiveCfg = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.CodeAnalysis|Any CPU.Build.0 = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.CodeAnalysis|ARM.ActiveCfg = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.CodeAnalysis|ARM.Build.0 = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.CodeAnalysis|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.CodeAnalysis|Mixed Platforms.Build.0 = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.CodeAnalysis|x64.ActiveCfg = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.CodeAnalysis|x64.Build.0 = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.CodeAnalysis|x86.ActiveCfg = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.CodeAnalysis|x86.Build.0 = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Debug|ARM.Build.0 = Debug|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Debug|x64.Build.0 = Debug|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Debug|x86.Build.0 = Debug|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.PerformanceTest|Any CPU.ActiveCfg = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.PerformanceTest|Any CPU.Build.0 = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.PerformanceTest|ARM.ActiveCfg = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.PerformanceTest|ARM.Build.0 = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.PerformanceTest|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.PerformanceTest|Mixed Platforms.Build.0 = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.PerformanceTest|x64.ActiveCfg = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.PerformanceTest|x64.Build.0 = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.PerformanceTest|x86.ActiveCfg = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.PerformanceTest|x86.Build.0 = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Release|ARM.ActiveCfg = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Release|ARM.Build.0 = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Release|x64.ActiveCfg = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Release|x64.Build.0 = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Release|x86.ActiveCfg = Release|Any CPU
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F}.Release|x86.Build.0 = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.CodeAnalysis|Any CPU.ActiveCfg = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.CodeAnalysis|Any CPU.Build.0 = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.CodeAnalysis|ARM.ActiveCfg = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.CodeAnalysis|ARM.Build.0 = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.CodeAnalysis|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.CodeAnalysis|Mixed Platforms.Build.0 = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.CodeAnalysis|x64.ActiveCfg = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.CodeAnalysis|x64.Build.0 = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.CodeAnalysis|x86.ActiveCfg = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.CodeAnalysis|x86.Build.0 = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Debug|ARM.Build.0 = Debug|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Debug|x64.Build.0 = Debug|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Debug|x86.Build.0 = Debug|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.PerformanceTest|Any CPU.ActiveCfg = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.PerformanceTest|Any CPU.Build.0 = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.PerformanceTest|ARM.ActiveCfg = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.PerformanceTest|ARM.Build.0 = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.PerformanceTest|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.PerformanceTest|Mixed Platforms.Build.0 = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.PerformanceTest|x64.ActiveCfg = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.PerformanceTest|x64.Build.0 = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.PerformanceTest|x86.ActiveCfg = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.PerformanceTest|x86.Build.0 = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Release|ARM.ActiveCfg = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Release|ARM.Build.0 = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Release|x64.ActiveCfg = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Release|x64.Build.0 = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Release|x86.ActiveCfg = Release|Any CPU
+ {153CED68-9905-4B1F-9790-F463840895E2}.Release|x86.Build.0 = Release|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.CodeAnalysis|Any CPU.ActiveCfg = Release|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.CodeAnalysis|Any CPU.Build.0 = Release|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.CodeAnalysis|ARM.ActiveCfg = Release|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.CodeAnalysis|ARM.Build.0 = Release|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.CodeAnalysis|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.CodeAnalysis|Mixed Platforms.Build.0 = Release|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.CodeAnalysis|x64.ActiveCfg = Release|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.CodeAnalysis|x64.Build.0 = Release|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.CodeAnalysis|x86.ActiveCfg = Release|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.CodeAnalysis|x86.Build.0 = Release|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.Debug|ARM.Build.0 = Debug|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.Debug|x64.Build.0 = Debug|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.Debug|x86.Build.0 = Debug|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.PerformanceTest|Any CPU.ActiveCfg = Release|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.PerformanceTest|Any CPU.Build.0 = Release|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.PerformanceTest|ARM.ActiveCfg = Release|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.PerformanceTest|ARM.Build.0 = Release|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.PerformanceTest|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.PerformanceTest|Mixed Platforms.Build.0 = Release|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.PerformanceTest|x64.ActiveCfg = Release|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.PerformanceTest|x64.Build.0 = Release|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.PerformanceTest|x86.ActiveCfg = Release|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.PerformanceTest|x86.Build.0 = Release|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.Release|ARM.ActiveCfg = Release|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.Release|ARM.Build.0 = Release|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.Release|x64.ActiveCfg = Release|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.Release|x64.Build.0 = Release|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.Release|x86.ActiveCfg = Release|Any CPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}.Release|x86.Build.0 = Release|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.CodeAnalysis|Any CPU.ActiveCfg = Release|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.CodeAnalysis|Any CPU.Build.0 = Release|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.CodeAnalysis|ARM.ActiveCfg = Release|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.CodeAnalysis|ARM.Build.0 = Release|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.CodeAnalysis|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.CodeAnalysis|Mixed Platforms.Build.0 = Release|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.CodeAnalysis|x64.ActiveCfg = Release|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.CodeAnalysis|x64.Build.0 = Release|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.CodeAnalysis|x86.ActiveCfg = Release|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.CodeAnalysis|x86.Build.0 = Release|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.Debug|ARM.Build.0 = Debug|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.Debug|x64.Build.0 = Debug|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.Debug|x86.Build.0 = Debug|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.PerformanceTest|Any CPU.ActiveCfg = Release|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.PerformanceTest|Any CPU.Build.0 = Release|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.PerformanceTest|ARM.ActiveCfg = Release|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.PerformanceTest|ARM.Build.0 = Release|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.PerformanceTest|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.PerformanceTest|Mixed Platforms.Build.0 = Release|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.PerformanceTest|x64.ActiveCfg = Release|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.PerformanceTest|x64.Build.0 = Release|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.PerformanceTest|x86.ActiveCfg = Release|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.PerformanceTest|x86.Build.0 = Release|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.Release|ARM.ActiveCfg = Release|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.Release|ARM.Build.0 = Release|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.Release|x64.ActiveCfg = Release|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.Release|x64.Build.0 = Release|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.Release|x86.ActiveCfg = Release|Any CPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}.Release|x86.Build.0 = Release|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.CodeAnalysis|Any CPU.ActiveCfg = Release|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.CodeAnalysis|Any CPU.Build.0 = Release|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.CodeAnalysis|ARM.ActiveCfg = Release|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.CodeAnalysis|ARM.Build.0 = Release|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.CodeAnalysis|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.CodeAnalysis|Mixed Platforms.Build.0 = Release|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.CodeAnalysis|x64.ActiveCfg = Release|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.CodeAnalysis|x64.Build.0 = Release|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.CodeAnalysis|x86.ActiveCfg = Release|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.CodeAnalysis|x86.Build.0 = Release|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.Debug|ARM.Build.0 = Debug|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.Debug|x64.Build.0 = Debug|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.Debug|x86.Build.0 = Debug|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.PerformanceTest|Any CPU.ActiveCfg = Release|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.PerformanceTest|Any CPU.Build.0 = Release|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.PerformanceTest|ARM.ActiveCfg = Release|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.PerformanceTest|ARM.Build.0 = Release|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.PerformanceTest|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.PerformanceTest|Mixed Platforms.Build.0 = Release|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.PerformanceTest|x64.ActiveCfg = Release|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.PerformanceTest|x64.Build.0 = Release|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.PerformanceTest|x86.ActiveCfg = Release|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.PerformanceTest|x86.Build.0 = Release|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.Release|ARM.ActiveCfg = Release|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.Release|ARM.Build.0 = Release|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.Release|x64.ActiveCfg = Release|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.Release|x64.Build.0 = Release|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.Release|x86.ActiveCfg = Release|Any CPU
+ {D5A4E386-E418-4407-916E-A65092B78693}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -250,5 +505,13 @@ Global
{EACF1BF1-CB21-4D62-942C-3488F60B8D70} = {87A17015-9338-431E-B338-57BDA03984C1}
{3E9C7751-EE97-4820-BFEF-BA5F532A45C9} = {1BD5D488-707E-4030-8AE8-80D93D04963F}
{9C7B55A6-AF7F-4D26-AB5B-297B7FF25B6D} = {3E9C7751-EE97-4820-BFEF-BA5F532A45C9}
+ {7ED37CCB-869D-4FAC-80F5-3A13B2386B1D} = {1BD5D488-707E-4030-8AE8-80D93D04963F}
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB} = {7ED37CCB-869D-4FAC-80F5-3A13B2386B1D}
+ {08D9A49D-736E-4CAD-919E-72CA8C1D4A9F} = {7ED37CCB-869D-4FAC-80F5-3A13B2386B1D}
+ {153CED68-9905-4B1F-9790-F463840895E2} = {7ED37CCB-869D-4FAC-80F5-3A13B2386B1D}
+ {B10240C1-BB07-47A3-B056-CE52B5194D86} = {7ED37CCB-869D-4FAC-80F5-3A13B2386B1D}
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B} = {7ED37CCB-869D-4FAC-80F5-3A13B2386B1D}
+ {D5A4E386-E418-4407-916E-A65092B78693} = {F7CD1D27-1441-4C2F-AB17-6FF8803460EC}
+ {F7CD1D27-1441-4C2F-AB17-6FF8803460EC} = {87A17015-9338-431E-B338-57BDA03984C1}
EndGlobalSection
EndGlobal
diff --git a/Sync.Test.xml b/Sync.Test.xml
index d830280f5..743e7e2c3 100644
--- a/Sync.Test.xml
+++ b/Sync.Test.xml
@@ -35,6 +35,7 @@
+
@@ -116,9 +117,11 @@
+
+
@@ -150,6 +153,7 @@
+
@@ -191,6 +195,7 @@
+
diff --git a/Sync.xml b/Sync.xml
index 793e65bbb..202e753d5 100644
--- a/Sync.xml
+++ b/Sync.xml
@@ -52,6 +52,7 @@
+
@@ -59,7 +60,7 @@
-
+
diff --git a/src/MsgPack.CodeGeneration.CSharp/MsgPack.CodeGeneration.CSharp.csproj b/src/MsgPack.CodeGeneration.CSharp/MsgPack.CodeGeneration.CSharp.csproj
new file mode 100644
index 000000000..81f10ebb7
--- /dev/null
+++ b/src/MsgPack.CodeGeneration.CSharp/MsgPack.CodeGeneration.CSharp.csproj
@@ -0,0 +1,90 @@
+
+
+
+
+ 14.0
+ Debug
+ AnyCPU
+ {B10240C1-BB07-47A3-B056-CE52B5194D86}
+ Library
+ Properties
+ MsgPack
+ MsgPack.CodeGeneration.CSharp
+ ja-JP
+ 512
+ {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+
+
+ v5.0
+
+
+ true
+ full
+ false
+ bin\Debug\
+ TRACE;DEBUG;NETSTANDARD1_3;CSHARP
+ prompt
+ 4
+ bin\Debug\MsgPack.CodeGeneration.CSharp.XML
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE;NETSTANDARD1_3;CSHARP
+ prompt
+ 4
+ bin\Release\MsgPack.CodeGeneration.CSharp.XML
+
+
+ true
+
+
+ ..\MsgPack.snk
+
+
+
+
+ MsgPack.snk
+
+
+
+
+
+ Properties\CommonAssemblyInfo.cs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {efe532ea-77c8-4877-96c2-e79fd101b2ab}
+ MsgPack.CodeGeneration.Core
+
+
+ {08d9a49d-736e-4cad-919e-72ca8c1d4a9f}
+ MsgPack.Core
+
+
+ {153ced68-9905-4b1f-9790-f463840895e2}
+ MsgPack.Serialization
+
+
+
+
+
\ No newline at end of file
diff --git a/src/MsgPack.CodeGeneration.CSharp/Properties/AssemblyInfo.cs b/src/MsgPack.CodeGeneration.CSharp/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..9ad48e5b2
--- /dev/null
+++ b/src/MsgPack.CodeGeneration.CSharp/Properties/AssemblyInfo.cs
@@ -0,0 +1,34 @@
+#region -- License Terms --
+//
+// MessagePack for CLI
+//
+// Copyright (C) 2016 FUJIWARA, Yusuke
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion -- License Terms --
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Security;
+
+[assembly: AssemblyTitle( "MessagePack for CLI(.NET/Mono)" )]
+[assembly: AssemblyDescription( "MessagePack for CLI(.NET/Mono) C# code generator library." )]
+
+[assembly: AssemblyFileVersion( "0.7.2259.1047" )]
+
+#if DEBUG || PERFORMANCE_TEST
+[assembly: InternalsVisibleTo( "MsgPack.UnitTest.CodeTree, PublicKey=0024000004800000940000000602000000240000525341310004000001000100a967de8de9d45380b93a6aa56f64fc2cb2d3c9d4b400e00de01f31ba9e15cf5ca95926dbf8760cce413eabd711e23df0c133193a570da8a3bb1bdc00ef170fccb2bc033266fa5346442c9cf0b071133d5b484845eab17095652aeafeeb71193506b8294d9c8c91e3fd01cc50bdbc2d0eb78dd655bb8cd0bd3cdbbcb192549cb4" )]
+#endif
+
+
diff --git a/src/MsgPack.CodeGeneration.CSharp/Serialization/CodeGenerators/CSharpCodeTreeBasedSerializerCodeGenerator.cs b/src/MsgPack.CodeGeneration.CSharp/Serialization/CodeGenerators/CSharpCodeTreeBasedSerializerCodeGenerator.cs
new file mode 100644
index 000000000..6e8db240d
--- /dev/null
+++ b/src/MsgPack.CodeGeneration.CSharp/Serialization/CodeGenerators/CSharpCodeTreeBasedSerializerCodeGenerator.cs
@@ -0,0 +1,55 @@
+#region -- License Terms --
+//
+// MessagePack for CLI
+//
+// Copyright (C) 2016 FUJIWARA, Yusuke
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion -- License Terms --
+
+using System;
+
+using MsgPack.Serialization.CodeTreeSerializers;
+
+namespace MsgPack.Serialization.CodeGenerators
+{
+ ///
+ /// Provides front-end for Roslyn Code Analyzer based, portable C# serializer source code generator.
+ ///
+ ///
+ /// You must call in advance to use Roslyn Code Analyzer based C# source code generation.
+ /// If you miss it, Code DOM based legacy generator is used in desktop .NET Framework build (including Mono), or failed on other (.NET Core, etc.) based build.
+ ///
+ public static class CSharpCodeTreeBasedSerializerCodeGenerator
+ {
+ // based on in root web.config.
+ private static readonly string[] LanguageIdentifiers =
+ new[] { "C#", "CSharp", "CS" };
+
+ // TODO: VisualBasic are vb;vbs;visualbasic;vbscript
+
+ ///
+ /// Configures C# generator and enables in .
+ ///
+ public static void Configure()
+ {
+ CodeTreeSerializerCodeGeneratorFactory.EnsureInitialized();
+ CodeTreeSerializerCodeGeneratorFactory.RegisterFactory(
+ LanguageIdentifiers,
+ ( context, configuration ) => new CodeTreeContext( context, configuration, "cs" ),
+ context => type => new CSharpCodeTreeSerializerBuilder( type, type.GetCollectionTraits( CollectionTraitOptions.Full, context.CompatibilityOptions.AllowNonCollectionEnumerableTypes ) )
+ );
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/MsgPack.CodeGeneration.CSharp/Serialization/CodeTreeSerializers/CodeTreeConstruct.cs b/src/MsgPack.CodeGeneration.CSharp/Serialization/CodeTreeSerializers/CodeTreeConstruct.cs
new file mode 100644
index 000000000..5080b66f9
--- /dev/null
+++ b/src/MsgPack.CodeGeneration.CSharp/Serialization/CodeTreeSerializers/CodeTreeConstruct.cs
@@ -0,0 +1,85 @@
+#region -- License Terms --
+//
+// MessagePack for CLI
+//
+// Copyright (C) 2016 FUJIWARA, Yusuke
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion -- License Terms --
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+
+#if CSHARP
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+#elif VISUAL_BASIC
+using Microsoft.CodeAnalysis.VisualBasic.Syntax;
+using VariableDeclarationSyntax = Microsoft.CodeAnalysis.VisualBasic.Syntax.LocalDeclarationStatementSyntax;
+#endif
+
+using MsgPack.Serialization.AbstractSerializers;
+
+namespace MsgPack.Serialization.CodeTreeSerializers
+{
+ internal abstract class CodeTreeConstruct : ICodeConstruct
+ {
+ public TypeDefinition ContextType { get; }
+
+ public virtual bool IsExpression => false;
+
+ public virtual bool IsStatement => false;
+
+ protected CodeTreeConstruct( TypeDefinition contextType )
+ {
+ this.ContextType = contextType;
+ }
+
+ public virtual ParameterSyntax AsParameter()
+ {
+ throw new InvalidOperationException(
+ String.Format( CultureInfo.CurrentCulture, "Cannot get '{0}' as parameter declaration.", this )
+ );
+ }
+
+ public virtual ExpressionSyntax AsExpression()
+ {
+ throw new InvalidOperationException(
+ String.Format( CultureInfo.CurrentCulture, "Cannot get '{0}' as expression.", this )
+ );
+ }
+
+ public virtual IEnumerable AsStatements()
+ {
+ throw new InvalidOperationException(
+ String.Format( CultureInfo.CurrentCulture, "Cannot get '{0}' as statements.", this )
+ );
+ }
+
+ public static CodeTreeConstruct Expression( TypeDefinition contextType, ExpressionSyntax expression )
+ => new ExpressionCodeTreeConstruct( contextType, expression );
+
+ public static CodeTreeConstruct Statement( StatementSyntax statement )
+ => new StatementCodeTreeConstruct( new[] { statement } );
+
+ public static CodeTreeConstruct Statement( IEnumerable statements )
+ => new StatementCodeTreeConstruct( statements );
+
+ public static CodeTreeConstruct Variable( TypeDefinition contextType, VariableDeclarationSyntax syntax )
+ => new VariableCodeTreeConstruct( contextType, syntax );
+
+ public static CodeTreeConstruct Parameter( TypeDefinition contextType, IdentifierNameSyntax syntax )
+ => new ParameterCodeTreeConstruct( contextType, syntax );
+ }
+}
\ No newline at end of file
diff --git a/src/MsgPack.CodeGeneration.CSharp/Serialization/CodeTreeSerializers/CodeTreeContext.cs b/src/MsgPack.CodeGeneration.CSharp/Serialization/CodeTreeSerializers/CodeTreeContext.cs
new file mode 100644
index 000000000..dc0eda2c4
--- /dev/null
+++ b/src/MsgPack.CodeGeneration.CSharp/Serialization/CodeTreeSerializers/CodeTreeContext.cs
@@ -0,0 +1,908 @@
+#region -- License Terms --
+//
+// MessagePack for CLI
+//
+// Copyright (C) 2016 FUJIWARA, Yusuke
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion -- License Terms --
+
+using System;
+using System.CodeDom.Compiler;
+using System.Collections.Generic;
+using System.Diagnostics;
+#if NETSTANDARD1_3
+using Contract = MsgPack.MPContract;
+#else
+using System.Diagnostics.Contracts;
+#endif // NETSTANDARD1_3
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+using Microsoft.CodeAnalysis;
+#if CSHARP
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
+using CodeTreeSerializerBuilder = MsgPack.Serialization.CodeTreeSerializers.CSharpCodeTreeSerializerBuilder;
+#elif VISUAL_BASIC
+using Microsoft.CodeAnalysis.VisualBasic;
+using Microsoft.CodeAnalysis.VisualBasic.Syntax;
+using static Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory;
+using CodeTreeSerializerBuilder = MsgPack.Serialization.CodeTreeSerializers.VisualBasicCodeTreeSerializerBuilder;
+#endif
+
+using MsgPack.Serialization.AbstractSerializers;
+using static MsgPack.Serialization.CodeTreeSerializers.Syntax;
+using static MsgPack.Serialization.CodeTreeSerializers.SyntaxCompatibilities;
+
+#if VISUAL_BASIC
+using AttributeArgumentSyntax = Microsoft.CodeAnalysis.VisualBasic.Syntax.ArgumentSyntax;
+using ClassDeclarationSyntax = Microsoft.CodeAnalysis.VisualBasic.Syntax.ClassStatementSyntax;
+using ConstructorDeclarationSyntax = Microsoft.CodeAnalysis.VisualBasic.Syntax.SubNewStatementSyntax;
+using MemberDeclarationSyntax = Microsoft.CodeAnalysis.VisualBasic.Syntax.DeclarationStatementSyntax;
+using TypeDeclarationSyntax = Microsoft.CodeAnalysis.VisualBasic.Syntax.TypeBlockSyntax;
+using UsingDirectiveSyntax = Microsoft.CodeAnalysis.VisualBasic.Syntax.ImportsStatementSyntax;
+#endif // VISUAL_BASIC
+
+#warning Fix Samuel Cragg spreading
+
+namespace MsgPack.Serialization.CodeTreeSerializers
+{
+ internal class CodeTreeContext : SerializerGenerationContext, ISerializerCodeGenerationContext
+ {
+#if VISUAL_BASIC
+
+ private static ModifiedIdentifierSyntax Identifier( string identifier ) => ModifiedIdentifier( identifier );
+
+#endif // VISUAL_BASIC
+
+ private static readonly ParameterSyntax MessagePackObjectParameterSyntax = Parameter( Identifier( "messagePackObject" ) ).WithType( MessagePackObjectTypeSyntax );
+
+ private static readonly ParameterSyntax InitialCapacityParameterSyntax = Parameter( Identifier( "initialCapacity" ) ).WithType( Int32TypeSyntax );
+
+ private static readonly ParameterSyntax CancellationTokenParameterSyntax = Parameter( Identifier( "cancellationToken" ) ).WithType( CancellationTokenTypeSyntax );
+
+ private static readonly SyntaxList KnownUsingDirectives =
+ new SyntaxList().Add(
+ UsingDirective( IdentifierName( "System" ) )
+ ).Add(
+ UsingDirective( IdentifierName( "System.Collections.Generic" ) )
+ ).Add(
+ UsingDirective( IdentifierName( "System.Threading" ) )
+ ).Add(
+ UsingDirective( IdentifierName( "System.Threading.Tasks" ) )
+ ).Add(
+ UsingDirective( IdentifierName( "MsgPack" ) ).WithLeadingTrivia( BlankLine )
+ ).Add(
+ UsingDirective( IdentifierName( "MsgPack.Serialization" ) )
+ );
+
+ private static readonly SyntaxList StandardTypeAttributes =
+ new SyntaxList().Add(
+ AttributeList().AddAttributes(
+ Attribute(
+#if CSHARP
+ IdentifierName( typeof( GeneratedCodeAttribute ).FullName ),
+ AttributeArgumentList(
+#elif VISUAL_BASIC
+ Syntax.ToTypeSyntax( typeof( GeneratedCodeAttribute ) )
+ ).WithArgumentList(
+ ArgumentList(
+#endif
+ new SeparatedSyntaxList().Add(
+ AttributeArgument(
+ LiteralExpression( SyntaxKind.StringLiteralExpression, Literal( typeof( CodeTreeSerializerBuilder ).FullName ) )
+ )
+ ).Add(
+ AttributeArgument(
+ LiteralExpression( SyntaxKind.StringLiteralExpression, Literal( typeof( CodeTreeSerializerBuilder ).GetAssembly().GetName().Version.ToString() ) )
+ )
+ )
+ )
+ )
+ )
+ );
+
+ private static readonly AttributeListSyntax DebuggerNonUserCodeAttributeSyntax =
+ AttributeList().AddAttributes(
+ Attribute(
+ IdentifierName( typeof( DebuggerNonUserCodeAttribute ).FullName )
+ )
+ );
+
+#if CSHARP
+ private static readonly ClassDeclarationSyntax UnpackingContextTypeTemplate =
+ ClassDeclaration( SerializerBuilderHelper.UnpackingContextTypeName );
+#elif VISUAL_BASIC
+ private static readonly ClassBlockSyntax UnpackingContextTypeTemplate =
+ ClassBlock( ClassDeclaration( SerializerBuilderHelper.UnpackingContextTypeName ) );
+#endif
+
+ private static readonly ConstructorDeclarationSyntax UnpackingContextConstructorTemplate =
+ ConstructorDeclaration( SerializerBuilderHelper.UnpackingContextTypeName, PublicKeyword );
+
+ private static readonly CodeTreeConstruct SingletonPacker = CodeTreeConstruct.Parameter( typeof( Packer ), IdentifierName( "packer" ) );
+
+ private static readonly CodeTreeConstruct SingletonUnpacker = CodeTreeConstruct.Parameter( typeof( Unpacker ), IdentifierName( "unpacker" ) );
+
+ private static readonly CodeTreeConstruct SingletonIndexOfItem = CodeTreeConstruct.Parameter( typeof( int ), IdentifierName( "indexOfItem" ) );
+
+ private static readonly CodeTreeConstruct SingletonItemsCount = CodeTreeConstruct.Parameter( typeof( int ), IdentifierName( "itemsCount" ) );
+
+ private static readonly CodeTreeConstruct SingletonInitialCapacity = CodeTreeConstruct.Parameter( typeof( int ), IdentifierName( "initialCapacity" ) );
+
+
+ private readonly Dictionary _dependentSerializers;
+
+ private readonly Dictionary _cachedTargetFields;
+
+ private readonly Dictionary _cachedPropertyAccessors;
+
+ private readonly Dictionary _declaringTypes;
+
+ private readonly SerializerCodeGenerationConfiguration _configuration;
+
+ private readonly string _extension;
+
+ private Type _targetType;
+
+ private bool IsDictionary => this.KeyToAdd != null;
+
+ private ClassDeclarationSyntaxBuilder _buildingType;
+
+ public string DeclaringTypeName => this._buildingType.Identifier.ValueText;
+
+ private readonly Stack _methodContextStack;
+
+ ///
+ /// Gets a value indicating whether the generated serializers will be internal to MsgPack library itself.
+ ///
+ ///
+ /// true if the generated serializers are internal to MsgPack library itself; otherwise, false.
+ ///
+ ///
+ /// When you use MsgPack in Unity3D, you can import the library in source code form to your assets.
+ /// And, you may also import generated serializers together, then the generated serializers and MsgPack library will be same assembly ultimately.
+ /// It causes compilation error because some of overriding members have accessbility FamilyOrAssembly(protected internal in C#),
+ /// so the generated source code must have the accessibility when and only when they will be same assembly as MsgPack library itself.
+ ///
+ public bool IsInternalToMsgPackLibrary => this._configuration.IsInternalToMsgPackLibrary;
+
+ public CodeTreeContext( SerializationContext context, SerializerCodeGenerationConfiguration configuration, string extension )
+ : base( context )
+ {
+ this._configuration = configuration;
+ this._extension = extension;
+ this._methodContextStack = new Stack();
+ this._dependentSerializers = new Dictionary();
+ this._cachedTargetFields =
+ new Dictionary( FieldInfoEqualityComparer.Instance );
+ this._cachedPropertyAccessors =
+ new Dictionary( MethodBaseEqualityComparer.Instance );
+ this._declaringTypes = new Dictionary();
+ }
+
+ public string RegisterSerializer( Type targetType, EnumMemberSerializationMethod enumSerializationMethod, DateTimeMemberConversionMethod dateTimeConversionMethod, PolymorphismSchema polymorphismSchema )
+ {
+ var key = new SerializerFieldKey( targetType, enumSerializationMethod, dateTimeConversionMethod, polymorphismSchema );
+
+ string fieldName;
+ if ( !this._dependentSerializers.TryGetValue( key, out fieldName ) )
+ {
+ fieldName = "_serializer" + this._dependentSerializers.Count.ToString( CultureInfo.InvariantCulture );
+ this._dependentSerializers.Add( key, fieldName );
+ this._buildingType.AddMembers(
+ FieldDeclaration(
+ GenericName(
+ "MessagePackSerializer",
+ ToTypeSyntax( Type.GetTypeFromHandle( key.TypeHandle ) )
+ ),
+ fieldName
+ ).WithModifiers( PrivateReadOnlyKeyword )
+ );
+ }
+
+ return fieldName;
+ }
+
+ public Dictionary GetDependentSerializers()
+ {
+ return this._dependentSerializers;
+ }
+
+ public string RegisterCachedFieldInfo( FieldInfo field )
+ {
+ CachedFieldInfo cachedField;
+ if ( !this._cachedTargetFields.TryGetValue( field, out cachedField ) )
+ {
+ Contract.Assert( field.DeclaringType != null, "field.DeclaringType != null" );
+
+ cachedField =
+ new CachedFieldInfo(
+ field,
+ "_field" + field.DeclaringType?.Name.Replace( '`', '_' ) + "_" + field.Name + this._cachedTargetFields.Count.ToString( CultureInfo.InvariantCulture )
+ );
+ this._cachedTargetFields.Add( field, cachedField );
+ this._buildingType.AddMembers(
+ FieldDeclaration( FieldInfoTypeSyntax, cachedField.StorageFieldName ).WithModifiers( PrivateReadOnlyKeyword )
+ );
+ }
+
+ return cachedField.StorageFieldName;
+ }
+
+ protected override FieldDefinition DeclarePrivateFieldCore( string name, TypeDefinition type )
+ {
+ if ( !this._buildingType.ContainsField( name ) )
+ {
+ this._buildingType.AddMembers(
+ FieldDeclaration( MethodInfoTypeSyntax, name ).WithModifiers( PrivateReadOnlyKeyword )
+ );
+ }
+
+ return new FieldDefinition( null, name, type );
+ }
+
+ public Dictionary GetCachedFieldInfos()
+ {
+ return this._cachedTargetFields;
+ }
+
+ public string RegisterCachedMethodBase( MethodBase method )
+ {
+ CachedMethodBase cachedMethod;
+ if ( !this._cachedPropertyAccessors.TryGetValue( method, out cachedMethod ) )
+ {
+ Contract.Assert( method.DeclaringType != null, "method.DeclaringType != null" );
+
+ cachedMethod =
+ new CachedMethodBase(
+ method,
+ "_methodInfo" + method.DeclaringType?.Name.Replace( '`', '_' ) + "_" + method.Name + this._cachedPropertyAccessors.Count.ToString( CultureInfo.InvariantCulture )
+ );
+ this._cachedPropertyAccessors.Add( method, cachedMethod );
+ this._buildingType.AddMembers(
+ FieldDeclaration( MethodInfoTypeSyntax, cachedMethod.StorageFieldName ).WithModifiers( PrivateReadOnlyKeyword )
+ );
+ }
+
+ return cachedMethod.StorageFieldName;
+ }
+
+ public Dictionary GetCachedMethodBases()
+ {
+ return this._cachedPropertyAccessors;
+ }
+
+ ///
+ /// Gets a unique name of a local variable.
+ ///
+ /// The prefix of the variable.
+ /// A unique name of a local variable.
+ public override string GetUniqueVariableName( string prefix )
+ {
+ var uniqueVariableSuffixes = this._methodContextStack.Peek().UniqueVariableSuffixes;
+ int counter;
+ if ( !uniqueVariableSuffixes.TryGetValue( prefix, out counter ) )
+ {
+ uniqueVariableSuffixes.Add( prefix, 0 );
+ return prefix;
+ }
+
+ uniqueVariableSuffixes[ prefix ] = counter + 1;
+
+ return prefix + counter.ToString( CultureInfo.InvariantCulture );
+ }
+
+ ///
+ /// Resets internal states for new type.
+ ///
+ /// Type of the target.
+ /// Type of base class of the target.
+ protected override void ResetCore( Type targetType, Type baseClass )
+ {
+ var attributes = StandardTypeAttributes;
+
+ if ( !this._configuration.SuppressDebuggerNonUserCodeAttribute )
+ {
+ attributes = attributes.Add( DebuggerNonUserCodeAttributeSyntax );
+ }
+
+ this._targetType = targetType;
+ this._dependentSerializers.Clear();
+ this._cachedTargetFields.Clear();
+ this._cachedPropertyAccessors.Clear();
+
+ this._buildingType =
+ new ClassDeclarationSyntaxBuilder(
+ ClassDeclaration( IdentifierUtility.EscapeTypeName( targetType ) + "Serializer" )
+ .WithAttributeLists( attributes )
+ .WithModifiers( PublicKeyword )
+ ).WithBaseList( baseClass );
+ this._declaringTypes.Add( targetType, this._buildingType );
+
+ this.PackToTarget = CodeTreeConstruct.Parameter( targetType, IdentifierName( "objectTree" ) );
+ this.NullCheckTarget = this.PackToTarget;
+ this.UnpackToTarget = CodeTreeConstruct.Parameter( targetType, IdentifierName( "collection" ) );
+ this.Packer = SingletonPacker;
+ this.Unpacker = SingletonUnpacker;
+ this.IndexOfItem = SingletonIndexOfItem;
+ this.ItemsCount = SingletonItemsCount;
+
+ var traits = targetType.GetCollectionTraits( CollectionTraitOptions.Full, this.SerializationContext.CompatibilityOptions.AllowNonCollectionEnumerableTypes );
+ if ( traits.ElementType != null )
+ {
+ this.CollectionToBeAdded = this.UnpackToTarget;
+ this.ItemToAdd = CodeTreeConstruct.Parameter( traits.ElementType, IdentifierName( "item" ) );
+
+ if ( traits.DetailedCollectionType == CollectionDetailedKind.GenericDictionary
+ || traits.DetailedCollectionType == CollectionDetailedKind.GenericReadOnlyDictionary
+ )
+ {
+ this.KeyToAdd = CodeTreeConstruct.Parameter( traits.ElementType.GetGenericArguments()[ 0 ], IdentifierName( "key" ) );
+ this.ValueToAdd = CodeTreeConstruct.Parameter( traits.ElementType.GetGenericArguments()[ 1 ], IdentifierName( "value" ) );
+ }
+ else
+ {
+ this.KeyToAdd = null;
+ this.ValueToAdd = null;
+ }
+
+ this.InitialCapacity = SingletonInitialCapacity;
+ }
+ }
+
+ public override void BeginMethodOverride( string name )
+ {
+ this._methodContextStack.Push( new MethodContext( name, false, typeof( object ), SerializerBuilderHelper.EmptyParameters ) );
+ }
+
+ public override void BeginPrivateMethod( string name, bool isStatic, TypeDefinition returnType, params CodeTreeConstruct[] parameters )
+ {
+ this._methodContextStack.Push(
+ new MethodContext(
+ name,
+ isStatic,
+ returnType,
+ parameters
+ .Select( p => new KeyValuePair( p.AsParameter().GetIdentifierText(), p.ContextType ) )
+ .ToArray()
+ )
+ );
+ }
+
+ protected override MethodDefinition EndMethodOverrideCore( string name, CodeTreeConstruct body )
+ {
+
+ var context = this._methodContextStack.Pop();
+#if DEBUG
+ Contract.Assert( context.Name == name, "context.Name == name" );
+#endif // DEBUG
+ if ( body == null )
+ {
+ return null;
+ }
+
+ SyntaxTokenList modifiers;
+ TypeSyntax returnType = VoidTypeSyntax;
+
+ var parameters = new SeparatedSyntaxList();
+
+ switch ( name )
+ {
+ case MethodName.PackToCore:
+ {
+ parameters =
+ parameters.Add(
+ this.Packer.AsParameter()
+ ).Add(
+ this.PackToTarget.AsParameter()
+ );
+ modifiers = this.IsInternalToMsgPackLibrary ? ProtectedInternalOverrideKeyword : ProtectedOverrideKeyword;
+ break;
+ }
+ case MethodName.UnpackFromCore:
+ {
+ parameters = parameters.Add( this.Unpacker.AsParameter() );
+ modifiers = this.IsInternalToMsgPackLibrary ? ProtectedInternalOverrideKeyword : ProtectedOverrideKeyword;
+ break;
+ }
+ case MethodName.UnpackToCore:
+ {
+ returnType = ToTypeSyntax( this._targetType );
+ parameters =
+ parameters.Add(
+ this.Unpacker.AsParameter()
+ ).Add(
+ this.UnpackToTarget.AsParameter()
+ );
+ modifiers = this.IsInternalToMsgPackLibrary ? ProtectedInternalOverrideKeyword : ProtectedOverrideKeyword;
+ break;
+ }
+ case MethodName.PackUnderlyingValueTo:
+ {
+ parameters =
+ parameters.Add(
+ this.Packer.AsParameter()
+ ).Add(
+ Parameter( Identifier( "enumValue" ) ).WithType( ToTypeSyntax( this._targetType ) )
+ );
+ modifiers = this.IsInternalToMsgPackLibrary ? ProtectedInternalOverrideKeyword : ProtectedOverrideKeyword;
+ break;
+ }
+ case MethodName.UnpackFromUnderlyingValue:
+ {
+ returnType = ToTypeSyntax( this._targetType );
+ parameters = parameters.Add( MessagePackObjectParameterSyntax );
+ modifiers = this.IsInternalToMsgPackLibrary ? ProtectedInternalOverrideKeyword : ProtectedOverrideKeyword;
+
+ break;
+ }
+ case MethodName.AddItem:
+ {
+ parameters =
+ parameters.Add(
+ Parameter( Identifier( "collection" ) ).WithType( ToTypeSyntax( this._targetType ) )
+ );
+ if ( this.IsDictionary )
+ {
+ parameters =
+ parameters.Add(
+ Parameter( Identifier( "key" ) ).WithType( ToTypeSyntax( this.KeyToAdd.ContextType ) )
+ ).Add(
+ Parameter( Identifier( "value" ) ).WithType( ToTypeSyntax( this.ValueToAdd.ContextType ) )
+ );
+ }
+ else
+ {
+ parameters =
+ parameters.Add(
+ Parameter( Identifier( "item" ) ).WithType( ToTypeSyntax( this.ItemToAdd.ContextType ) )
+ );
+ }
+
+ modifiers = ProtectedOverrideKeyword;
+ break;
+ }
+ case MethodName.CreateInstance:
+ {
+ returnType = ToTypeSyntax( this._targetType );
+ parameters = parameters.Add( InitialCapacityParameterSyntax );
+ modifiers = ProtectedOverrideKeyword;
+ break;
+ }
+ case MethodName.PackToAsyncCore:
+ {
+ returnType = TaskTypeSyntax;
+ parameters =
+ parameters.Add(
+ this.Packer.AsParameter()
+ ).Add(
+ this.PackToTarget.AsParameter()
+ ).Add(
+ CancellationTokenParameterSyntax
+ );
+ modifiers = this.IsInternalToMsgPackLibrary ? ProtectedInternalOverrideKeyword : ProtectedOverrideKeyword;
+ break;
+ }
+ case MethodName.UnpackFromAsyncCore:
+ {
+ returnType =
+ GenericName(
+ typeof( Task ).Name,
+ ToTypeSyntax( this._targetType )
+ );
+ parameters =
+ parameters.Add(
+ this.Unpacker.AsParameter()
+ ).Add(
+ CancellationTokenParameterSyntax
+ );
+ modifiers = this.IsInternalToMsgPackLibrary ? ProtectedInternalOverrideKeyword : ProtectedOverrideKeyword;
+ break;
+ }
+ case MethodName.UnpackToAsyncCore:
+ {
+ returnType = TaskTypeSyntax;
+ parameters =
+ parameters.Add(
+ this.Unpacker.AsParameter()
+ ).Add(
+ this.UnpackToTarget.AsParameter()
+ ).Add(
+ CancellationTokenParameterSyntax
+ );
+ modifiers = this.IsInternalToMsgPackLibrary ? ProtectedInternalOverrideKeyword : ProtectedOverrideKeyword;
+ break;
+ }
+ case MethodName.PackUnderlyingValueToAsync:
+ {
+ returnType = TaskTypeSyntax;
+ parameters =
+ parameters.Add(
+ this.Packer.AsParameter()
+ ).Add(
+ Parameter( Identifier( "enumValue" ) ).WithType( ToTypeSyntax( this._targetType ) )
+ ).Add(
+ CancellationTokenParameterSyntax
+ );
+ modifiers = this.IsInternalToMsgPackLibrary ? ProtectedInternalOverrideKeyword : ProtectedOverrideKeyword;
+ break;
+ }
+ default:
+ {
+ throw new ArgumentOutOfRangeException( nameof( name ), name );
+ }
+ }
+
+ this._buildingType.AddMembers(
+ MethodDeclaration( returnType, name )
+ .WithModifiers( modifiers )
+ .WithParameterList( ParameterList( parameters ) )
+ .WithBody( Block( body.AsStatements() ) )
+ );
+
+ return
+ new MethodDefinition(
+ context.Name,
+ null,
+ null,
+ context.IsStatic,
+ context.ReturnType,
+ context.Parameters.Select( kv => kv.Value ).ToArray()
+ );
+ }
+
+ protected override MethodDefinition EndPrivateMethodCore( string name, CodeTreeConstruct body )
+ {
+ var context = this._methodContextStack.Pop();
+#if DEBUG
+ Contract.Assert( context.Name == name, "context.Name == name" );
+#endif // DEBUG
+ if ( body == null )
+ {
+ return null;
+ }
+
+ this._buildingType.AddMembers(
+ MethodDeclaration(
+ context.ReturnType.TryGetRuntimeType() != typeof( void )
+ ? ToTypeSyntax( context.ReturnType )
+ : VoidTypeSyntax,
+ context.Name
+ ).WithModifiers(
+ context.IsStatic ? PrivateStaticKeyword : PrivateInstanceKeyword
+ ).WithParameterList(
+ ParameterList(
+ new SeparatedSyntaxList().AddRange(
+ context.Parameters.Select( kv =>
+ Parameter( Identifier( kv.Key ) ).WithType( ToTypeSyntax( kv.Value ) )
+ )
+ )
+ )
+ ).WithBody( Block( body.AsStatements() ) )
+ );
+
+ return
+ new MethodDefinition(
+ context.Name,
+ null,
+ null,
+ context.IsStatic,
+ context.ReturnType,
+ context.Parameters.Select( kv => kv.Value ).ToArray()
+ );
+ }
+
+ // For stack
+ public void BeginConstructor()
+ {
+ this._methodContextStack.Push( new MethodContext( ".ctor", false, typeof( object ), SerializerBuilderHelper.EmptyParameters ) );
+ }
+
+ public void EndConstructor()
+ {
+ this._methodContextStack.Pop();
+ }
+
+ public void AddMember( MemberDeclarationSyntax member )
+ {
+ this._buildingType.AddMembers( member );
+ }
+
+ protected override void DefineUnpackingContextCore(
+ IList> fields,
+ out TypeDefinition type,
+ out ConstructorDefinition constructor,
+ out CodeTreeConstruct parameterInUnpackValueMethods,
+ out CodeTreeConstruct parameterInSetValueMethods,
+ out CodeTreeConstruct parameterInCreateObjectFromContext
+ )
+ {
+ var fieldDeclarations = new SyntaxList();
+ var parameters = new SeparatedSyntaxList();
+ var statements = new SyntaxList();
+ foreach ( var kv in fields )
+ {
+ var fieldTypeSyntax = ToTypeSyntax( kv.Value );
+ fieldDeclarations =
+ fieldDeclarations.Add(
+ FieldDeclaration( fieldTypeSyntax, kv.Key ).WithModifiers( PublicKeyword )
+ );
+
+ parameters =
+ parameters.Add(
+ Parameter( Identifier( kv.Key ) ).WithType( fieldTypeSyntax )
+ );
+
+ statements =
+ statements.Add(
+ SimpleAssignmentStatement(
+ SimpleMemberAccessExpression(
+ ThisExpression(),
+ IdentifierName( kv.Key )
+ ),
+ IdentifierName( kv.Key )
+ )
+ );
+ }
+
+ this._buildingType
+ .WithMembers( fieldDeclarations )
+ .AddMembers(
+ UnpackingContextTypeTemplate
+ .AddMembers(
+ UnpackingContextConstructorTemplate
+ .WithParameterList( ParameterList( parameters ) )
+ .WithBody( Block( statements ) )
+ )
+ );
+ type = TypeDefinition.Object( SerializerBuilderHelper.UnpackingContextTypeName );
+ constructor = new ConstructorDefinition( type, fields.Select( kv => kv.Value ).ToArray() );
+ DefineUnpackValueMethodArguments( type, out parameterInUnpackValueMethods, out parameterInSetValueMethods, out parameterInCreateObjectFromContext );
+ }
+
+ protected override void DefineUnpackingContextWithResultObjectCore(
+ out TypeDefinition type,
+ out CodeTreeConstruct parameterInUnpackValueMethods,
+ out CodeTreeConstruct parameterInSetValueMethods,
+ out CodeTreeConstruct parameterInCreateObjectFromContext
+ )
+ {
+ type = TypeDefinition.Object( this._targetType );
+ DefineUnpackValueMethodArguments( type, out parameterInUnpackValueMethods, out parameterInSetValueMethods, out parameterInCreateObjectFromContext );
+ }
+
+ private static void DefineUnpackValueMethodArguments( TypeDefinition type, out CodeTreeConstruct parameterInUnpackValueMethods, out CodeTreeConstruct parameterInSetValueMethods, out CodeTreeConstruct parameterInCreateObjectFromContext )
+ {
+ parameterInUnpackValueMethods = CodeTreeConstruct.Parameter( type, IdentifierName( "unpackingContext" ) );
+ parameterInSetValueMethods = CodeTreeConstruct.Parameter( type, IdentifierName( "unpackingContext" ) );
+ parameterInCreateObjectFromContext = CodeTreeConstruct.Parameter( type, IdentifierName( "unpackingContext" ) );
+ }
+
+ public override CodeTreeConstruct DefineUnpackedItemParameterInSetValueMethods( TypeDefinition itemType )
+ {
+ return CodeTreeConstruct.Parameter( itemType, IdentifierName( "unpackedValue" ) );
+ }
+
+ public IEnumerable Generate()
+ {
+#warning TODO: indentation
+
+ var directory =
+ Path.Combine(
+ this._configuration.OutputDirectory,
+ this._configuration.Namespace.Replace( ReflectionAbstractions.TypeDelimiter, Path.DirectorySeparatorChar )
+ );
+ Directory.CreateDirectory( directory );
+
+ var result = new List( this._declaringTypes.Count );
+
+ foreach ( var kv in this._declaringTypes )
+ {
+ var declaringType = kv.Value.Build();
+ var declaringTypeIdentifier =
+#if CSHARP
+ declaringType.Identifier;
+#elif VISUAL_BASIC
+ declaringType.ClassStatement.Identifier;
+#endif
+ var typeFileName = declaringTypeIdentifier.ValueText;
+ var genericArity =
+#if CSHARP
+ declaringType.TypeParameterList?.Parameters.Count;
+#elif VISUAL_BASIC
+ declaringType.ClassStatement.TypeParameterList?.Parameters.Count;
+#endif
+ if ( genericArity != null )
+ {
+ typeFileName += "`" + genericArity.Value.ToString( "D", CultureInfo.InvariantCulture );
+ }
+
+ typeFileName += "." + this._extension;
+
+ var compilationUnit = this.CreateCompilationUnit( declaringType );
+ var filePath = Path.Combine( directory, typeFileName );
+ result.Add(
+ new SerializerCodeGenerationResult(
+ kv.Key,
+ filePath,
+ String.IsNullOrEmpty( this._configuration.Namespace )
+ ? declaringTypeIdentifier.ValueText
+ : this._configuration.Namespace + "." + declaringTypeIdentifier.ValueText,
+ this._configuration.Namespace,
+ declaringTypeIdentifier.ValueText
+ )
+ );
+
+ using ( var fileStream = new FileStream( filePath, FileMode.Create, FileAccess.Write, FileShare.Read ) )
+ using ( var writer = new StreamWriter( fileStream, Encoding.UTF8 ) )
+ {
+ compilationUnit.WriteTo( writer );
+ }
+ }
+
+ return result;
+ }
+
+ private CompilationUnitSyntax CreateCompilationUnit( TypeDeclarationSyntax targetType )
+ => CompilationUnit()
+ .WithUsings( KnownUsingDirectives )
+ .AddMembers(
+ NamespaceDeclaration(
+ IdentifierName( this._configuration.Namespace )
+ ).WithLeadingTrivia( BlankLine )
+ .WithMembers(
+#if CSHARP
+ new SyntaxList()
+#elif VISUAL_BASIC
+ new SyntaxList()
+#endif
+ .Add(
+ targetType
+ )
+ )
+ );
+
+ public CompilationUnitSyntax CreateCompilationUnit()
+ => this.CreateCompilationUnit( this._buildingType.Build() );
+
+ public struct CachedFieldInfo
+ {
+ public readonly string StorageFieldName;
+ public readonly FieldInfo Target;
+
+ public CachedFieldInfo( FieldInfo target, string storageFieldName )
+ {
+ this.Target = target;
+ this.StorageFieldName = storageFieldName;
+ }
+ }
+
+ public struct CachedMethodBase
+ {
+ public readonly string StorageFieldName;
+ public readonly MethodBase Target;
+
+ public CachedMethodBase( MethodBase target, string storageFieldName )
+ {
+ this.Target = target;
+ this.StorageFieldName = storageFieldName;
+ }
+ }
+
+ private sealed class MethodContext
+ {
+ public readonly IDictionary UniqueVariableSuffixes;
+
+ public readonly string Name;
+
+ public readonly bool IsStatic;
+
+ public readonly TypeDefinition ReturnType;
+
+ public readonly KeyValuePair[] Parameters;
+
+ public MethodContext( string name, bool isStatic, TypeDefinition returnType, KeyValuePair[] parameters )
+ {
+ this.Name = name;
+ this.IsStatic = isStatic;
+ this.ReturnType = returnType;
+ this.Parameters = parameters;
+ this.UniqueVariableSuffixes = new Dictionary();
+ }
+ }
+
+ private sealed class ClassDeclarationSyntaxBuilder
+ {
+#if CSHARP
+ private ClassDeclarationSyntax _syntax;
+
+ public SyntaxToken Identifier => this._syntax.Identifier;
+
+#elif VISUAL_BASIC
+
+ private ClassBlockSyntax _syntax;
+
+ public SyntaxToken Identifier => this._syntax.ClassStatement.Identifier;
+
+#endif
+
+ public ClassDeclarationSyntaxBuilder( ClassDeclarationSyntax syntax )
+ {
+#if CSHARP
+ this._syntax = syntax;
+#elif VISUAL_BASIC
+ this._syntax = ClassBlock( syntax );
+#endif
+ }
+
+ public ClassDeclarationSyntaxBuilder WithBaseList( TypeDefinition baseClass )
+ {
+ this._syntax =
+#if CSHARP
+ this._syntax.WithBaseList(
+ BaseList(
+ new SeparatedSyntaxList().Add(
+ SimpleBaseType( ToTypeSyntax( baseClass ) )
+ )
+ )
+ );
+#elif VISUAL_BASIC
+ this._syntax.AddInherits(
+ InheritsStatement( ToTypeSyntax( baseClass ) )
+ );
+#endif
+ return this;
+ }
+
+ public ClassDeclarationSyntaxBuilder WithMembers( SyntaxList members )
+ {
+#if CSHARP
+ this._syntax = this._syntax.WithMembers( members );
+#elif VISUAL_BASIC
+ this._syntax = this._syntax.WithMembers( new SyntaxList().AddRange( members ) );
+#endif
+ return this;
+ }
+
+ // ReSharper disable once UnusedMethodReturnValue.Local
+ public ClassDeclarationSyntaxBuilder AddMembers( params MemberDeclarationSyntax[] items )
+ {
+ this._syntax = this._syntax.AddMembers( items );
+ return this;
+ }
+
+ public bool ContainsField( string name )
+ => this._syntax.Members.OfType()
+#if CSHARP
+ .Any( x => x.Declaration.Variables.Any( v => v.Identifier.ValueText == name ) );
+#elif VISUAL_BASIC
+ .Any( x => x.Declarators.Any( d => d.Names.Any( n => n.Identifier.ValueText == name ) ) );
+#endif
+
+#if CSHARP
+ public ClassDeclarationSyntax Build() => this._syntax;
+#elif VISUAL_BASIC
+ public ClassBlockSyntax Build() => this._syntax;
+#endif
+ }
+ }
+}
+
diff --git a/src/MsgPack.CodeGeneration.CSharp/Serialization/CodeTreeSerializers/CodeTreeSerializerBuilder.cs b/src/MsgPack.CodeGeneration.CSharp/Serialization/CodeTreeSerializers/CodeTreeSerializerBuilder.cs
new file mode 100644
index 000000000..05065ce2d
--- /dev/null
+++ b/src/MsgPack.CodeGeneration.CSharp/Serialization/CodeTreeSerializers/CodeTreeSerializerBuilder.cs
@@ -0,0 +1,1709 @@
+#region -- License Terms --
+//
+// MessagePack for CLI
+//
+// Copyright (C) 2016 FUJIWARA, Yusuke
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion -- License Terms --
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+#if NETSTANDARD1_3
+using Contract = MsgPack.MPContract;
+#else
+using System.Diagnostics.Contracts;
+#endif // NETSTANDARD1_3
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Threading;
+using System.Threading.Tasks;
+
+using Microsoft.CodeAnalysis;
+
+using MsgPack.Serialization.AbstractSerializers;
+using MsgPack.Serialization.CollectionSerializers;
+using static MsgPack.Serialization.CodeTreeSerializers.Syntax;
+using static MsgPack.Serialization.CodeTreeSerializers.SyntaxCompatibilities;
+
+#if CSHARP
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
+using CompilationFactory = Microsoft.CodeAnalysis.CSharp.CSharpCompilation;
+using CompilationOptionsImpl = Microsoft.CodeAnalysis.CSharp.CSharpCompilationOptions;
+#elif VISUAL_BASIC
+using Microsoft.CodeAnalysis.VisualBasic;
+using Microsoft.CodeAnalysis.VisualBasic.Syntax;
+using static Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory;
+using CatchClauseSyntax = Microsoft.CodeAnalysis.VisualBasic.Syntax.CatchBlockSyntax;
+using CompilationFactory = Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation;
+using CompilationOptionsImpl = Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilationOptions;
+using ConstructorInitializerSyntax = Microsoft.CodeAnalysis.VisualBasic.Syntax.ExpressionStatementSyntax;
+using NamespaceDeclarationSyntax = Microsoft.CodeAnalysis.VisualBasic.Syntax.NamespaceBlockSyntax;
+#endif
+
+namespace MsgPack.Serialization.CodeTreeSerializers
+{
+#if CSHARP
+ internal sealed class CSharpCodeTreeSerializerBuilder :
+#elif VISUAL_BASIC
+ internal sealed class VisualBasicCodeTreeSerializerBuilder :
+#endif
+ SerializerBuilder,
+ ISerializerCodeGenerator
+ {
+#if CSHARP
+ private const string Extension = "cs";
+#elif VISUAL_BASIC
+ private const string Extension = "vb";
+#endif
+
+#if VISUAL_BASIC
+
+ private static ModifiedIdentifierSyntax Identifier( string identifier ) => ModifiedIdentifier( identifier );
+
+#endif // VISUAL_BASIC
+
+ private static readonly int ProcessId = GetCurrentProcessId();
+
+ private static int GetCurrentProcessId()
+ {
+ using ( var process = Process.GetCurrentProcess() )
+ {
+ return process.Id;
+ }
+ }
+
+ private static readonly ParameterSyntax ContextParameterSyntax =
+ Parameter( Identifier( "context" ) )
+ .WithType( SerializationContextTypeSyntax );
+
+ private static readonly ParameterListSyntax ContextParameterListSyntax =
+ ParameterList(
+ new SeparatedSyntaxList().Add(
+ ContextParameterSyntax
+ )
+ );
+
+ private static readonly SimpleNameSyntax ContextArgumentReferenceSyntax = IdentifierName( "context" );
+
+ private static readonly ArgumentSyntax ContextArgumentSyntax = Argument( ContextArgumentReferenceSyntax );
+
+ private static readonly SeparatedSyntaxList ContextArgumentListTemplate =
+ new SeparatedSyntaxList().Add( ContextArgumentSyntax );
+
+ private static readonly ParameterListSyntax ContextAndEnumSerializationMethodParameterListSyntax =
+ ContextParameterListSyntax.AddParameters(
+ Parameter( Identifier( "enumSerializationMethod" ) )
+ .WithType( ToTypeSyntax( typeof( EnumSerializationMethod ) ) )
+ );
+
+ private static readonly ConstructorInitializerSyntax ContextAndEnumSerializationMethodConstructorInitializerSyntax =
+ BaseConstructorInitializer(
+ ArgumentList(
+ // ReSharper disable once ImpureMethodCallOnReadonlyValueField
+ ContextArgumentListTemplate.Add(
+ Argument(
+ IdentifierName( "enumSerializationMethod" )
+ )
+ )
+ )
+ );
+
+ private static readonly SimpleNameSyntax EnumSerializationMethodTypeIdentifierSyntax = IdentifierName( typeof( EnumSerializationMethod ).FullName );
+
+ private static readonly SimpleNameSyntax RestoreSchemaMethodIdentifierSyntax = IdentifierName( MethodName.RestoreSchema );
+
+ private static readonly SimpleNameSyntax SerializerCapabilitiesTypeIdentifierSyntax = IdentifierName( typeof( SerializerCapabilities ).FullName );
+
+ private static readonly ExpressionSyntax SerializerCapabilitiesNoneSyntax =
+ SimpleMemberAccessExpression(
+ SerializerCapabilitiesTypeIdentifierSyntax,
+ IdentifierName( "None" )
+ );
+
+ private static readonly InvocationExpressionSyntax EnumMessagePackSerializerHelpersDetermineEnumSerializationMethodMethodTemplate =
+ InvocationExpression(
+ SimpleMemberAccessExpression(
+ ToTypeSyntax( typeof( EnumMessagePackSerializerHelpers ) ),
+ IdentifierName( nameof( EnumMessagePackSerializerHelpers.DetermineEnumSerializationMethod ) )
+ )
+ );
+
+ private static readonly InvocationExpressionSyntax DateTimeMessagePackSerializerHelpersDetermineDateTimeConversionMethodTemplate =
+ InvocationExpression(
+ SimpleMemberAccessExpression(
+ ToTypeSyntax( typeof( DateTimeMessagePackSerializerHelpers ) ),
+ IdentifierName( nameof( DateTimeMessagePackSerializerHelpers.DetermineDateTimeConversionMethod ) )
+ )
+ );
+
+ private static readonly SimpleNameSyntax DateTimeMemberConversionMethodIdentifierSyntax = IdentifierName( typeof( DateTimeMemberConversionMethod ).FullName );
+
+ private static readonly InvocationExpressionSyntax ReflectionHelpersGetFieldMethodTemplate =
+ InvocationExpression(
+ SimpleMemberAccessExpression(
+ ToTypeSyntax( typeof( ReflectionHelpers ) ),
+ IdentifierName( nameof( ReflectionHelpers.GetField ) )
+ )
+ );
+
+ private static readonly InvocationExpressionSyntax ReflectionHelpersGetMethodMethodTemplate =
+ InvocationExpression(
+ SimpleMemberAccessExpression(
+ ToTypeSyntax( typeof( ReflectionHelpers ) ),
+ IdentifierName( nameof( ReflectionHelpers.GetMethod ) )
+ )
+ );
+
+#if CSHARP
+
+ private static readonly ArrayCreationExpressionSyntax TypeArrayCreationTemplate =
+ ArrayCreationExpression( ArrayType( ToTypeSyntax( TypeDefinition.TypeType ) ) );
+
+ private static ArrayCreationExpressionSyntax TypeArrayCreation( IEnumerable typeExpresions ) =>
+ TypeArrayCreationTemplate.WithInitializer(
+ InitializerExpression(
+ SyntaxKind.ArrayInitializerExpression,
+ new SeparatedSyntaxList().AddRange( typeExpresions )
+ )
+ );
+
+#elif VISUAL_BASIC
+
+ private static readonly ArrayCreationExpressionSyntax TypeArrayCreationTemplate =
+ ArrayCreationExpression( ToTypeSyntax( TypeDefinition.TypeType ), CollectionInitializer() );
+
+ private static ArrayCreationExpressionSyntax TypeArrayCreation( IEnumerable typeExpressions ) =>
+ TypeArrayCreationTemplate.AddInitializerInitializers( typeExpressions.ToArray() );
+
+#endif
+
+ private static readonly SyntaxList EmptyCatches = new SyntaxList();
+
+
+ private readonly TypeDefinition _thisType;
+
+#if CSHARP
+ public CSharpCodeTreeSerializerBuilder(
+#elif VISUAL_BASIC
+ public VisualBasicCodeTreeSerializerBuilder(
+#endif
+ Type targetType,
+ CollectionTraits collectionTraits
+ )
+ : base( targetType, collectionTraits )
+ {
+ this._thisType = typeof( MessagePackSerializer<> ).MakeGenericType( this.TargetType );
+ }
+
+ protected override CodeTreeConstruct MakeNullLiteral( CodeTreeContext context, TypeDefinition contextType )
+ => CodeTreeConstruct.Expression( contextType, NullLiteralSyntax );
+
+ private static CodeTreeConstruct MakeTinyNumberLiteral( TypeDefinition contextType, int value )
+ => CodeTreeConstruct.Expression(
+ contextType,
+ CastExpression(
+ ToTypeSyntax( contextType ),
+ LiteralExpression( SyntaxKind.NumericLiteralExpression, Literal( value ) )
+ )
+ );
+
+ protected override CodeTreeConstruct MakeByteLiteral( CodeTreeContext context, byte constant )
+ => MakeTinyNumberLiteral( TypeDefinition.ByteType, constant );
+
+ protected override CodeTreeConstruct MakeSByteLiteral( CodeTreeContext context, sbyte constant )
+ => MakeTinyNumberLiteral( TypeDefinition.SByteType, constant );
+
+ protected override CodeTreeConstruct MakeInt16Literal( CodeTreeContext context, short constant )
+ => MakeTinyNumberLiteral( TypeDefinition.Int16Type, constant );
+
+ protected override CodeTreeConstruct MakeUInt16Literal( CodeTreeContext context, ushort constant )
+ => MakeTinyNumberLiteral( TypeDefinition.UInt16Type, constant );
+
+ protected override CodeTreeConstruct MakeInt32Literal( CodeTreeContext context, int constant )
+ => CodeTreeConstruct.Expression( TypeDefinition.Int32Type, LiteralExpression( SyntaxKind.NumericLiteralExpression, Literal( constant ) ) );
+
+ protected override CodeTreeConstruct MakeUInt32Literal( CodeTreeContext context, uint constant )
+ => CodeTreeConstruct.Expression( TypeDefinition.UInt32Type, LiteralExpression( SyntaxKind.NumericLiteralExpression, Literal( constant ) ) );
+
+ protected override CodeTreeConstruct MakeInt64Literal( CodeTreeContext context, long constant )
+ => CodeTreeConstruct.Expression( TypeDefinition.Int64Type, LiteralExpression( SyntaxKind.NumericLiteralExpression, Literal( constant ) ) );
+
+ protected override CodeTreeConstruct MakeUInt64Literal( CodeTreeContext context, ulong constant )
+ => CodeTreeConstruct.Expression( TypeDefinition.UInt64Type, LiteralExpression( SyntaxKind.NumericLiteralExpression, Literal( constant ) ) );
+
+ protected override CodeTreeConstruct MakeReal32Literal( CodeTreeContext context, float constant )
+ => CodeTreeConstruct.Expression( TypeDefinition.SingleType, LiteralExpression( SyntaxKind.NumericLiteralExpression, Literal( constant ) ) );
+
+ protected override CodeTreeConstruct MakeReal64Literal( CodeTreeContext context, double constant )
+ => CodeTreeConstruct.Expression( TypeDefinition.DoubleType, LiteralExpression( SyntaxKind.NumericLiteralExpression, Literal( constant ) ) );
+
+ protected override CodeTreeConstruct MakeBooleanLiteral( CodeTreeContext context, bool constant )
+#if CSHARP
+ => CodeTreeConstruct.Expression( TypeDefinition.BooleanType, LiteralExpression( constant ? SyntaxKind.TrueLiteralExpression : SyntaxKind.FalseLiteralExpression ) );
+#elif VISUAL_BASIC
+ => CodeTreeConstruct.Expression( TypeDefinition.BooleanType, constant ? TrueLiteralExpression( Token( SyntaxKind.TrueKeyword ) ) : FalseLiteralExpression( Token( SyntaxKind.FalseKeyword ) ) );
+#endif
+
+ protected override CodeTreeConstruct MakeCharLiteral( CodeTreeContext context, char constant )
+ => CodeTreeConstruct.Expression( TypeDefinition.CharType, LiteralExpression( SyntaxKind.CharacterLiteralExpression, Literal( constant ) ) );
+
+ protected override CodeTreeConstruct MakeStringLiteral( CodeTreeContext context, string constant )
+ => CodeTreeConstruct.Expression( TypeDefinition.StringType, LiteralExpression( SyntaxKind.StringLiteralExpression, Literal( constant ) ) );
+
+ protected override CodeTreeConstruct MakeEnumLiteral( CodeTreeContext context, TypeDefinition type, object constant )
+ {
+ var asString = constant.ToString();
+ if ( ( '0' <= asString[ 0 ] && asString[ 0 ] <= '9' ) || asString.Contains( ',' ) )
+ {
+ // Unrepresentable numeric or combined flags
+ return
+ CodeTreeConstruct.Expression(
+ type,
+ CastExpression(
+ ToTypeSyntax( type ),
+ // Only support integrals.
+ LiteralExpression(
+ SyntaxKind.NumericLiteralExpression,
+ Literal( UInt64.Parse( ( ( Enum )constant ).ToString( "D" ), CultureInfo.InvariantCulture ) )
+ )
+ )
+ );
+ }
+ else
+ {
+ return
+ CodeTreeConstruct.Expression(
+ type,
+ MemberAccessExpression(
+ SyntaxKind.SimpleMemberAccessExpression,
+ IdentifierName( type.TypeName ),
+ Token( SyntaxKind.DotToken ),
+ IdentifierName( asString )
+ )
+ );
+ }
+ }
+
+ protected override CodeTreeConstruct MakeDefaultLiteral( CodeTreeContext context, TypeDefinition type )
+#if CSHARP
+ => CodeTreeConstruct.Expression( type, DefaultExpression( ToTypeSyntax( type ) ) );
+#elif VISUAL_BASIC
+ => CodeTreeConstruct.Expression( type, NothingLiteralExpression( Token( SyntaxKind.NothingKeyword ) ) );
+#endif
+
+ protected override CodeTreeConstruct EmitThisReferenceExpression( CodeTreeContext context )
+ => CodeTreeConstruct.Expression( this._thisType, ThisExpression() );
+
+ protected override CodeTreeConstruct EmitBoxExpression( CodeTreeContext context, TypeDefinition valueType, CodeTreeConstruct value )
+ => CodeTreeConstruct.Expression( TypeDefinition.ObjectType, CastExpression( ObjectTypeSyntax, value.AsExpression() ) );
+
+ protected override CodeTreeConstruct EmitUnboxAnyExpression( CodeTreeContext context, TypeDefinition targetType, CodeTreeConstruct value )
+ => CodeTreeConstruct.Expression( targetType, CastExpression( ToTypeSyntax( targetType ), value.AsExpression() ) );
+
+ protected override CodeTreeConstruct EmitNotExpression( CodeTreeContext context, CodeTreeConstruct booleanExpression )
+#if CSHARP
+ => CodeTreeConstruct.Expression( TypeDefinition.BooleanType, PrefixUnaryExpression( SyntaxKind.LogicalNotExpression, booleanExpression.AsExpression() ) );
+#elif VISUAL_BASIC
+ => CodeTreeConstruct.Expression( TypeDefinition.BooleanType, NotExpression( booleanExpression.AsExpression() ) );
+#endif
+
+ protected override CodeTreeConstruct EmitEqualsExpression( CodeTreeContext context, CodeTreeConstruct left, CodeTreeConstruct right )
+#if CSHARP
+ => CodeTreeConstruct.Expression( TypeDefinition.BooleanType, BinaryExpression( SyntaxKind.EqualsExpression, left.AsExpression(), right.AsExpression() ) );
+#elif VISUAL_BASIC
+ => CodeTreeConstruct.Expression( TypeDefinition.BooleanType, EqualsExpression( left.AsExpression(), right.AsExpression() ) );
+#endif
+
+ protected override CodeTreeConstruct EmitGreaterThanExpression( CodeTreeContext context, CodeTreeConstruct left, CodeTreeConstruct right )
+#if CSHARP
+ => CodeTreeConstruct.Expression( TypeDefinition.BooleanType, BinaryExpression( SyntaxKind.GreaterThanExpression, left.AsExpression(), right.AsExpression() ) );
+#elif VISUAL_BASIC
+ => CodeTreeConstruct.Expression( TypeDefinition.BooleanType, GreaterThanExpression( left.AsExpression(), right.AsExpression() ) );
+#endif
+
+ protected override CodeTreeConstruct EmitLessThanExpression( CodeTreeContext context, CodeTreeConstruct left, CodeTreeConstruct right )
+#if CSHARP
+ => CodeTreeConstruct.Expression( TypeDefinition.BooleanType, BinaryExpression( SyntaxKind.LessThanExpression, left.AsExpression(), right.AsExpression() ) );
+#elif VISUAL_BASIC
+ => CodeTreeConstruct.Expression( TypeDefinition.BooleanType, LessThanExpression( left.AsExpression(), right.AsExpression() ) );
+#endif
+
+ protected override CodeTreeConstruct EmitIncrement( CodeTreeContext context, CodeTreeConstruct int32Value )
+#if CSHARP
+ => CodeTreeConstruct.Expression( TypeDefinition.Int32Type, PostfixUnaryExpression( SyntaxKind.PostIncrementExpression, int32Value.AsExpression() ) );
+#elif VISUAL_BASIC
+ => CodeTreeConstruct.Statement( AddAssignmentStatement( int32Value.AsExpression(), NumericLiteralExpression( Literal( 1 ) ) ) );
+#endif
+
+ protected override CodeTreeConstruct EmitTypeOfExpression( CodeTreeContext context, TypeDefinition type )
+ => CodeTreeConstruct.Expression( TypeDefinition.TypeType, TypeOfExpression( ToTypeSyntax( type ) ) );
+
+ protected override CodeTreeConstruct EmitMethodOfExpression( CodeTreeContext context, MethodBase method )
+ => CodeTreeConstruct.Expression(
+ TypeDefinition.MethodBaseType,
+ MemberAccessExpression(
+ SyntaxKind.SimpleMemberAccessExpression,
+ ThisExpression(),
+ Token( SyntaxKind.DotToken ),
+ IdentifierName(
+ context.RegisterCachedMethodBase(
+ method
+ )
+ )
+ )
+ );
+
+ protected override CodeTreeConstruct EmitFieldOfExpression( CodeTreeContext context, FieldInfo field )
+ => CodeTreeConstruct.Expression(
+ TypeDefinition.FieldInfoType,
+ MemberAccessExpression(
+ SyntaxKind.SimpleMemberAccessExpression,
+ ThisExpression(),
+ Token( SyntaxKind.DotToken ),
+ IdentifierName(
+ context.RegisterCachedFieldInfo(
+ field
+ )
+ )
+ )
+ );
+
+ protected override CodeTreeConstruct EmitThrowStatement( CodeTreeContext context, CodeTreeConstruct exception )
+ => CodeTreeConstruct.Statement( ThrowStatement( exception.AsExpression() ) );
+
+ protected override CodeTreeConstruct EmitSequentialStatements( CodeTreeContext context, TypeDefinition contextType, IEnumerable statements )
+ {
+#if DEBUG
+ statements = statements.ToArray();
+ Contract.Assert( statements.All( c => c.IsStatement ), $"[{String.Join( ", ", statements.Select( ( c, i ) => new { c, i } ).Where( x => !x.c.IsStatement ).Select( x => $"[{x.i}]{x.c}" ) )}]" );
+#endif
+ return CodeTreeConstruct.Statement( statements.SelectMany( s => s.AsStatements() ) );
+ }
+
+ protected override CodeTreeConstruct DeclareLocal( CodeTreeContext context, TypeDefinition type, string name )
+ {
+#if DEBUG
+ Contract.Assert( !name.Contains( "." ) );
+#endif
+ return
+ CodeTreeConstruct.Variable(
+ type,
+ VariableDeclaration(
+ ToTypeSyntax( type ),
+ new SeparatedSyntaxList().Add( VariableDeclarator( context.GetUniqueVariableName( name ) ) )
+ )
+ );
+ }
+
+ protected override CodeTreeConstruct ReferArgument( CodeTreeContext context, TypeDefinition type, string name, int index )
+ {
+#if DEBUG
+ Contract.Assert( !name.Contains( "." ) );
+#endif
+ return CodeTreeConstruct.Parameter( type, IdentifierName( name ) );
+ }
+
+ protected override CodeTreeConstruct EmitCreateNewObjectExpression( CodeTreeContext context, CodeTreeConstruct variable, ConstructorDefinition constructor, params CodeTreeConstruct[] arguments )
+ {
+#if DEBUG
+ Contract.Assert( constructor != null );
+ Contract.Assert( constructor.DeclaringType != null );
+ Contract.Assert( arguments.All( c => c.IsExpression ), String.Join( ",", arguments.Select( c => c.ToString() ).ToArray() ) );
+#endif
+ return
+ CodeTreeConstruct.Expression(
+ constructor.DeclaringType,
+ ObjectCreationExpression(
+ ToTypeSyntax( constructor.DeclaringType )
+ ).AddArgumentListArguments(
+ arguments.Select( a => Argument( a.AsExpression() ) ).ToArray()
+ )
+ );
+ }
+
+ protected override CodeTreeConstruct EmitMakeRef( CodeTreeContext context, CodeTreeConstruct target )
+ => CodeTreeConstruct.Expression( target.ContextType, MakeRefExpression( target.AsExpression() ) );
+
+ protected override CodeTreeConstruct EmitInvokeVoidMethod( CodeTreeContext context, CodeTreeConstruct instance, MethodDefinition method, params CodeTreeConstruct[] arguments )
+ {
+#if DEBUG
+ Contract.Assert( instance == null || instance.IsExpression );
+ Contract.Assert( instance != null || method.DeclaringType != null );
+ arguments = arguments.Where( a => a != null ).ToArray();
+ Contract.Assert( arguments.All( c => c.IsExpression ), String.Join( ",", arguments.Select( c => c.ToString() ).ToArray() ) );
+#endif
+ return
+ CodeTreeConstruct.Statement(
+ ExpressionStatement(
+ CreateMethodInvocation( method, instance, arguments )
+ )
+ );
+ }
+
+ protected override CodeTreeConstruct EmitInvokeMethodExpression( CodeTreeContext context, CodeTreeConstruct instance, MethodDefinition method, IEnumerable arguments )
+ {
+#if DEBUG
+ Contract.Assert( instance == null || instance.IsExpression );
+ Contract.Assert( instance != null || method.DeclaringType != null );
+ arguments = arguments.Where( a => a != null ).ToArray();
+ Contract.Assert( arguments.All( c => c.IsExpression ), String.Join( ",", arguments.Select( c => c.ToString() ).ToArray() ) );
+#endif
+ return
+ CodeTreeConstruct.Expression(
+ method.ReturnType,
+ CreateMethodInvocation( method, instance, arguments )
+ );
+ }
+
+
+ private static ExpressionSyntax CreateMethodInvocation( MethodDefinition method, CodeTreeConstruct instance, IEnumerable arguments )
+ {
+ ExpressionSyntax target;
+ var methodName = method.MethodName;
+
+ if ( method.Interface != null )
+ {
+ // Explicit interface impl.
+#if DEBUG
+ Contract.Assert( instance != null, "instance != null" );
+ Contract.Assert( method.TryGetRuntimeMethod() != null, "method.TryGetRuntimeMethod() != null" );
+ Contract.Assert( !method.TryGetRuntimeMethod().GetIsPublic(), method.TryGetRuntimeMethod() + " is non public" );
+#endif // DEBUG
+ target =
+ CastExpression(
+ // Generics is not supported yet.
+ ToTypeSyntax( method.Interface ),
+ instance.AsExpression()
+ );
+ methodName = method.MethodName.Substring( method.MethodName.LastIndexOf( '.' ) + 1 );
+ }
+ else
+ {
+ target =
+ instance == null
+ ? IdentifierName( method.DeclaringType.TypeName )
+ : instance.AsExpression();
+ }
+
+ return
+ InvocationExpression(
+ SimpleMemberAccessExpression(
+ target,
+ ( method.TryGetRuntimeMethod() != null && method.TryGetRuntimeMethod().IsGenericMethod )
+ ? GenericName(
+ methodName,
+ method.TryGetRuntimeMethod().GetGenericArguments().Select( t => ToTypeSyntax( t ) )
+ ) : IdentifierName( methodName ) as SimpleNameSyntax
+ ),
+ ArgumentList(
+ new SeparatedSyntaxList().AddRange( arguments.Select( a => Argument( a.AsExpression() ) ) )
+ )
+ );
+ }
+
+ protected override CodeTreeConstruct EmitInvokeDelegateExpression( CodeTreeContext context, TypeDefinition delegateReturnType, CodeTreeConstruct @delegate, params CodeTreeConstruct[] arguments )
+ {
+#if DEBUG
+ Contract.Assert( @delegate.IsExpression );
+ Contract.Assert(
+ @delegate.ContextType.TypeName.StartsWith( "System.Action" )
+ || @delegate.ContextType.TypeName.StartsWith( "System.Func" )
+ );
+ arguments = arguments.Where( a => a != null ).ToArray();
+ Contract.Assert( arguments.All( c => c.IsExpression ), String.Join( ",", arguments.Select( c => c.ToString() ).ToArray() ) );
+#endif
+ return
+ CodeTreeConstruct.Expression(
+ delegateReturnType,
+ InvocationExpression(
+ @delegate.AsExpression(),
+ ArgumentList( new SeparatedSyntaxList().AddRange( arguments.Select( a => Argument( a.AsExpression() ) ) ) )
+ )
+ );
+ }
+ protected override CodeTreeConstruct EmitGetPropertyExpression( CodeTreeContext context, CodeTreeConstruct instance, PropertyInfo property )
+ {
+#if DEBUG
+ Contract.Assert( instance == null || instance.IsExpression );
+ Contract.Assert( property.DeclaringType != null );
+#endif
+ return
+ CodeTreeConstruct.Expression(
+ property.PropertyType,
+ SimpleMemberAccessExpression(
+ instance == null
+ ? ToTypeSyntax( property.DeclaringType )
+ : instance.AsExpression(),
+ IdentifierName( property.Name )
+ )
+ );
+ }
+
+ protected override CodeTreeConstruct EmitGetFieldExpression( CodeTreeContext context, CodeTreeConstruct instance, FieldDefinition field )
+ {
+#if DEBUG
+ Contract.Assert( instance == null || instance.IsExpression );
+ Contract.Assert( instance != null || field.DeclaringType != null );
+#endif
+ return
+ CodeTreeConstruct.Expression(
+ field.FieldType,
+ SimpleMemberAccessExpression(
+ instance == null
+ ? ToTypeSyntax( field.DeclaringType )
+ : instance.AsExpression(),
+ IdentifierName( field.FieldName )
+ )
+ );
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "2", Justification = "Asserted internally" )]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "3", Justification = "Asserted internally" )]
+ protected override CodeTreeConstruct EmitSetProperty( CodeTreeContext context, CodeTreeConstruct instance, PropertyInfo property, CodeTreeConstruct value )
+ {
+#if DEBUG
+ Contract.Assert( instance == null || instance.IsExpression );
+ Contract.Assert( property.DeclaringType != null );
+ Contract.Assert( value.IsExpression );
+#endif
+ return
+ CodeTreeConstruct.Statement(
+ SimpleAssignmentStatement(
+ SimpleMemberAccessExpression(
+ instance == null
+ ? ToTypeSyntax( property.DeclaringType )
+ : instance.AsExpression(),
+ IdentifierName( property.Name )
+ ),
+ value.AsExpression()
+ )
+ );
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "2", Justification = "Asserted internally" )]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "4", Justification = "Asserted internally" )]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "5", Justification = "Asserted internally" )]
+ protected override CodeTreeConstruct EmitSetIndexedProperty( CodeTreeContext context, CodeTreeConstruct instance, TypeDefinition declaringType, string proeprtyName, CodeTreeConstruct key, CodeTreeConstruct value )
+ {
+#if DEBUG
+ Contract.Assert( instance == null || instance.IsExpression );
+ Contract.Assert( instance != null || declaringType.HasRuntimeTypeFully() );
+ Contract.Assert( key.IsExpression );
+ Contract.Assert( value.IsExpression );
+#endif
+ return
+ CodeTreeConstruct.Statement(
+ SimpleAssignmentStatement(
+ ElementAccessExpression(
+ instance == null
+ ? ToTypeSyntax( declaringType.ResolveRuntimeType() )
+ : instance.AsExpression()
+ ).AddArgumentListArguments(
+ Argument( key.AsExpression() )
+ ),
+ value.AsExpression()
+ )
+ );
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "2", Justification = "Asserted internally" )]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "3", Justification = "Asserted internally" )]
+ protected override CodeTreeConstruct EmitSetField( CodeTreeContext context, CodeTreeConstruct instance, FieldDefinition field, CodeTreeConstruct value )
+ {
+#if DEBUG
+ Contract.Assert( instance == null || instance.IsExpression );
+ Contract.Assert( instance != null || field.DeclaringType != null );
+ Contract.Assert( value.IsExpression );
+#endif
+ return
+ CodeTreeConstruct.Statement(
+ SimpleAssignmentStatement(
+ SimpleMemberAccessExpression(
+ instance == null
+ ? ToTypeSyntax( field.DeclaringType )
+ : instance.AsExpression(),
+ IdentifierName( field.FieldName )
+ ),
+ value.AsExpression()
+ )
+ );
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "4", Justification = "Asserted internally" )]
+ protected override CodeTreeConstruct EmitSetField( CodeTreeContext context, CodeTreeConstruct instance, TypeDefinition nestedType, string fieldName, CodeTreeConstruct value )
+ {
+#if DEBUG
+ Contract.Assert( instance == null || instance.IsExpression );
+ Contract.Assert( value.IsExpression );
+#endif
+ return
+ CodeTreeConstruct.Statement(
+ SimpleAssignmentStatement(
+ SimpleMemberAccessExpression(
+ instance == null
+ ? ToTypeSyntax( nestedType )
+ : instance.AsExpression(),
+ IdentifierName( fieldName )
+ ),
+ value.AsExpression()
+ )
+ );
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "1", Justification = "Asserted internally" )]
+ protected override CodeTreeConstruct EmitLoadVariableExpression( CodeTreeContext context, CodeTreeConstruct variable )
+ => CodeTreeConstruct.Expression( variable.ContextType, variable.AsExpression() );
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "1", Justification = "Asserted internally" )]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "2", Justification = "Asserted internally" )]
+ protected override CodeTreeConstruct EmitStoreVariableStatement( CodeTreeContext context, CodeTreeConstruct variable, CodeTreeConstruct value )
+ {
+#if DEBUG
+ Contract.Assert( variable.IsExpression );
+ Contract.Assert( value.IsExpression );
+#endif
+ return
+ CodeTreeConstruct.Statement(
+ SimpleAssignmentStatement(
+ variable.AsExpression(),
+ value.AsExpression()
+ )
+ );
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "1", Justification = "Asserted internally" )]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "2", Justification = "Asserted internally" )]
+ protected override CodeTreeConstruct EmitTryFinally( CodeTreeContext context, CodeTreeConstruct tryStatement, CodeTreeConstruct finallyStatement )
+ {
+#if DEBUG
+ Contract.Assert( tryStatement.IsStatement );
+ Contract.Assert( finallyStatement.IsStatement );
+#endif
+ return
+ CodeTreeConstruct.Statement(
+ TryStatement(
+ Block(
+ tryStatement.AsStatements()
+ ),
+ EmptyCatches,
+ FinallyClause(
+ Block(
+ finallyStatement.AsStatements()
+ )
+ )
+ )
+ );
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "1", Justification = "Asserted internally" )]
+ protected override CodeTreeConstruct EmitCreateNewArrayExpression( CodeTreeContext context, TypeDefinition elementType, int length )
+ => CodeTreeConstruct.Expression(
+ TypeDefinition.Array( elementType ),
+ SZArrayCreationExpression(
+ ToTypeSyntax( elementType ),
+ LiteralExpression( SyntaxKind.NumericLiteralExpression, Literal( length ) )
+ )
+ );
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "1", Justification = "Asserted internally" )]
+ protected override CodeTreeConstruct EmitCreateNewArrayExpression( CodeTreeContext context, TypeDefinition elementType, int length, IEnumerable initialElements )
+ {
+#if DEBUG
+ initialElements = initialElements.ToArray();
+ Contract.Assert( initialElements.All( i => i.IsExpression ) );
+#endif
+ return
+ CodeTreeConstruct.Expression(
+ TypeDefinition.Array( elementType ),
+ SZArrayCreationExpression(
+ ToTypeSyntax( elementType ),
+ LiteralExpression( SyntaxKind.NumericLiteralExpression, Literal( length ) ),
+ initialElements.Select( i => i.AsExpression() )
+ )
+ );
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "1", Justification = "Asserted internally" )]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "2", Justification = "Asserted internally" )]
+ protected override CodeTreeConstruct EmitGetArrayElementExpression( CodeTreeContext context, CodeTreeConstruct array, CodeTreeConstruct index )
+ => CodeTreeConstruct.Expression(
+ array.ContextType.ElementType,
+ ElementAccessExpression( array.AsExpression() )
+ .WithExpression( index.AsExpression() )
+ );
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "1", Justification = "Asserted internally" )]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "2", Justification = "Asserted internally" )]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "3", Justification = "Asserted internally" )]
+ protected override CodeTreeConstruct EmitSetArrayElementStatement( CodeTreeContext context, CodeTreeConstruct array, CodeTreeConstruct index, CodeTreeConstruct value )
+ => CodeTreeConstruct.Statement(
+ SimpleAssignmentStatement(
+ ElementAccessExpression(
+ array.AsExpression()
+ ).WithExpression(
+ index.AsExpression()
+ ),
+ value.AsExpression()
+ )
+ );
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "0", Justification = "Asserted internally" )]
+ protected override CodeTreeConstruct EmitGetSerializerExpression( CodeTreeContext context, Type targetType, SerializingMember? memberInfo, PolymorphismSchema itemsSchema )
+ => CodeTreeConstruct.Expression(
+ typeof( MessagePackSerializer<> ).MakeGenericType( targetType ),
+ SimpleMemberAccessExpression(
+ ThisExpression(),
+ IdentifierName(
+ context.RegisterSerializer(
+ targetType,
+ memberInfo?.GetEnumMemberSerializationMethod() ?? EnumMemberSerializationMethod.Default,
+ memberInfo?.GetDateTimeMemberConversionMethod() ?? DateTimeMemberConversionMethod.Default,
+ itemsSchema ?? PolymorphismSchema.Create( targetType, memberInfo )
+ )
+ )
+ )
+ );
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "0", Justification = "Asserted internally" )]
+ protected override CodeTreeConstruct EmitGetActionsExpression( CodeTreeContext context, ActionType actionType, bool isAsync )
+ {
+ TypeDefinition type;
+ string name;
+ switch ( actionType )
+ {
+ case ActionType.PackToArray:
+ {
+ type =
+ isAsync ? typeof( IList<> ).MakeGenericType( typeof( Func<,,,> ).MakeGenericType( typeof( Packer ), this.TargetType, typeof( CancellationToken ), typeof( Task ) ) ) :
+ typeof( IList<> ).MakeGenericType( typeof( Action<,> ).MakeGenericType( typeof( Packer ), this.TargetType ) );
+ name = FieldName.PackOperationList;
+ break;
+ }
+ case ActionType.PackToMap:
+ {
+ type =
+ isAsync ? typeof( IDictionary<,> ).MakeGenericType( typeof( string ), typeof( Func<,,,> ).MakeGenericType( typeof( Packer ), this.TargetType, typeof( CancellationToken ), typeof( Task ) ) ) :
+ typeof( IDictionary<,> ).MakeGenericType( typeof( string ), typeof( Action<,> ).MakeGenericType( typeof( Packer ), this.TargetType ) );
+ name = FieldName.PackOperationTable;
+ break;
+ }
+ case ActionType.IsNull:
+ {
+ type = typeof( IDictionary<,> ).MakeGenericType( typeof( string ), typeof( Func<,> ).MakeGenericType( this.TargetType, typeof( bool ) ) );
+ name = FieldName.NullCheckersTable;
+ break;
+ }
+ case ActionType.UnpackFromArray:
+ {
+ type =
+ TypeDefinition.GenericReferenceType(
+ typeof( IList<> ),
+ isAsync ?
+ TypeDefinition.GenericReferenceType(
+ typeof( Func<,,,,,> ),
+ typeof( Unpacker ),
+ context.UnpackingContextType ?? this.TargetType,
+ typeof( int ),
+ typeof( int ),
+ typeof( CancellationToken ),
+ typeof( Task )
+ ) :
+ TypeDefinition.GenericReferenceType(
+ typeof( Action<,,,> ),
+ typeof( Unpacker ),
+ context.UnpackingContextType ?? this.TargetType,
+ typeof( int ),
+ typeof( int )
+ )
+ );
+ name = FieldName.UnpackOperationList;
+ break;
+ }
+ case ActionType.UnpackFromMap:
+ {
+ type =
+ TypeDefinition.GenericReferenceType(
+ typeof( IDictionary<,> ),
+ typeof( string ),
+ isAsync ?
+ TypeDefinition.GenericReferenceType(
+ typeof( Func<,,,,,> ),
+ typeof( Unpacker ),
+ context.UnpackingContextType ?? this.TargetType,
+ typeof( int ),
+ typeof( int ),
+ typeof( CancellationToken ),
+ typeof( Task )
+ ) :
+ TypeDefinition.GenericReferenceType(
+ typeof( Action<,,,> ),
+ typeof( Unpacker ),
+ context.UnpackingContextType ?? this.TargetType,
+ typeof( int ),
+ typeof( int )
+ )
+ );
+ name = FieldName.UnpackOperationTable;
+ break;
+ }
+ case ActionType.UnpackTo:
+ {
+ type =
+ isAsync ? typeof( Func<,,,,> ).MakeGenericType( typeof( Unpacker ), this.TargetType, typeof( int ), typeof( CancellationToken ), typeof( Task ) ) :
+ typeof( Action<,,> ).MakeGenericType( typeof( Unpacker ), this.TargetType, typeof( int ) );
+ name = FieldName.UnpackTo;
+ break;
+ }
+ default:
+ {
+ throw new ArgumentOutOfRangeException( nameof( actionType ) );
+ }
+ }
+
+ if ( isAsync )
+ {
+ name += "Async";
+ }
+
+ var field = context.DeclarePrivateField( name, type );
+
+ return
+ CodeTreeConstruct.Expression(
+ type,
+ SimpleMemberAccessExpression(
+ ThisExpression(),
+ IdentifierName( field.FieldName )
+ )
+ );
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "0", Justification = "Asserted internally" )]
+ protected override CodeTreeConstruct EmitGetMemberNamesExpression( CodeTreeContext context )
+ {
+ var field = context.DeclarePrivateField( FieldName.MemberNames, typeof( IList ) );
+
+ return
+ CodeTreeConstruct.Expression(
+ typeof( IList ),
+ SimpleMemberAccessExpression(
+ ThisExpression(),
+ IdentifierName( field.FieldName )
+ )
+ );
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "2", Justification = "Asserted internally" )]
+ protected override CodeTreeConstruct EmitFinishFieldInitializationStatement( CodeTreeContext context, string name, CodeTreeConstruct value )
+ => CodeTreeConstruct.Statement(
+ SimpleAssignmentStatement(
+ SimpleMemberAccessExpression(
+ ThisExpression(),
+ IdentifierName( name )
+ ),
+ value.AsExpression()
+ )
+ );
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "1", Justification = "Asserted internally" )]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "2", Justification = "Asserted internally" )]
+ protected override CodeTreeConstruct EmitConditionalExpression( CodeTreeContext context, CodeTreeConstruct conditionExpression, CodeTreeConstruct thenExpression, CodeTreeConstruct elseExpression )
+ {
+#if DEBUG
+ Contract.Assert(
+ elseExpression == null
+ || thenExpression.ContextType.TryGetRuntimeType() == typeof( void )
+ || ( thenExpression.ContextType.TryGetRuntimeType() == elseExpression.ContextType.TryGetRuntimeType() ),
+ thenExpression.ContextType + " != " + ( elseExpression == null ? "(null)" : elseExpression.ContextType.TypeName )
+ );
+ Contract.Assert( conditionExpression.IsExpression );
+ Contract.Assert(
+ elseExpression == null
+ || thenExpression.ContextType.TryGetRuntimeType() == typeof( void )
+ || ( thenExpression.ContextType.TryGetRuntimeType() == elseExpression.ContextType.TryGetRuntimeType()
+ && thenExpression.IsExpression == elseExpression.IsExpression )
+ );
+
+#endif
+
+ return
+ elseExpression == null
+ ? CodeTreeConstruct.Statement(
+ IfStatement(
+ conditionExpression.AsExpression(),
+ Block( thenExpression.AsStatements() )
+ )
+ ) : thenExpression.ContextType.TryGetRuntimeType() == typeof( void ) || thenExpression.IsStatement
+ ? CodeTreeConstruct.Statement(
+ IfElseStatement(
+ conditionExpression.AsExpression(),
+ thenExpression.AsStatements(),
+ elseExpression.AsStatements()
+ )
+ )
+ : CodeTreeConstruct.Expression(
+ thenExpression.ContextType,
+ ConditionalExpression(
+ conditionExpression.AsExpression(),
+ thenExpression.AsExpression(),
+ elseExpression.AsExpression()
+ )
+ );
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "2", Justification = "Asserted internally" )]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "3", Justification = "Asserted internally" )]
+ protected override CodeTreeConstruct EmitAndConditionalExpression( CodeTreeContext context, IList conditionExpressions, CodeTreeConstruct thenExpression, CodeTreeConstruct elseExpression )
+ {
+#if DEBUG
+ Contract.Assert( conditionExpressions.All( c => c.IsExpression ) );
+ Contract.Assert( thenExpression.IsStatement );
+ Contract.Assert( elseExpression.IsStatement );
+#endif
+
+ return
+ CodeTreeConstruct.Statement(
+ IfElseStatement(
+ conditionExpressions
+ .Select( c => c.AsExpression() )
+ .Aggregate( ( l, r ) =>
+ AndAlsoExpression( l, r )
+ ),
+ thenExpression.AsStatements(),
+ elseExpression.AsStatements()
+ )
+ );
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "1", Justification = "Asserted internally" )]
+ protected override CodeTreeConstruct EmitRetrunStatement( CodeTreeContext context, CodeTreeConstruct expression )
+ {
+#if DEBUG
+ Contract.Assert( expression.IsExpression );
+#endif
+ return
+ CodeTreeConstruct.Statement(
+ ReturnStatement(
+ expression.AsExpression()
+ )
+ );
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "0", Justification = "Asserted internally" )]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "1", Justification = "Asserted internally" )]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "2", Justification = "Asserted internally" )]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "3", Justification = "Asserted internally" )]
+ protected override CodeTreeConstruct EmitForEachLoop( CodeTreeContext context, CollectionTraits collectionTraits, CodeTreeConstruct collection, Func loopBodyEmitter )
+ {
+#if DEBUG
+ Contract.Assert( collection.IsExpression );
+#endif
+
+ var currentName = context.GetUniqueVariableName( "current" );
+ var current = this.DeclareLocal( context, collectionTraits.ElementType, currentName );
+ return
+ CodeTreeConstruct.Statement(
+ ForEachStatement(
+ ToTypeSyntax( collectionTraits.ElementType ),
+ currentName,
+ collection.AsExpression(),
+ Block(
+ loopBodyEmitter( current ).AsStatements()
+ )
+ )
+ );
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "2", Justification = "Asserted internally" )]
+ protected override CodeTreeConstruct EmitEnumFromUnderlyingCastExpression(
+ CodeTreeContext context,
+ Type enumType,
+ CodeTreeConstruct underlyingValue
+ ) => CodeTreeConstruct.Expression( enumType, CastExpression( ToTypeSyntax( enumType ), underlyingValue.AsExpression() ) );
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "2", Justification = "Asserted internally" )]
+ protected override CodeTreeConstruct EmitEnumToUnderlyingCastExpression(
+ CodeTreeContext context,
+ Type underlyingType,
+ CodeTreeConstruct enumValue
+ ) => CodeTreeConstruct.Expression( underlyingType, CastExpression( ToTypeSyntax( underlyingType ), enumValue.AsExpression() ) );
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "1", Justification = "Asserted internally" )]
+ protected override CodeTreeConstruct EmitNewPrivateMethodDelegateExpression( CodeTreeContext context, MethodDefinition method )
+ {
+ var delegateBaseType = SerializerBuilderHelper.FindDelegateType( method.ReturnType, method.ParameterTypes );
+
+ var delegateType =
+ ( method.ReturnType.TryGetRuntimeType() == typeof( void ) && method.ParameterTypes.Length == 0 )
+ ? delegateBaseType
+ : TypeDefinition.GenericReferenceType(
+ delegateBaseType,
+ method.ReturnType.TryGetRuntimeType() == typeof( void )
+ ? method.ParameterTypes
+ : method.ParameterTypes.Concat( new[] { method.ReturnType } ).ToArray()
+ );
+
+ return
+ CodeTreeConstruct.Expression(
+ delegateType,
+ ObjectCreationExpression(
+ ToTypeSyntax( delegateType )
+ ).AddArgumentListArguments(
+ Argument(
+ SimpleMemberAccessExpression(
+ method.IsStatic ? IdentifierName( context.DeclaringTypeName ) : ThisExpression() as ExpressionSyntax,
+ IdentifierName( method.MethodName )
+ )
+ )
+ )
+ );
+ }
+
+ ///
+ /// Builds the serializer code using specified code generation context.
+ ///
+ ///
+ /// The which holds configuration and stores generated code constructs.
+ ///
+ /// The substitution type if is abstract type. null when is not abstract type.
+ /// The schema which contains schema for collection items, dictionary keys, or tuple items. This value must not be null.
+ ///
+ /// is null.
+ ///
+ ///
+ /// This class does not support code generation.
+ ///
+ public void BuildSerializerCode( ISerializerCodeGenerationContext context, Type concreteType, PolymorphismSchema itemSchema )
+ {
+ if ( context == null )
+ {
+ throw new ArgumentNullException( nameof( context ) );
+ }
+
+ var asCodeTreeContext = context as CodeTreeContext;
+ if ( asCodeTreeContext == null )
+ {
+ throw new ArgumentException(
+ "'context' was not created with CreateGenerationContextForCodeGeneration method.",
+ nameof( context )
+ );
+ }
+
+ asCodeTreeContext.Reset( this.TargetType, this.BaseClass );
+
+ if ( !this.TargetType.GetIsEnum() )
+ {
+ SerializationTarget targetInfo;
+ this.BuildSerializer( asCodeTreeContext, concreteType, itemSchema, out targetInfo );
+ this.Finish(
+ asCodeTreeContext,
+ targetInfo,
+ false,
+ targetInfo == null
+ ? default( SerializerCapabilities? )
+ : this.CollectionTraits.CollectionType == CollectionKind.NotCollection
+ ? targetInfo.GetCapabilitiesForObject()
+ : targetInfo.GetCapabilitiesForCollection( this.CollectionTraits )
+ );
+ }
+ else
+ {
+ this.BuildEnumSerializer( asCodeTreeContext );
+ this.Finish( asCodeTreeContext, null, true, ( SerializerCapabilities.PackTo | SerializerCapabilities.UnpackFrom ) );
+ }
+ }
+
+ protected override Func CreateSerializerConstructor( CodeTreeContext codeGenerationContext, SerializationTarget targetInfo, PolymorphismSchema schema, SerializerCapabilities? capabilities )
+ {
+ this.Finish( codeGenerationContext, targetInfo, false, capabilities );
+ var targetType = PrepareSerializerConstructorCreation( codeGenerationContext );
+
+ return targetType.CreateConstructorDelegate();
+ }
+
+ protected override Func CreateEnumSerializerConstructor( CodeTreeContext codeGenerationContext )
+ {
+ this.Finish( codeGenerationContext, null, true, SerializerCapabilities.PackTo | SerializerCapabilities.UnpackFrom );
+ var targetType = PrepareSerializerConstructorCreation( codeGenerationContext );
+
+ return targetType.CreateConstructorDelegate();
+ }
+
+ private static Type PrepareSerializerConstructorCreation( CodeTreeContext codeGenerationContext )
+ {
+ if ( !SerializerDebugging.OnTheFlyCodeGenerationEnabled )
+ {
+ throw new NotSupportedException();
+ }
+
+ CompilationUnitSyntax cu = codeGenerationContext.CreateCompilationUnit();
+
+ if ( SerializerDebugging.DumpEnabled )
+ {
+ SerializerDebugging.TraceEmitEvent( "Compile {0}", codeGenerationContext.DeclaringTypeName );
+ cu.WriteTo( SerializerDebugging.ILTraceWriter );
+ SerializerDebugging.FlushTraceData();
+ }
+
+ var assemblyName = $"CodeAssembly{DateTime.Now:yyyyMMddHHmmssfff}{ProcessId}{Environment.CurrentManagedThreadId}";
+
+ var compilation =
+ CompilationFactory.Create(
+ assemblyName,
+ new[] { cu.SyntaxTree },
+ SerializerDebugging.CodeSerializerDependentAssemblies.Select( x => MetadataReference.CreateFromFile( x ) ),
+ new CompilationOptionsImpl(
+ OutputKind.DynamicallyLinkedLibrary
+#if !DEBUG || PERFORMANCE_TEST
+ , optimizationLevel: OptimizationLevel.Release
+#endif // !DEBUG || PERFORMANCE_TEST
+ )
+ );
+ var outputPath = Path.Combine( Path.GetTempPath(), assemblyName + "." + Extension );
+
+ var result = compilation.Emit( outputPath );
+ if ( !result.Success )
+ {
+ if ( SerializerDebugging.TraceEnabled && !SerializerDebugging.DumpEnabled )
+ {
+ cu.WriteTo( SerializerDebugging.ILTraceWriter );
+ SerializerDebugging.FlushTraceData();
+ }
+
+ throw new System.Runtime.Serialization.SerializationException(
+ String.Format(
+ CultureInfo.CurrentCulture,
+ "Failed to compile assembly. Details:{0}{1}",
+ Environment.NewLine,
+ BuildCompilationError( result.Diagnostics )
+ )
+ );
+ }
+#if DEBUG
+ // Check warning except ambigious type reference.
+ var warnings =
+ result.Diagnostics.Where( e => e.Id != "CS0436" ).ToArray();
+ Contract.Assert( !warnings.Any(), BuildCompilationError( result.Diagnostics ) );
+#endif
+
+ if ( SerializerDebugging.TraceEnabled )
+ {
+ SerializerDebugging.TraceEmitEvent( "Build assembly '{0}' from dom.", outputPath );
+ }
+
+ SerializerDebugging.AddCompiledCodeDomAssembly( outputPath );
+
+ var rootNamespace =
+ cu.SyntaxTree.GetCompilationUnitRoot().ChildNodesAndTokens()
+ .First( x => x.AsNode() is NamespaceDeclarationSyntax ).ChildNodesAndTokens()
+ .First( x => x.AsNode() is QualifiedNameSyntax ).ToString();
+
+ var assembly = SerializerDebugging.LoadAssembly( outputPath );
+ var targetType =
+ assembly.ExportedTypes
+ .SingleOrDefault(
+ t =>
+ t.Namespace == rootNamespace
+ && t.Name == codeGenerationContext.DeclaringTypeName
+ );
+
+ Contract.Assert(
+ targetType != null,
+ rootNamespace + " not in:" +
+ String.Join(
+ Environment.NewLine,
+ assembly.ExportedTypes
+ .Select( t => t.FullName ).ToArray()
+ )
+ );
+
+ return targetType;
+ }
+
+ private static string BuildCompilationError( IEnumerable diagnostics )
+ => String.Join(
+ Environment.NewLine,
+ diagnostics
+ .Select(
+ ( error, i ) =>
+ String.Format(
+ CultureInfo.InvariantCulture,
+ "[{0}]{1}:{2}:({3}):{4}",
+ i,
+ error.Severity,
+ error.Id,
+ error.Location,
+ error
+ )
+ ).ToArray()
+ );
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling", Justification = "CodeDOM" )]
+ private void Finish( CodeTreeContext context, SerializationTarget targetInfo, bool isEnum, SerializerCapabilities? capabilities )
+ {
+ var publicConstructorTemplate =
+ ConstructorDeclaration(
+ context.DeclaringTypeName,
+ SyntaxTokenList.Create( Token( SyntaxKind.PublicKeyword ) )
+ );
+
+ // ctor
+ if ( isEnum )
+ {
+ // .ctor(SerializationContext context) : base(context, EnumSerializationMethod.Xxx)
+ context.AddMember(
+ publicConstructorTemplate.WithParameterList(
+ ContextParameterListSyntax
+ ).WithInitializer(
+ BaseConstructorInitializer(
+ ArgumentList(
+ ContextArgumentListTemplate.Add(
+ Argument(
+ SimpleMemberAccessExpression(
+ EnumSerializationMethodTypeIdentifierSyntax,
+ IdentifierName(
+ EnumMessagePackSerializerHelpers.DetermineEnumSerializationMethod(
+ context.SerializationContext,
+ this.TargetType,
+ EnumMemberSerializationMethod.Default
+ ).ToString()
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+ );
+
+ // .ctor(SerializationContext context, EnumSerializationMethod enumSerializationMethod) : base(context, enumSerializationMethod)
+ context.AddMember(
+ publicConstructorTemplate.WithParameterList(
+ ContextAndEnumSerializationMethodParameterListSyntax
+ ).WithInitializer(
+ ContextAndEnumSerializationMethodConstructorInitializerSyntax
+ )
+ );
+ }
+ else
+ {
+ // not enum
+
+ context.BeginConstructor();
+ try
+ {
+ var statements = this.BuildDependentSerializersInitialization( context );
+ statements = BuildCachedFieldInfosInitialization( context, statements );
+ statements = BuildCachedMethodInfosInitialization( context, statements );
+
+ if ( targetInfo != null && this.CollectionTraits.CollectionType == CollectionKind.NotCollection )
+ {
+ // For object only.
+ if ( !typeof( IPackable ).IsAssignableFrom( this.TargetType )
+ || !typeof( IAsyncPackable ).IsAssignableFrom( this.TargetType )
+ )
+ {
+ statements = this.BuildPackOperationDelegatesInitialization( context, targetInfo, statements );
+ }
+
+ if ( targetInfo.CanDeserialize
+ && ( !typeof( IUnpackable ).IsAssignableFrom( this.TargetType )
+ || !typeof( IAsyncUnpackable ).IsAssignableFrom( this.TargetType ) )
+ )
+ {
+ statements = this.BuildUnpackOperationDelegatesInitialization( context, targetInfo, statements );
+ }
+ }
+
+ statements = BuildCachedDelegatesInitialization( context, statements );
+
+ if ( context.IsUnpackToUsed )
+ {
+ statements = statements.AddRange( this.EmitUnpackToInitialization( context ).AsStatements() );
+ }
+
+ context.AddMember(
+ publicConstructorTemplate.WithParameterList(
+ ContextParameterListSyntax
+ ).WithInitializer(
+ BaseConstructorInitializer(
+ ArgumentList(
+ this.BuildBaseConstructorArgs( context, capabilities )
+ )
+ )
+ ).AddBodyStatements( statements.ToArray() )
+ );
+ }
+ finally
+ {
+ context.EndConstructor();
+ }
+ } // else of isEnum
+ }
+
+ private static SyntaxList BuildCachedDelegatesInitialization( CodeTreeContext context, SyntaxList statements )
+ {
+ foreach ( var cachedDelegateInfo in context.GetCachedDelegateInfos() )
+ {
+ statements =
+ statements.Add(
+ SimpleAssignmentStatement(
+ SimpleMemberAccessExpression(
+ ThisExpression(),
+ IdentifierName( cachedDelegateInfo.BackingField.FieldName )
+ ),
+ ObjectCreationExpression(
+ ToTypeSyntax( cachedDelegateInfo.BackingField.FieldType )
+ ).AddArgumentListArguments(
+ Argument(
+ SimpleMemberAccessExpression(
+ cachedDelegateInfo.IsThisInstance
+ ? ThisExpression() as ExpressionSyntax
+ : ToTypeSyntax( cachedDelegateInfo.TargetMethod.DeclaringType ),
+ IdentifierName( cachedDelegateInfo.TargetMethod.MethodName )
+ )
+ )
+ )
+ )
+ );
+ }
+
+ return statements;
+ }
+
+ private SeparatedSyntaxList BuildBaseConstructorArgs( CodeTreeContext context, SerializerCapabilities? capabilities )
+ {
+ var baseConstructorArgs = ContextArgumentListTemplate;
+
+ if ( this.BaseClass.GetTypeInfo().DeclaredConstructors.Where( c => !c.IsPublic && !c.IsStatic )
+ .Any(
+ c =>
+ c.GetParameterTypes()
+ .SequenceEqual( CollectionSerializerHelpers.CollectionConstructorTypes )
+ )
+ )
+ {
+ baseConstructorArgs =
+ baseConstructorArgs.Add(
+ Argument(
+ InvocationExpression(
+ SimpleMemberAccessExpression(
+ IdentifierName( context.DeclaringTypeName ),
+ RestoreSchemaMethodIdentifierSyntax
+ )
+ )
+ )
+ );
+ }
+
+ if ( capabilities.HasValue )
+ {
+ var capabilitiesExpression = BuildCapabilitiesExpression( null, capabilities.Value, SerializerCapabilities.PackTo );
+ capabilitiesExpression = BuildCapabilitiesExpression( capabilitiesExpression, capabilities.Value, SerializerCapabilities.UnpackFrom );
+ capabilitiesExpression = BuildCapabilitiesExpression( capabilitiesExpression, capabilities.Value, SerializerCapabilities.UnpackTo );
+
+ baseConstructorArgs =
+ baseConstructorArgs.Add(
+ Argument( capabilitiesExpression ?? SerializerCapabilitiesNoneSyntax )
+ );
+ }
+
+ return baseConstructorArgs;
+ }
+
+ private SyntaxList BuildDependentSerializersInitialization( CodeTreeContext context )
+ {
+ var statements = new SyntaxList();
+
+ int schemaNumber = -1;
+ foreach ( var dependentSerializer in context.GetDependentSerializers() )
+ {
+ var targetType = Type.GetTypeFromHandle( dependentSerializer.Key.TypeHandle );
+ var targetTypeSyntax = ToTypeSyntax( targetType );
+ ExpressionSyntax getSerializerArgument;
+
+ if ( targetType.GetIsEnum() )
+ {
+ getSerializerArgument =
+ EnumMessagePackSerializerHelpersDetermineEnumSerializationMethodMethodTemplate
+ .AddArgumentListArguments(
+ ContextArgumentSyntax,
+ Argument( TypeOfExpression( targetTypeSyntax ) ),
+ Argument(
+ SimpleMemberAccessExpression(
+ EnumSerializationMethodTypeIdentifierSyntax,
+ IdentifierName( dependentSerializer.Key.EnumSerializationMethod.ToString() )
+ )
+ )
+ );
+
+ }
+ else if ( DateTimeMessagePackSerializerHelpers.IsDateTime( targetType ) )
+ {
+ getSerializerArgument =
+ DateTimeMessagePackSerializerHelpersDetermineDateTimeConversionMethodTemplate
+ .AddArgumentListArguments(
+ ContextArgumentSyntax,
+ Argument(
+ SimpleMemberAccessExpression(
+ DateTimeMemberConversionMethodIdentifierSyntax,
+ IdentifierName( dependentSerializer.Key.DateTimeConversionMethod.ToString() )
+ )
+ )
+ );
+ }
+ else
+ {
+ if ( dependentSerializer.Key.PolymorphismSchema == null )
+ {
+ getSerializerArgument = NullLiteralSyntax;
+ }
+ else
+ {
+ schemaNumber++;
+ var variableName = "schema" + schemaNumber;
+ var schema = this.DeclareLocal( context, typeof( PolymorphismSchema ), variableName );
+ statements =
+ statements
+ .AddRange( schema.AsStatements() )
+ .AddRange(
+ this.EmitConstructPolymorphismSchema(
+ context,
+ schema,
+ dependentSerializer.Key.PolymorphismSchema
+ ).SelectMany( st => st.AsStatements() )
+ );
+
+ getSerializerArgument = IdentifierName( variableName );
+ }
+ }
+
+ statements.Add(
+ SimpleAssignmentStatement(
+ SimpleMemberAccessExpression(
+ ThisExpression(),
+ IdentifierName( dependentSerializer.Value )
+ ),
+ InvocationExpression(
+ SimpleMemberAccessExpression(
+ ContextArgumentReferenceSyntax,
+ GenericName( "GetSerializer" )
+ .AddTypeArgumentListArguments(
+ targetTypeSyntax
+ )
+ )
+ ).AddArgumentListArguments( Argument( getSerializerArgument ) )
+ )
+ );
+ } // foreach ( in context.GetDependentSerializers() )
+
+ return statements;
+ }
+
+ private static SyntaxList BuildCachedFieldInfosInitialization( CodeTreeContext context, SyntaxList statements )
+ {
+ foreach ( var cachedFieldInfo in context.GetCachedFieldInfos() )
+ {
+ var fieldInfo = cachedFieldInfo.Value.Target;
+#if DEBUG
+ Contract.Assert( fieldInfo != null, "fieldInfo != null" );
+ Contract.Assert( fieldInfo.DeclaringType != null, "fieldInfo.DeclaringType != null" );
+#endif // DEBUG
+ statements =
+ statements.Add(
+ SimpleAssignmentStatement(
+ SimpleMemberAccessExpression(
+ ThisExpression(),
+ IdentifierName( cachedFieldInfo.Value.StorageFieldName )
+ ),
+ ReflectionHelpersGetFieldMethodTemplate.AddArgumentListArguments(
+ Argument( TypeOfExpression( ToTypeSyntax( fieldInfo.DeclaringType ) ) ),
+ Argument( LiteralExpression( SyntaxKind.StringLiteralExpression, Literal( fieldInfo.Name ) ) )
+ )
+ )
+ );
+ } // foreach ( in context.GetCachedFieldInfos() )
+
+ return statements;
+ }
+
+ private static SyntaxList BuildCachedMethodInfosInitialization( CodeTreeContext context, SyntaxList statements )
+ {
+ foreach ( var cachedMethodBase in context.GetCachedMethodBases() )
+ {
+ var methodBase = cachedMethodBase.Value.Target;
+ var parameterTypes = methodBase.GetParameterTypes();
+ statements =
+ statements.Add(
+ SimpleAssignmentStatement(
+ SimpleMemberAccessExpression(
+ ThisExpression(),
+ IdentifierName( cachedMethodBase.Value.StorageFieldName )
+ ),
+ ReflectionHelpersGetMethodMethodTemplate.AddArgumentListArguments(
+ Argument( TypeOfExpression( ToTypeSyntax( methodBase.DeclaringType ) ) ),
+ Argument( LiteralExpression( SyntaxKind.StringLiteralExpression, Literal( methodBase.Name ) ) ),
+ Argument( TypeArrayCreation( parameterTypes.Select( t => TypeOfExpression( ToTypeSyntax( t ) ) ) ) )
+ )
+ )
+ );
+ } // foreach ( in context.GetCachedMethodBases() )
+
+ return statements;
+ }
+
+ private SyntaxList BuildPackOperationDelegatesInitialization( CodeTreeContext context, SerializationTarget targetInfo, SyntaxList statements )
+ {
+ if ( !typeof( IPackable ).IsAssignableFrom( this.TargetType ) )
+ {
+ statements =
+ statements.AddRange(
+ this.EmitPackOperationListInitialization( context, targetInfo, isAsync: false ).AsStatements()
+ );
+ }
+
+ if ( this.WithAsync( context ) && !typeof( IAsyncPackable ).IsAssignableFrom( this.TargetType ) )
+ {
+ statements =
+ statements.AddRange(
+ this.EmitPackOperationListInitialization( context, targetInfo, isAsync: true ).AsStatements()
+ );
+ }
+
+ if ( targetInfo.Members.Any( m => m.Member != null ) ) // except Tuple
+ {
+ if ( !typeof( IPackable ).IsAssignableFrom( this.TargetType ) )
+ {
+ statements =
+ statements.AddRange(
+ this.EmitPackOperationTableInitialization( context, targetInfo, isAsync: false ).AsStatements()
+ );
+ }
+
+ if ( this.WithAsync( context ) && !typeof( IAsyncPackable ).IsAssignableFrom( this.TargetType ) )
+ {
+ statements =
+ statements.AddRange(
+ this.EmitPackOperationTableInitialization( context, targetInfo, isAsync: true ).AsStatements()
+ );
+ }
+
+ if ( !SerializerDebugging.UseLegacyNullMapEntryHandling
+ && ( !typeof( IPackable ).IsAssignableFrom( this.TargetType )
+ || ( !typeof( IAsyncPackable ).IsAssignableFrom( this.TargetType ) && this.WithAsync( context ) )
+ ) )
+ {
+ statements =
+ statements.AddRange(
+ this.EmitPackNullCheckerTableInitialization( context, targetInfo ).AsStatements()
+ );
+ }
+ }
+
+ return statements;
+ }
+
+ private SyntaxList BuildUnpackOperationDelegatesInitialization( CodeTreeContext context, SerializationTarget targetInfo, SyntaxList statements )
+ {
+ if ( !typeof( IUnpackable ).IsAssignableFrom( this.TargetType ) )
+ {
+ statements =
+ statements.AddRange(
+ this.EmitUnpackOperationListInitialization( context, targetInfo, false ).AsStatements()
+ );
+ }
+
+ if ( this.WithAsync( context ) && !typeof( IAsyncUnpackable ).IsAssignableFrom( this.TargetType ) )
+ {
+ statements =
+ statements.AddRange(
+ this.EmitUnpackOperationListInitialization( context, targetInfo, true ).AsStatements()
+ );
+ }
+
+ if ( targetInfo.Members.Any( m => m.Member != null ) )
+ {
+ // Except tuples
+ if ( !typeof( IUnpackable ).IsAssignableFrom( this.TargetType ) )
+ {
+ statements =
+ statements.AddRange(
+ this.EmitUnpackOperationTableInitialization( context, targetInfo, false ).AsStatements()
+ );
+ }
+
+ if ( this.WithAsync( context ) && !typeof( IAsyncUnpackable ).IsAssignableFrom( this.TargetType ) )
+ {
+ statements =
+ statements.AddRange(
+ this.EmitUnpackOperationTableInitialization( context, targetInfo, true ).AsStatements()
+ );
+ }
+ }
+
+ if ( !typeof( IUnpackable ).IsAssignableFrom( this.TargetType )
+ || ( !typeof( IAsyncUnpackable ).IsAssignableFrom( this.TargetType ) && this.WithAsync( context ) )
+ )
+ {
+ statements =
+ statements.AddRange(
+ this.EmitMemberListInitialization( context, targetInfo ).AsStatements()
+ );
+ }
+
+ return statements;
+ }
+
+ private static ExpressionSyntax BuildCapabilitiesExpression( ExpressionSyntax expression, SerializerCapabilities capabilities, SerializerCapabilities value )
+ {
+ if ( ( capabilities & value ) != 0 )
+ {
+ var capabilityExpression =
+ SimpleMemberAccessExpression(
+ SerializerCapabilitiesTypeIdentifierSyntax,
+ IdentifierName( value.ToString() )
+ );
+
+ if ( expression == null )
+ {
+ return capabilityExpression;
+ }
+ else
+ {
+ return
+ OrExpression(
+ expression,
+ capabilityExpression
+ );
+ }
+ }
+ else
+ {
+ return expression;
+ }
+ }
+
+ protected override CodeTreeContext CreateCodeGenerationContextForSerializerCreation( SerializationContext context )
+ {
+ var result = new CodeTreeContext( context, new SerializerCodeGenerationConfiguration(), Extension );
+ result.Reset( this.TargetType, this.BaseClass );
+ return result;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/MsgPack.CodeGeneration.CSharp/Serialization/CodeTreeSerializers/ExpressionCodeTreeConstruct.cs b/src/MsgPack.CodeGeneration.CSharp/Serialization/CodeTreeSerializers/ExpressionCodeTreeConstruct.cs
new file mode 100644
index 000000000..6ccde976f
--- /dev/null
+++ b/src/MsgPack.CodeGeneration.CSharp/Serialization/CodeTreeSerializers/ExpressionCodeTreeConstruct.cs
@@ -0,0 +1,54 @@
+#region -- License Terms --
+//
+// MessagePack for CLI
+//
+// Copyright (C) 2016 FUJIWARA, Yusuke
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion -- License Terms --
+
+using System;
+using System.Collections.Generic;
+
+#if CSHARP
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+#elif VISUAL_BASIC
+using Microsoft.CodeAnalysis.VisualBasic;
+using Microsoft.CodeAnalysis.VisualBasic.Syntax;
+#endif
+
+using MsgPack.Serialization.AbstractSerializers;
+
+namespace MsgPack.Serialization.CodeTreeSerializers
+{
+ internal sealed class ExpressionCodeTreeConstruct : CodeTreeConstruct
+ {
+ private readonly ExpressionSyntax _expression;
+
+ public override bool IsExpression => true;
+
+ public ExpressionCodeTreeConstruct( TypeDefinition contextType, ExpressionSyntax expression )
+ : base( contextType )
+ {
+ this._expression = expression;
+ }
+
+ public override ExpressionSyntax AsExpression() => this._expression;
+
+ public override IEnumerable AsStatements() => new StatementSyntax[] { SyntaxFactory.ExpressionStatement( this._expression ) };
+
+ public override string ToString() => this._expression.ToString();
+ }
+}
\ No newline at end of file
diff --git a/src/MsgPack.CodeGeneration.CSharp/Serialization/CodeTreeSerializers/ParameterCodeTreeConstruct.cs b/src/MsgPack.CodeGeneration.CSharp/Serialization/CodeTreeSerializers/ParameterCodeTreeConstruct.cs
new file mode 100644
index 000000000..bcb755ad6
--- /dev/null
+++ b/src/MsgPack.CodeGeneration.CSharp/Serialization/CodeTreeSerializers/ParameterCodeTreeConstruct.cs
@@ -0,0 +1,62 @@
+#region -- License Terms --
+//
+// MessagePack for CLI
+//
+// Copyright (C) 2016 FUJIWARA, Yusuke
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion -- License Terms --
+
+using System;
+
+#if CSHARP
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+#elif VISUAL_BASIC
+using Microsoft.CodeAnalysis.VisualBasic;
+using Microsoft.CodeAnalysis.VisualBasic.Syntax;
+using static Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory;
+#endif
+
+using MsgPack.Serialization.AbstractSerializers;
+
+namespace MsgPack.Serialization.CodeTreeSerializers
+{
+ internal sealed class ParameterCodeTreeConstruct : CodeTreeConstruct
+ {
+ private readonly IdentifierNameSyntax _identifierName;
+ private readonly ParameterSyntax _parameter;
+
+ public override bool IsExpression => true;
+
+ public ParameterCodeTreeConstruct( TypeDefinition contextType, IdentifierNameSyntax expression )
+ : base( contextType )
+ {
+ this._identifierName = expression;
+ this._parameter =
+#if CSHARP
+ SyntaxFactory.Parameter( this._identifierName.Identifier )
+#elif VISUAL_BASIC
+ SyntaxFactory.Parameter( ModifiedIdentifier( this._identifierName.Identifier ) )
+#endif
+ .WithType( Syntax.ToTypeSyntax( contextType ) );
+ }
+
+ public override ParameterSyntax AsParameter() => this._parameter;
+
+ public override ExpressionSyntax AsExpression() => this._identifierName;
+
+ public override string ToString() => this._parameter.ToString();
+ }
+}
\ No newline at end of file
diff --git a/src/MsgPack.CodeGeneration.CSharp/Serialization/CodeTreeSerializers/StatementCodeTreeConstruct.cs b/src/MsgPack.CodeGeneration.CSharp/Serialization/CodeTreeSerializers/StatementCodeTreeConstruct.cs
new file mode 100644
index 000000000..5a3bdacad
--- /dev/null
+++ b/src/MsgPack.CodeGeneration.CSharp/Serialization/CodeTreeSerializers/StatementCodeTreeConstruct.cs
@@ -0,0 +1,49 @@
+#region -- License Terms --
+//
+// MessagePack for CLI
+//
+// Copyright (C) 2016 FUJIWARA, Yusuke
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion -- License Terms --
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+#if CSHARP
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+#elif VISUAL_BASIC
+using Microsoft.CodeAnalysis.VisualBasic.Syntax;
+#endif
+
+namespace MsgPack.Serialization.CodeTreeSerializers
+{
+ internal sealed class StatementCodeTreeConstruct : CodeTreeConstruct
+ {
+ private readonly StatementSyntax[] _statements;
+
+ public override bool IsStatement => true;
+
+ public StatementCodeTreeConstruct( IEnumerable statements )
+ : base( typeof( void ) )
+ {
+ this._statements = statements.ToArray();
+ }
+
+ public override IEnumerable AsStatements() => this._statements;
+
+ public override string ToString() => $"[{String.Join( ", ", this._statements as IEnumerable )}]";
+ }
+}
\ No newline at end of file
diff --git a/src/MsgPack.CodeGeneration.CSharp/Serialization/CodeTreeSerializers/Syntax.cs b/src/MsgPack.CodeGeneration.CSharp/Serialization/CodeTreeSerializers/Syntax.cs
new file mode 100644
index 000000000..f89309841
--- /dev/null
+++ b/src/MsgPack.CodeGeneration.CSharp/Serialization/CodeTreeSerializers/Syntax.cs
@@ -0,0 +1,171 @@
+#region -- License Terms --
+//
+// MessagePack for CLI
+//
+// Copyright (C) 2016 FUJIWARA, Yusuke
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion -- License Terms --
+
+using System;
+using System.Linq;
+using System.Reflection;
+using System.Threading;
+using System.Threading.Tasks;
+
+using Microsoft.CodeAnalysis;
+#if CSHARP
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
+#elif VISUAL_BASIC
+using Microsoft.CodeAnalysis.VisualBasic;
+using Microsoft.CodeAnalysis.VisualBasic.Syntax;
+using static Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory;
+#endif
+
+using MsgPack.Serialization.AbstractSerializers;
+
+namespace MsgPack.Serialization.CodeTreeSerializers
+{
+ ///
+ /// Known syntax declarations.
+ ///
+ internal static class Syntax
+ {
+ public static readonly ExpressionSyntax NullLiteralSyntax =
+#if CSHARP
+ LiteralExpression( SyntaxKind.NullLiteralExpression );
+#elif VISUAL_BASIC
+ NothingLiteralExpression( Token( SyntaxKind.NothingKeyword ) );
+#endif
+ public static readonly SyntaxTokenList PublicKeyword =
+ TokenList( Token( SyntaxKind.PublicKeyword ) );
+
+ public static readonly SyntaxTokenList PrivateInstanceKeyword =
+ TokenList( Token( SyntaxKind.PrivateKeyword ) );
+
+ public static readonly SyntaxTokenList PrivateReadOnlyKeyword =
+ TokenList( Token( SyntaxKind.PrivateKeyword ), Token( SyntaxKind.ReadOnlyKeyword ) );
+
+ public static readonly SyntaxTokenList PrivateStaticKeyword =
+#if CSHARP
+ TokenList( Token( SyntaxKind.PrivateKeyword ), Token( SyntaxKind.StaticKeyword ) );
+#elif VISUAL_BASIC
+ TokenList( Token( SyntaxKind.PrivateKeyword ), Token( SyntaxKind.SharedKeyword ) );
+#endif
+
+ public static readonly SyntaxTokenList ProtectedOverrideKeyword =
+#if CSHARP
+ TokenList( Token( SyntaxKind.ProtectedKeyword ), Token( SyntaxKind.OverrideKeyword ) );
+#elif VISUAL_BASIC
+ TokenList( Token( SyntaxKind.ProtectedKeyword ), Token( SyntaxKind.OverridesKeyword ) );
+#endif
+
+ public static readonly SyntaxTokenList ProtectedInternalOverrideKeyword =
+#if CSHARP
+ TokenList( Token( SyntaxKind.ProtectedKeyword ), Token( SyntaxKind.InternalKeyword ), Token( SyntaxKind.OverrideKeyword ) );
+#elif VISUAL_BASIC
+ TokenList( Token( SyntaxKind.ProtectedKeyword ), Token( SyntaxKind.AssemblyKeyword ), Token( SyntaxKind.OverridesKeyword ) );
+#endif
+
+ public static readonly TypeSyntax VoidTypeSyntax =
+#if CSHARP
+ PredefinedType( Token( SyntaxKind.VoidKeyword ) );
+#elif VISUAL_BASIC
+ null;
+#endif
+
+ public static readonly TypeSyntax Int32TypeSyntax =
+#if CSHARP
+ PredefinedType( Token( SyntaxKind.IntKeyword ) );
+#elif VISUAL_BASIC
+ PredefinedType( Token( SyntaxKind.IntegerKeyword ) );
+#endif
+
+
+ public static readonly TypeSyntax MessagePackObjectTypeSyntax = IdentifierName( typeof( MessagePackObject ).Name );
+
+ public static readonly TypeSyntax TaskTypeSyntax = IdentifierName( typeof( Task ).Name );
+
+ public static readonly TypeSyntax CancellationTokenTypeSyntax = IdentifierName( typeof( CancellationToken ).Name );
+
+ public static readonly TypeSyntax MethodInfoTypeSyntax = IdentifierName( typeof( MethodInfo ).Name );
+
+ public static readonly TypeSyntax FieldInfoTypeSyntax = IdentifierName( typeof( FieldInfo ).Name );
+
+ public static readonly TypeSyntax ObjectTypeSyntax = ToTypeSyntax( TypeDefinition.ObjectType );
+
+ public static readonly TypeSyntax SerializationContextTypeSyntax = ToTypeSyntax( TypeDefinition.SerializationContextType );
+
+ public static readonly SyntaxTrivia BlankLine = SyntaxTrivia( SyntaxKind.EndOfLineTrivia, "\r\n" );
+
+
+ private static string GetGenericTypeBaseName( TypeDefinition genericType )
+ {
+ return
+ genericType.HasRuntimeTypeFully()
+ ? genericType.ResolveRuntimeType().FullName.Remove( genericType.ResolveRuntimeType().FullName.IndexOf( '`' ) )
+ : genericType.TypeName;
+ }
+
+ public static TypeSyntax ToTypeSyntax( TypeDefinition type )
+ {
+ if ( type.IsArray )
+ {
+ return ArrayType( ToTypeSyntax( type.ElementType ) );
+ }
+
+ if ( type.HasRuntimeTypeFully() )
+ {
+ if ( type.GenericArguments.Length == 0 )
+ {
+ return IdentifierName( type.ResolveRuntimeType().FullName );
+ }
+ else
+ {
+ return
+ GenericName(
+ Identifier( GetGenericTypeBaseName( type ) ),
+ TypeArgumentList(
+ new SeparatedSyntaxList().AddRange(
+ type.GenericArguments.Select( ToTypeSyntax )
+ )
+ )
+ );
+ }
+ }
+ else
+ {
+ if ( type.GenericArguments.Length == 0 )
+ {
+ return IdentifierName( type.TypeName );
+ }
+ else
+ {
+ return
+ GenericName(
+ Identifier( type.TypeName ),
+ TypeArgumentList(
+ new SeparatedSyntaxList().AddRange(
+ type.GenericArguments.Select( ToTypeSyntax )
+ )
+ )
+ );
+ }
+ }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/MsgPack.CodeGeneration.CSharp/Serialization/CodeTreeSerializers/SyntaxCompatibilities.cs b/src/MsgPack.CodeGeneration.CSharp/Serialization/CodeTreeSerializers/SyntaxCompatibilities.cs
new file mode 100644
index 000000000..3e5f4e32a
--- /dev/null
+++ b/src/MsgPack.CodeGeneration.CSharp/Serialization/CodeTreeSerializers/SyntaxCompatibilities.cs
@@ -0,0 +1,101 @@
+#region -- License Terms --
+//
+// MessagePack for CLI
+//
+// Copyright (C) 2016 FUJIWARA, Yusuke
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion -- License Terms --
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
+
+namespace MsgPack.Serialization.CodeTreeSerializers
+{
+ internal static class SyntaxCompatibilities
+ {
+ public static BinaryExpressionSyntax AndAlsoExpression( ExpressionSyntax left, ExpressionSyntax right ) =>
+ BinaryExpression( SyntaxKind.LogicalAndExpression, left, right );
+
+ public static ConstructorInitializerSyntax BaseConstructorInitializer( ArgumentListSyntax argumentList ) =>
+ ConstructorInitializer( SyntaxKind.BaseConstructorInitializer, argumentList );
+
+ public static ConstructorDeclarationSyntax ConstructorDeclaration( string identifier, SyntaxTokenList accessibility ) =>
+ SyntaxFactory.ConstructorDeclaration( identifier ).WithModifiers( accessibility );
+
+ public static FieldDeclarationSyntax FieldDeclaration( TypeSyntax type, string identifier ) =>
+ SyntaxFactory.FieldDeclaration( VariableDeclaration( type ).AddVariables( VariableDeclarator( identifier ) ) );
+
+ public static GenericNameSyntax GenericName( string baseName, params TypeSyntax[] genericArguments ) =>
+ SyntaxFactory.GenericName( baseName ).AddTypeArgumentListArguments( genericArguments );
+
+ public static GenericNameSyntax GenericName( string baseName, IEnumerable genericArguments ) =>
+ SyntaxFactory.GenericName( baseName ).AddTypeArgumentListArguments( genericArguments.ToArray() );
+
+ public static IfStatementSyntax IfElseStatement( ExpressionSyntax conditionExpression, IEnumerable thenStatements, IEnumerable elseStatements ) =>
+ IfStatement(
+ conditionExpression,
+ Block(
+ thenStatements
+ ),
+ ElseClause(
+ Block(
+ elseStatements
+ )
+ )
+ );
+
+ public static BinaryExpressionSyntax OrExpression( ExpressionSyntax left, ExpressionSyntax right ) =>
+ BinaryExpression( SyntaxKind.BitwiseOrExpression, left, right );
+
+ public static StatementSyntax SimpleAssignmentStatement( ExpressionSyntax left, ExpressionSyntax right ) =>
+ ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, left, right ) );
+
+ public static MemberAccessExpressionSyntax SimpleMemberAccessExpression( ExpressionSyntax expression, SimpleNameSyntax name ) =>
+ MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, expression, name );
+
+ public static ArrayCreationExpressionSyntax SZArrayCreationExpression( TypeSyntax elementType, ExpressionSyntax length ) =>
+ SyntaxFactory.ArrayCreationExpression(
+ ArrayType(
+ elementType,
+ new SyntaxList().Add(
+ ArrayRankSpecifier().AddSizes( length )
+ )
+ )
+ );
+
+ public static ArrayCreationExpressionSyntax SZArrayCreationExpression( TypeSyntax elementType, ExpressionSyntax length, IEnumerable initializerExpressions ) =>
+ SyntaxFactory.ArrayCreationExpression(
+ ArrayType(
+ elementType,
+ new SyntaxList().Add(
+ ArrayRankSpecifier().AddSizes( length )
+ )
+ ),
+ InitializerExpression(
+ SyntaxKind.ArrayInitializerExpression,
+ new SeparatedSyntaxList().AddRange( initializerExpressions )
+ )
+ );
+
+
+ public static string GetIdentifierText( this ParameterSyntax source ) => source.Identifier.ValueText;
+ }
+}
\ No newline at end of file
diff --git a/src/MsgPack.CodeGeneration.CSharp/Serialization/CodeTreeSerializers/VariableCodeTreeConstruct.cs b/src/MsgPack.CodeGeneration.CSharp/Serialization/CodeTreeSerializers/VariableCodeTreeConstruct.cs
new file mode 100644
index 000000000..007cc3957
--- /dev/null
+++ b/src/MsgPack.CodeGeneration.CSharp/Serialization/CodeTreeSerializers/VariableCodeTreeConstruct.cs
@@ -0,0 +1,72 @@
+#region -- License Terms --
+//
+// MessagePack for CLI
+//
+// Copyright (C) 2016 FUJIWARA, Yusuke
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion -- License Terms --
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using Microsoft.CodeAnalysis;
+#if CSHARP
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
+#elif VISUAL_BASIC
+using Microsoft.CodeAnalysis.VisualBasic;
+using Microsoft.CodeAnalysis.VisualBasic.Syntax;
+using static Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory;
+using VariableDeclarationSyntax = Microsoft.CodeAnalysis.VisualBasic.Syntax.LocalDeclarationStatementSyntax;
+#endif
+
+using MsgPack.Serialization.AbstractSerializers;
+
+namespace MsgPack.Serialization.CodeTreeSerializers
+{
+ internal sealed class VariableCodeTreeConstruct : CodeTreeConstruct
+ {
+ private readonly VariableDeclarationSyntax _syntax;
+ private readonly IdentifierNameSyntax _identifierName;
+
+ public override bool IsExpression => true;
+
+ public override bool IsStatement => true;
+
+ public VariableCodeTreeConstruct( TypeDefinition contextType, VariableDeclarationSyntax syntax )
+ : base( contextType )
+ {
+ this._syntax = syntax;
+#if CSHARP
+ this._identifierName = IdentifierName( syntax.Variables.Single().Identifier );
+#elif VISUAL_BASIC
+ this._identifierName = IdentifierName( syntax.Declarators.Single().Names.Single().Identifier );
+#endif
+ }
+
+ public override ExpressionSyntax AsExpression() => this._identifierName;
+
+ public override IEnumerable AsStatements() =>
+#if CSHARP
+ new StatementSyntax[] { LocalDeclarationStatement( this._syntax ) };
+#elif VISUAL_BASIC
+ new StatementSyntax[] { LocalDeclarationStatement( this._syntax.Modifiers, this._syntax.Declarators ) };
+#endif
+
+ public override string ToString() => this._identifierName.ToString();
+ }
+}
\ No newline at end of file
diff --git a/src/MsgPack.CodeGeneration.CSharp/project.json b/src/MsgPack.CodeGeneration.CSharp/project.json
new file mode 100644
index 000000000..b211574e0
--- /dev/null
+++ b/src/MsgPack.CodeGeneration.CSharp/project.json
@@ -0,0 +1,10 @@
+{
+ "supports": {},
+ "dependencies": {
+ "Microsoft.CodeAnalysis.CSharp": "1.3.2",
+ "System.Diagnostics.Process": "4.1.0"
+ },
+ "frameworks": {
+ "netstandard1.3": {}
+ }
+}
\ No newline at end of file
diff --git a/src/MsgPack.CodeGeneration.Core/MsgPack.CodeGeneration.Core.csproj b/src/MsgPack.CodeGeneration.Core/MsgPack.CodeGeneration.Core.csproj
new file mode 100644
index 000000000..fd19158a6
--- /dev/null
+++ b/src/MsgPack.CodeGeneration.Core/MsgPack.CodeGeneration.Core.csproj
@@ -0,0 +1,103 @@
+
+
+
+
+ 14.0
+ Debug
+ AnyCPU
+ {EFE532EA-77C8-4877-96C2-E79FD101B2AB}
+ Library
+ Properties
+ MsgPack
+ MsgPack.CodeGeneration.Core
+ ja-JP
+ 512
+ {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+
+
+ v5.0
+
+
+ true
+ full
+ false
+ bin\Debug\
+ TRACE;DEBUG;FEATURE_CONCURRENT;NETSTANDARD1_3
+ prompt
+ 4
+ bin\Debug\MsgPack.CodeGeneration.Core.XML
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE;FEATURE_CONCURRENT;NETSTANDARD1_3
+ prompt
+ 4
+ bin\Release\MsgPack.CodeGeneration.Core.XML
+
+
+ true
+
+
+ ..\MsgPack.snk
+
+
+
+
+ MsgPack.snk
+
+
+
+
+
+ Properties\CommonAssemblyInfo.cs
+
+
+ Serialization\AbstractSerializers\ISerializerCodeGenerationContext.cs
+
+
+ Serialization\AbstractSerializers\ISerializerCodeGenerator.cs
+
+
+ Serialization\CodeGenerators\SerializerCodeGeneratorFactory.cs
+
+
+ Serialization\CodeGenerators\SerializerGenerationLogic`1.cs
+
+
+ Serialization\SerializerCodeGenerationConfiguration.cs
+
+
+ Serialization\SerializerCodeGenerationResult.cs
+
+
+ Serialization\SerializerGenerator.cs
+
+
+ Validation.cs
+
+
+
+
+
+
+
+
+ {08d9a49d-736e-4cad-919e-72ca8c1d4a9f}
+ MsgPack.Core
+
+
+ {153ced68-9905-4b1f-9790-f463840895e2}
+ MsgPack.Serialization
+
+
+
+
+
\ No newline at end of file
diff --git a/src/MsgPack.CodeGeneration.Core/Properties/AssemblyInfo.cs b/src/MsgPack.CodeGeneration.Core/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..f53f63e68
--- /dev/null
+++ b/src/MsgPack.CodeGeneration.Core/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+#region -- License Terms --
+//
+// MessagePack for CLI
+//
+// Copyright (C) 2016 FUJIWARA, Yusuke
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion -- License Terms --
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Security;
+
+[assembly: AssemblyTitle( "MessagePack for CLI(.NET/Mono)" )]
+[assembly: AssemblyDescription( "MessagePack for CLI(.NET/Mono) code generator core library." )]
+
+[assembly: AssemblyFileVersion( "0.7.2259.1047" )]
+
+[assembly: InternalsVisibleTo( "MsgPack.CodeGeneration.CSharp, PublicKey=0024000004800000940000000602000000240000525341310004000001000100a967de8de9d45380b93a6aa56f64fc2cb2d3c9d4b400e00de01f31ba9e15cf5ca95926dbf8760cce413eabd711e23df0c133193a570da8a3bb1bdc00ef170fccb2bc033266fa5346442c9cf0b071133d5b484845eab17095652aeafeeb71193506b8294d9c8c91e3fd01cc50bdbc2d0eb78dd655bb8cd0bd3cdbbcb192549cb4" )]
+[assembly: InternalsVisibleTo( "MsgPack.CodeGeneration.VisualBasic, PublicKey=0024000004800000940000000602000000240000525341310004000001000100a967de8de9d45380b93a6aa56f64fc2cb2d3c9d4b400e00de01f31ba9e15cf5ca95926dbf8760cce413eabd711e23df0c133193a570da8a3bb1bdc00ef170fccb2bc033266fa5346442c9cf0b071133d5b484845eab17095652aeafeeb71193506b8294d9c8c91e3fd01cc50bdbc2d0eb78dd655bb8cd0bd3cdbbcb192549cb4" )]
+
+#if DEBUG || PERFORMANCE_TEST
+[assembly: InternalsVisibleTo( "MsgPack.UnitTest.CodeTree, PublicKey=0024000004800000940000000602000000240000525341310004000001000100a967de8de9d45380b93a6aa56f64fc2cb2d3c9d4b400e00de01f31ba9e15cf5ca95926dbf8760cce413eabd711e23df0c133193a570da8a3bb1bdc00ef170fccb2bc033266fa5346442c9cf0b071133d5b484845eab17095652aeafeeb71193506b8294d9c8c91e3fd01cc50bdbc2d0eb78dd655bb8cd0bd3cdbbcb192549cb4" )]
+#endif
+
diff --git a/src/MsgPack.CodeGeneration.Core/Serialization/CodeGenerators/CodeTreeSerializerCodeGeneratorFactory.cs b/src/MsgPack.CodeGeneration.Core/Serialization/CodeGenerators/CodeTreeSerializerCodeGeneratorFactory.cs
new file mode 100644
index 000000000..043d002c8
--- /dev/null
+++ b/src/MsgPack.CodeGeneration.Core/Serialization/CodeGenerators/CodeTreeSerializerCodeGeneratorFactory.cs
@@ -0,0 +1,85 @@
+#region -- License Terms --
+//
+// MessagePack for CLI
+//
+// Copyright (C) 2016 FUJIWARA, Yusuke and contributors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion -- License Terms --
+
+using System;
+using System.Collections.Concurrent;
+using System.Globalization;
+
+using MsgPack.Serialization.AbstractSerializers;
+
+namespace MsgPack.Serialization.CodeGenerators
+{
+ internal sealed class CodeTreeSerializerCodeGeneratorFactory : SerializerCodeGeneratorFactory
+ {
+ private static readonly string[] GeneratorKeys =
+ new[] { "roslyn", "codetree", "codeanalyzer" };
+
+ public static readonly CodeTreeSerializerCodeGeneratorFactory Instance = new CodeTreeSerializerCodeGeneratorFactory();
+
+ private readonly ConcurrentDictionary _factories = new ConcurrentDictionary( StringComparer.OrdinalIgnoreCase );
+
+ private CodeTreeSerializerCodeGeneratorFactory() { }
+
+ public static void EnsureInitialized() => SerializerGenerator.RegisterGenerator( GeneratorKeys, Instance );
+
+ public static void RegisterFactory(
+ string[] languages,
+ Func contextFactory,
+ Func> generatorFactory
+ )
+ {
+ foreach ( var language in languages )
+ {
+ Instance._factories[ language ] = new Factories( contextFactory, generatorFactory );
+ }
+ }
+
+ internal override SerializerGenerationLogic Create( SerializerCodeGenerationConfiguration configuration )
+ {
+ Factories factories;
+ if ( !this._factories.TryGetValue( configuration.Language, out factories ) )
+ {
+ throw new InvalidOperationException(
+ String.Format(
+ CultureInfo.CurrentCulture,
+ "Code analyzer based code generator is not registered for language '{0}'",
+ configuration.Language
+ )
+ );
+ }
+ return new CodeTreeSerializerGenerationLogic( factories.ContextFactory, factories.GeneratorFactory );
+ }
+
+ private struct Factories
+ {
+ public readonly Func ContextFactory;
+ public readonly Func> GeneratorFactory;
+
+ public Factories(
+ Func contextFactory,
+ Func> generatorFactory
+ )
+ {
+ this.ContextFactory = contextFactory;
+ this.GeneratorFactory = generatorFactory;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/MsgPack.CodeGeneration.Core/Serialization/CodeGenerators/CodeTreeSerializerGenerationLogic.cs b/src/MsgPack.CodeGeneration.Core/Serialization/CodeGenerators/CodeTreeSerializerGenerationLogic.cs
new file mode 100644
index 000000000..a307bf23c
--- /dev/null
+++ b/src/MsgPack.CodeGeneration.Core/Serialization/CodeGenerators/CodeTreeSerializerGenerationLogic.cs
@@ -0,0 +1,50 @@
+#region -- License Terms --
+//
+// MessagePack for CLI
+//
+// Copyright (C) 2016 FUJIWARA, Yusuke and contributors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion -- License Terms --
+
+using System;
+
+using MsgPack.Serialization.AbstractSerializers;
+
+namespace MsgPack.Serialization.CodeGenerators
+{
+ internal sealed class CodeTreeSerializerGenerationLogic : SerializerGenerationLogic
+ {
+ private readonly Func _contextFactory;
+ private readonly Func> _generatorFactory;
+
+ public CodeTreeSerializerGenerationLogic(
+ Func contextFactory,
+ Func> generatorFactory
+ )
+ {
+ this._contextFactory = contextFactory;
+ this._generatorFactory = generatorFactory;
+ }
+
+ // Just returns random stuff.
+ protected override EmitterFlavor EmitterFlavor => EmitterFlavor.FieldBased;
+
+ protected override ISerializerCodeGenerationContext CreateGenerationContext( SerializationContext context, SerializerCodeGenerationConfiguration configuration )
+ => this._contextFactory( context, configuration );
+
+ protected override Func CreateGeneratorFactory( SerializationContext context )
+ => this._generatorFactory( context );
+ }
+}
\ No newline at end of file
diff --git a/src/MsgPack.CodeGeneration.Core/project.json b/src/MsgPack.CodeGeneration.Core/project.json
new file mode 100644
index 000000000..662e36f78
--- /dev/null
+++ b/src/MsgPack.CodeGeneration.Core/project.json
@@ -0,0 +1,10 @@
+{
+ "supports": {},
+ "dependencies": {
+ "System.IO.FileSystem": "4.0.1",
+ "System.Text.RegularExpressions": "4.1.0"
+ },
+ "frameworks": {
+ "netstandard1.3": {}
+ }
+}
\ No newline at end of file
diff --git a/src/MsgPack.CodeGeneration.VisualBasic/MsgPack.CodeGeneration.VisualBasic.csproj b/src/MsgPack.CodeGeneration.VisualBasic/MsgPack.CodeGeneration.VisualBasic.csproj
new file mode 100644
index 000000000..436612b2a
--- /dev/null
+++ b/src/MsgPack.CodeGeneration.VisualBasic/MsgPack.CodeGeneration.VisualBasic.csproj
@@ -0,0 +1,111 @@
+
+
+
+
+ 14.0
+ Debug
+ AnyCPU
+ {A88D64DB-DE14-4B77-80D8-B765F45EBB8B}
+ Library
+ Properties
+ MsgPack
+ MsgPack.CodeGeneration.VisualBasic
+ ja-JP
+ 512
+ {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+
+
+ v5.0
+
+
+ true
+ full
+ false
+ bin\Debug\
+ TRACE;DEBUG;NETSTANDARD1_3;VISUAL_BASIC
+ prompt
+ 4
+ bin\Debug\MsgPack.CodeGeneration.VisualBasic.XML
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE;NETSTANDARD1_3;VISUAL_BASIC
+ prompt
+ 4
+ bin\Release\MsgPack.CodeGeneration.VisualBasic.XML
+
+
+ true
+
+
+ ..\MsgPack.snk
+
+
+
+
+ MsgPack.snk
+
+
+
+
+
+ Properties\CommonAssemblyInfo.cs
+
+
+ Serialization\CodeTreeSerializers\CodeTreeConstruct.cs
+
+
+ Serialization\CodeTreeSerializers\CodeTreeContext.cs
+
+
+ Serialization\CodeTreeSerializers\CodeTreeSerializerBuilder.cs
+
+
+ Serialization\CodeTreeSerializers\ExpressionCodeTreeConstruct.cs
+
+
+ Serialization\CodeTreeSerializers\ParameterCodeTreeConstruct.cs
+
+
+ Serialization\CodeTreeSerializers\StatementCodeTreeConstruct.cs
+
+
+ Serialization\CodeTreeSerializers\Syntax.cs
+
+
+ Serialization\CodeTreeSerializers\VariableCodeTreeConstruct.cs
+
+
+
+
+
+
+
+ {efe532ea-77c8-4877-96c2-e79fd101b2ab}
+ MsgPack.CodeGeneration.Core
+
+
+ {08d9a49d-736e-4cad-919e-72ca8c1d4a9f}
+ MsgPack.Core
+
+
+ {153ced68-9905-4b1f-9790-f463840895e2}
+ MsgPack.Serialization
+
+
+
+
+ C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6\Microsoft.VisualC.dll
+
+
+
+
+
\ No newline at end of file
diff --git a/src/MsgPack.CodeGeneration.VisualBasic/Properties/AssemblyInfo.cs b/src/MsgPack.CodeGeneration.VisualBasic/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..04e311f80
--- /dev/null
+++ b/src/MsgPack.CodeGeneration.VisualBasic/Properties/AssemblyInfo.cs
@@ -0,0 +1,34 @@
+#region -- License Terms --
+//
+// MessagePack for CLI
+//
+// Copyright (C) 2016 FUJIWARA, Yusuke
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion -- License Terms --
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Security;
+
+[assembly: AssemblyTitle( "MessagePack for CLI(.NET/Mono)" )]
+[assembly: AssemblyDescription( "MessagePack for CLI(.NET/Mono) Visual Basic code generator library." )]
+
+[assembly: AssemblyFileVersion( "0.7.2259.1047" )]
+
+#if DEBUG || PERFORMANCE_TEST
+[assembly: InternalsVisibleTo( "MsgPack.UnitTest.CodeTree, PublicKey=0024000004800000940000000602000000240000525341310004000001000100a967de8de9d45380b93a6aa56f64fc2cb2d3c9d4b400e00de01f31ba9e15cf5ca95926dbf8760cce413eabd711e23df0c133193a570da8a3bb1bdc00ef170fccb2bc033266fa5346442c9cf0b071133d5b484845eab17095652aeafeeb71193506b8294d9c8c91e3fd01cc50bdbc2d0eb78dd655bb8cd0bd3cdbbcb192549cb4" )]
+#endif
+
+
diff --git a/src/MsgPack.CodeGeneration.VisualBasic/Serialization/CodeGenerators/VisualBasicCodeTreeBasedSerializerCodeGenerator.cs b/src/MsgPack.CodeGeneration.VisualBasic/Serialization/CodeGenerators/VisualBasicCodeTreeBasedSerializerCodeGenerator.cs
new file mode 100644
index 000000000..391ccb71c
--- /dev/null
+++ b/src/MsgPack.CodeGeneration.VisualBasic/Serialization/CodeGenerators/VisualBasicCodeTreeBasedSerializerCodeGenerator.cs
@@ -0,0 +1,53 @@
+#region -- License Terms --
+//
+// MessagePack for CLI
+//
+// Copyright (C) 2016 FUJIWARA, Yusuke
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion -- License Terms --
+
+using System;
+
+using MsgPack.Serialization.CodeTreeSerializers;
+
+namespace MsgPack.Serialization.CodeGenerators
+{
+ ///
+ /// Provides front-end for Roslyn Code Analyzer based, portable C# serializer source code generator.
+ ///
+ ///
+ /// You must call in advance to use Roslyn Code Analyzer based C# source code generation.
+ /// If you miss it, Code DOM based legacy generator is used in desktop .NET Framework build (including Mono), or failed on other (.NET Core, etc.) based build.
+ ///
+ public static class VisualBasicCodeTreeBasedSerializerCodeGenerator
+ {
+ // based on in root web.config.
+ private static readonly string[] LanguageIdentifiers =
+ new[] { "VB", "VBS", "VisualBasic", "VBScript" };
+
+ ///
+ /// Configures C# generator and enables in .
+ ///
+ public static void Configure()
+ {
+ CodeTreeSerializerCodeGeneratorFactory.EnsureInitialized();
+ CodeTreeSerializerCodeGeneratorFactory.RegisterFactory(
+ LanguageIdentifiers,
+ ( context, configuration ) => new CodeTreeContext( context, configuration, "cs" ),
+ context => type => new VisualBasicCodeTreeSerializerBuilder( type, type.GetCollectionTraits( CollectionTraitOptions.Full, context.CompatibilityOptions.AllowNonCollectionEnumerableTypes ) )
+ );
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/MsgPack.CodeGeneration.VisualBasic/Serialization/CodeTreeSerializers/SyntaxCompatibilities.cs b/src/MsgPack.CodeGeneration.VisualBasic/Serialization/CodeTreeSerializers/SyntaxCompatibilities.cs
new file mode 100644
index 000000000..14b67502a
--- /dev/null
+++ b/src/MsgPack.CodeGeneration.VisualBasic/Serialization/CodeTreeSerializers/SyntaxCompatibilities.cs
@@ -0,0 +1,152 @@
+#region -- License Terms --
+//
+// MessagePack for CLI
+//
+// Copyright (C) 2016 FUJIWARA, Yusuke
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion -- License Terms --
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.VisualBasic;
+using Microsoft.CodeAnalysis.VisualBasic.Syntax;
+using static Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory;
+
+namespace MsgPack.Serialization.CodeTreeSerializers
+{
+ internal static class SyntaxCompatibilities
+ {
+ public static SimpleArgumentSyntax Argument( ExpressionSyntax expression ) => SimpleArgument( expression );
+
+ public static SimpleArgumentSyntax AttributeArgument( ExpressionSyntax expression ) => SimpleArgument( expression );
+
+ public static ExpressionStatementSyntax BaseConstructorInitializer( ArgumentListSyntax argumentList ) =>
+ ExpressionStatement( InvocationExpression( SimpleMemberAccessExpression( MyBaseExpression(), IdentifierName( "New" ) ), argumentList ) );
+
+ public static SyntaxList Block( IEnumerable statements ) => new SyntaxList().AddRange( statements );
+
+ public static DirectCastExpressionSyntax CastExpression( TypeSyntax type, ExpressionSyntax expression ) => DirectCastExpression( expression, type );
+
+ public static ClassStatementSyntax ClassDeclaration( string identifier ) => ClassStatement( identifier );
+
+ public static InvocationExpressionSyntax ConditionalExpression( ExpressionSyntax conditionExpression, ExpressionSyntax thenExpression, ExpressionSyntax elseExpression ) =>
+ InvocationExpression(
+ MultiLineFunctionLambdaExpression(
+ FunctionLambdaHeader(),
+ EndFunctionStatement()
+ ).AddStatements(
+ MultiLineIfBlock(
+ SyntaxFactory.IfStatement( conditionExpression )
+ ).WithStatements( new SyntaxList().Add( ReturnStatement( thenExpression ) ) )
+ .WithElseBlock( ElseBlock( new SyntaxList().Add( ReturnStatement( elseExpression ) ) ) )
+ )
+ );
+
+ public static InvocationExpressionSyntax ElementAccessExpression( ExpressionSyntax typeOrInstance ) => InvocationExpression( typeOrInstance );
+
+ public static FinallyBlockSyntax FinallyClause( SyntaxList statements ) => FinallyBlock( statements );
+
+ public static ForEachBlockSyntax ForEachStatement( TypeSyntax variableType, string variableName, ExpressionSyntax collectionExpression, SyntaxList statements ) =>
+ ForEachBlock(
+ SyntaxFactory.ForEachStatement( VariableDeclarator( variableName ).WithAsClause( SimpleAsClause( variableType ) ), collectionExpression )
+ ).WithStatements( statements );
+
+ public static MultiLineIfBlockSyntax IfStatement( ExpressionSyntax conditionExpression, IEnumerable thenStatements ) =>
+ MultiLineIfBlock(
+ SyntaxFactory.IfStatement( conditionExpression )
+ ).WithStatements( Block( thenStatements ) );
+
+ public static MultiLineIfBlockSyntax IfElseStatement( ExpressionSyntax conditionExpression, IEnumerable thenStatements, IEnumerable elseStatements ) =>
+ MultiLineIfBlock(
+ SyntaxFactory.IfStatement( conditionExpression )
+ ).WithStatements( Block( thenStatements ) )
+ .WithElseBlock( ElseBlock( Block( elseStatements ) ) );
+
+ public static ExpressionSyntax MakeRefExpression( ExpressionSyntax expression ) => expression;
+
+ public static ArrayCreationExpressionSyntax SZArrayCreationExpression( TypeSyntax elementType, ExpressionSyntax length ) =>
+ ArrayCreationExpression(
+ elementType,
+ CollectionInitializer()
+ ).AddArrayBoundsArguments( Argument( length ) );
+
+ public static ArrayCreationExpressionSyntax SZArrayCreationExpression( TypeSyntax elementType, ExpressionSyntax length, IEnumerable initializerExpressions ) =>
+ ArrayCreationExpression(
+ elementType,
+ CollectionInitializer( new SeparatedSyntaxList().AddRange( initializerExpressions ) )
+ ).AddArrayBoundsArguments( Argument( length ) );
+
+ public static MeExpressionSyntax ThisExpression() => MeExpression();
+
+ public static GetTypeExpressionSyntax TypeOfExpression( TypeSyntax type ) => GetTypeExpression( type );
+
+ public static ImportsStatementSyntax UsingDirective( IdentifierNameSyntax identifier ) =>
+ ImportsStatement( new SeparatedSyntaxList().Add( SimpleImportsClause( identifier ) ) );
+
+ public static LocalDeclarationStatementSyntax VariableDeclaration( TypeSyntax type, SeparatedSyntaxList variables ) =>
+ LocalDeclarationStatement( TokenList( Token( SyntaxKind.DimKeyword ) ), variables );
+
+ public static VariableDeclaratorSyntax VariableDeclarator( string identifier ) =>
+ SyntaxFactory.VariableDeclarator( ModifiedIdentifier( identifier ) );
+
+ public static SubNewStatementSyntax ConstructorDeclaration( string identifier, SyntaxTokenList accessibility ) =>
+ SubNewStatement().WithModifiers( accessibility );
+
+ public static FieldDeclarationSyntax FieldDeclaration( TypeSyntax type, string identifier ) =>
+ SyntaxFactory.FieldDeclaration( VariableDeclarator( identifier ).WithAsClause( SimpleAsClause( type ) ) );
+
+ public static GenericNameSyntax GenericName( string baseName, params TypeSyntax[] genericArguments ) =>
+ SyntaxFactory.GenericName( baseName, TypeArgumentList( genericArguments ) );
+
+ public static GenericNameSyntax GenericName( string baseName, IEnumerable genericArguments ) =>
+ GenericName( baseName, genericArguments.ToArray() );
+
+ public static MethodStatementSyntax MethodDeclaration( TypeSyntax returnType, string identifier ) =>
+ returnType == null
+ ? SubStatement( identifier )
+ : FunctionStatement( identifier ).WithAsClause( SimpleAsClause( returnType ) );
+
+ public static NamespaceBlockSyntax NamespaceDeclaration( NameSyntax name ) =>
+ NamespaceBlock( NamespaceStatement( name ) );
+
+ public static TryBlockSyntax TryStatement( SyntaxList statements, SyntaxList catchBlocks, FinallyBlockSyntax finallyBlock ) =>
+ TryBlock( statements, catchBlocks, finallyBlock );
+
+
+ public static ConstructorBlockSyntax AddBodyStatements( this ConstructorBlockSyntax source, params StatementSyntax[] statements ) =>
+ source.AddStatements( statements );
+
+ public static string GetIdentifierText( this ParameterSyntax source ) => source.Identifier.Identifier.ValueText;
+
+ public static MethodBlockSyntax WithBody( this MethodStatementSyntax source, SyntaxList statements ) =>
+ ( source.SubOrFunctionKeyword.ValueText == "Sub" ? SubBlock( source ) : FunctionBlock( source ) )
+ .WithStatements( statements );
+
+ public static ConstructorBlockSyntax WithBody( this SubNewStatementSyntax source, SyntaxList statements ) =>
+ ConstructorBlock( source, statements );
+
+ public static ConstructorBlockSyntax WithInitializer( this SubNewStatementSyntax source, ExpressionStatementSyntax baseInitializer ) =>
+ ConstructorBlock( source, new SyntaxList().Add( baseInitializer ) );
+
+ public static ParameterSyntax WithType( this ParameterSyntax source, TypeSyntax type ) =>
+ source.WithAsClause( SimpleAsClause( type ) );
+
+ public static CompilationUnitSyntax WithUsings( this CompilationUnitSyntax source, SyntaxList imports ) =>
+ source.WithImports( imports );
+ }
+}
\ No newline at end of file
diff --git a/src/MsgPack.CodeGeneration.VisualBasic/project.json b/src/MsgPack.CodeGeneration.VisualBasic/project.json
new file mode 100644
index 000000000..fb4098b95
--- /dev/null
+++ b/src/MsgPack.CodeGeneration.VisualBasic/project.json
@@ -0,0 +1,10 @@
+{
+ "supports": {},
+ "dependencies": {
+ "Microsoft.CodeAnalysis.VisualBasic": "1.3.2",
+ "System.Diagnostics.Process": "4.1.0"
+ },
+ "frameworks": {
+ "netstandard1.3": {}
+ }
+}
\ No newline at end of file
diff --git a/src/MsgPack.Core/BufferedStream.cs b/src/MsgPack.Core/BufferedStream.cs
new file mode 100644
index 000000000..50e773e4e
--- /dev/null
+++ b/src/MsgPack.Core/BufferedStream.cs
@@ -0,0 +1,1294 @@
+// This file is based on https://github.com/dotnet/coreclr/blob/master/src/mscorlib/src/System/IO/BufferedStream.cs 814c2882a5c27ac40781bc20d6978708848784eb
+
+// ReSharper disable ArrangeThisQualifier
+// ReSharper disable CheckNamespace
+// ReSharper disable InconsistentNaming
+// ReSharper disable PossibleNullReferenceException
+// ReSharper disable RedundantUsingDirective
+
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/*============================================================
+**
+**
+**
+**
+** Purpose: A composable Stream that buffers reads & writes to the underlying stream.
+**
+**
+===========================================================*/
+using System;
+using System.Runtime.InteropServices;
+using System.Globalization;
+#if XAMIOS || XAMDROID || CORE_CLR || NETSTANDARD1_1
+using Contract = MsgPack.MPContract;
+#if CORE_CLR || NETSTANDARD1_1
+using PureAttribute = MsgPack.PureAttribute;
+#endif // CORE_CLR
+#else
+using System.Diagnostics.Contracts;
+#endif // XAMIOS || XAMDROID || CORE_CLR || NETSTANDARD1_1
+using System.Runtime.CompilerServices;
+using System.Threading;
+using System.Collections.ObjectModel;
+using System.Security;
+using System.Threading.Tasks;
+
+namespace System.IO
+{
+
+ ///
+ /// One of the design goals here is to prevent the buffer from getting in the way and slowing
+ /// down underlying stream accesses when it is not needed. If you always read & write for sizes
+ /// greater than the internal buffer size, then this class may not even allocate the internal buffer.
+ /// See a large comment in Write for the details of the write buffer heuristic.
+ ///
+ /// This class buffers reads & writes in a shared buffer.
+ /// (If you maintained two buffers separately, one operation would always trash the other buffer
+ /// anyways, so we might as well use one buffer.)
+ /// The assumption here is you will almost always be doing a series of reads or writes, but rarely
+ /// alternate between the two of them on the same stream.
+ ///
+ /// Class Invariants:
+ /// The class has one buffer, shared for reading & writing.
+ /// It can only be used for one or the other at any point in time - not both.
+ /// The following should be true:
+ /// 0 implies the read buffer is valid, but we're at the end of the buffer.
+ /// * _readPos == _readLen == 0 means the read buffer contains garbage.
+ /// * Either _writePos can be greater than 0, or _readLen & _readPos can be greater than zero,
+ /// but neither can be greater than zero at the same time.
+ /// ]]>
+ /// This class will never cache more bytes than the max specified buffer size.
+ /// However, it may use a temporary buffer of up to twice the size in order to combine several IO operations on
+ /// the underlying stream into a single operation. This is because we assume that memory copies are significantly
+ /// faster than IO operations on the underlying stream (if this was not true, using buffering is never appropriate).
+ /// The max size of this "shadow" buffer is limited as to not allocate it on the LOH.
+ /// Shadowing is always transient. Even when using this technique, this class still guarantees that the number of
+ /// bytes cached (not yet written to the target stream or not yet consumed by the user) is never larger than the
+ /// actual specified buffer size.
+ ///
+ [ComVisible( true )]
+ internal sealed class BufferedStream : Stream
+ {
+
+
+ private const Int32 _DefaultBufferSize = 4096;
+
+
+ private Stream _stream; // Underlying stream. Close sets _stream to null.
+
+ private Byte[] _buffer; // Shared read/write buffer. Alloc on first use.
+
+ private readonly Int32 _bufferSize; // Length of internal buffer (not counting the shadow buffer).
+
+ private Int32 _readPos; // Read pointer within shared buffer.
+ private Int32 _readLen; // Number of bytes read in buffer from _stream.
+ private Int32 _writePos; // Write pointer within shared buffer.
+
+ private Task _lastSyncCompletedReadTask; // The last successful Task returned from ReadAsync
+ // (perf optimization for successive reads of the same size)
+
+
+ // ReSharper disable once UnusedMember.Local
+ // Removing a private default constructor is a breaking change for the DataContractSerializer.
+ // Because this ctor was here previously we need to keep it around.
+ private BufferedStream() { }
+
+
+ public BufferedStream( Stream stream )
+
+ : this( stream, _DefaultBufferSize )
+ {
+ }
+
+
+ public BufferedStream( Stream stream, Int32 bufferSize )
+ {
+
+ if ( stream == null )
+ throw new ArgumentNullException( "stream" );
+
+ if ( bufferSize <= 0 )
+ throw new ArgumentOutOfRangeException( "bufferSize", "The value must be positive." );
+
+ Contract.EndContractBlock();
+
+ _stream = stream;
+ _bufferSize = bufferSize;
+
+ // Allocate _buffer on its first use - it will not be used if all reads
+ // & writes are greater than or equal to buffer size.
+
+ if ( !_stream.CanRead && !_stream.CanWrite )
+ __Error.StreamIsClosed();
+ }
+
+
+ private void EnsureNotClosed()
+ {
+
+ if ( _stream == null )
+ __Error.StreamIsClosed();
+ }
+
+
+ private void EnsureCanSeek()
+ {
+
+ Contract.Requires( _stream != null );
+
+ if ( !_stream.CanSeek )
+ __Error.SeekNotSupported();
+ }
+
+
+ private void EnsureCanRead()
+ {
+
+ Contract.Requires( _stream != null );
+
+ if ( !_stream.CanRead )
+ __Error.ReadNotSupported();
+ }
+
+
+ private void EnsureCanWrite()
+ {
+
+ Contract.Requires( _stream != null );
+
+ if ( !_stream.CanWrite )
+ __Error.WriteNotSupported();
+ }
+
+ /// MaxShadowBufferSize is chosed such that shadow buffers are not allocated on the Large Object Heap.
+ /// Currently, an object is allocated on the LOH if it is larger than 85000 bytes. See LARGE_OBJECT_SIZE in ndp\clr\src\vm\gc.h
+ /// We will go with exactly 80 KBytes, although this is somewhat arbitrary.
+ private const Int32 MaxShadowBufferSize = 81920; // Make sure not to get to the Large Object Heap.
+ private void EnsureShadowBufferAllocated()
+ {
+
+ Contract.Assert( _buffer != null );
+ Contract.Assert( _bufferSize > 0 );
+
+ // Already have shadow buffer?
+ if ( _buffer.Length != _bufferSize || _bufferSize >= MaxShadowBufferSize )
+ return;
+
+ Byte[] shadowBuffer = new Byte[Math.Min(_bufferSize + _bufferSize, MaxShadowBufferSize)];
+ Buffer.BlockCopy( _buffer, 0, shadowBuffer, 0, _writePos );
+ _buffer = shadowBuffer;
+ }
+
+
+ private void EnsureBufferAllocated()
+ {
+
+ Contract.Assert( _bufferSize > 0 );
+
+ // BufferedStream is not intended for multi-threaded use, so no worries about the get/set race conditions on _buffer.
+ if ( _buffer == null )
+ _buffer = new Byte[ _bufferSize ];
+ }
+
+
+ internal Stream UnderlyingStream
+ {
+ [Pure]
+ get
+ { return _stream; }
+ }
+
+
+ internal Int32 BufferSize
+ {
+ [Pure]
+ get
+ { return _bufferSize; }
+ }
+
+
+ public override bool CanRead
+ {
+ [Pure]
+ get
+ { return _stream != null && _stream.CanRead; }
+ }
+
+
+ public override bool CanWrite
+ {
+ [Pure]
+ get
+ { return _stream != null && _stream.CanWrite; }
+ }
+
+
+ public override bool CanSeek
+ {
+ [Pure]
+ get
+ { return _stream != null && _stream.CanSeek; }
+ }
+
+
+ public override Int64 Length
+ {
+ get
+ {
+ EnsureNotClosed();
+
+ if ( _writePos > 0 )
+ FlushWrite();
+
+ return _stream.Length;
+ }
+ }
+
+
+ public override Int64 Position
+ {
+ get
+ {
+ EnsureNotClosed();
+ EnsureCanSeek();
+
+ Contract.Assert( !( _writePos > 0 && _readPos != _readLen ), "Read and Write buffers cannot both have data in them at the same time." );
+ return _stream.Position + ( _readPos - _readLen + _writePos );
+ }
+ set
+ {
+ if ( value < 0 )
+ throw new ArgumentOutOfRangeException( "value", "The value cannot be negative." );
+ Contract.EndContractBlock();
+
+ EnsureNotClosed();
+ EnsureCanSeek();
+
+ if ( _writePos > 0 )
+ FlushWrite();
+
+ _readPos = 0;
+ _readLen = 0;
+ _stream.Seek( value, SeekOrigin.Begin );
+ }
+ }
+
+
+ protected override void Dispose( bool disposing )
+ {
+
+ try
+ {
+ if ( disposing && _stream != null )
+ {
+ try
+ {
+ Flush();
+ }
+ finally
+ {
+ _stream.Dispose();
+ }
+ }
+ }
+ finally
+ {
+ _stream = null;
+ _buffer = null;
+ _lastSyncCompletedReadTask = null;
+
+ // Call base.Dispose(bool) to cleanup async IO resources
+ base.Dispose( disposing );
+ }
+ }
+
+
+ public override void Flush()
+ {
+
+ EnsureNotClosed();
+
+ // Has WRITE data in the buffer:
+ if ( _writePos > 0 )
+ {
+
+ FlushWrite();
+ Contract.Assert( _writePos == 0 && _readPos == 0 && _readLen == 0 );
+ return;
+ }
+
+ // Has READ data in the buffer:
+ if ( _readPos < _readLen )
+ {
+
+ // If the underlying stream is not seekable AND we have something in the read buffer, then FlushRead would throw.
+ // We can either throw away the buffer resulting in data loss (!) or ignore the Flush.
+ // (We cannot throw becasue it would be a breaking change.) We opt into ignoring the Flush in that situation.
+ if ( !_stream.CanSeek )
+ return;
+
+ FlushRead();
+
+ // User streams may have opted to throw from Flush if CanWrite is false (although the abstract Stream does not do so).
+ // However, if we do not forward the Flush to the underlying stream, we may have problems when chaining several streams.
+ // Let us make a best effort attempt:
+ if ( _stream.CanWrite || _stream is BufferedStream )
+ _stream.Flush();
+
+ Contract.Assert( _writePos == 0 && _readPos == 0 && _readLen == 0 );
+ return;
+ }
+
+ // We had no data in the buffer, but we still need to tell the underlying stream to flush.
+ if ( _stream.CanWrite || _stream is BufferedStream )
+ _stream.Flush();
+
+ _writePos = _readPos = _readLen = 0;
+ }
+
+ public override Task FlushAsync( CancellationToken cancellationToken )
+ {
+
+ if ( cancellationToken.IsCancellationRequested )
+ return _Task.FromCancellation( cancellationToken );
+
+ EnsureNotClosed();
+
+ return FlushAsyncInternal( cancellationToken, this, _stream, _writePos, _readPos, _readLen );
+ }
+
+
+ private static async Task FlushAsyncInternal( CancellationToken cancellationToken,
+ BufferedStream _this, Stream stream, Int32 writePos, Int32 readPos, Int32 readLen )
+ {
+
+ // We bring instance fields down as local parameters to this async method becasue BufferedStream is derived from MarshalByRefObject.
+ // Field access would be from the async state machine i.e., not via the this pointer and would require runtime checking to see
+ // if we are talking to a remote object, which is currently very slow
+
+ Contract.Assert( stream != null );
+
+ SemaphoreSlim sem = _this.EnsureAsyncActiveSemaphoreInitialized();
+ await sem.WaitAsync().ConfigureAwait( false );
+ try
+ {
+
+ if ( writePos > 0 )
+ {
+
+ await _this.FlushWriteAsync( cancellationToken ).ConfigureAwait( false );
+ Contract.Assert( _this._writePos == 0 && _this._readPos == 0 && _this._readLen == 0 );
+ return;
+ }
+
+ if ( readPos < readLen )
+ {
+
+ // If the underlying stream is not seekable AND we have something in the read buffer, then FlushRead would throw.
+ // We can either throw away the buffer resulting in date loss (!) or ignore the Flush. (We cannot throw becasue it
+ // would be a breaking change.) We opt into ignoring the Flush in that situation.
+ if ( !stream.CanSeek )
+ return;
+
+ _this.FlushRead(); // not async; it uses Seek, but there's no SeekAsync
+
+ // User streams may have opted to throw from Flush if CanWrite is false (although the abstract Stream does not do so).
+ // However, if we do not forward the Flush to the underlying stream, we may have problems when chaining several streams.
+ // Let us make a best effort attempt:
+ if ( stream.CanRead || stream is BufferedStream )
+ await stream.FlushAsync( cancellationToken ).ConfigureAwait( false );
+
+ Contract.Assert( _this._writePos == 0 && _this._readPos == 0 && _this._readLen == 0 );
+ return;
+ }
+
+ // We had no data in the buffer, but we still need to tell the underlying stream to flush.
+ if ( stream.CanWrite || stream is BufferedStream )
+ await stream.FlushAsync( cancellationToken ).ConfigureAwait( false );
+
+ // There was nothing in the buffer:
+ Contract.Assert( _this._writePos == 0 && _this._readPos == _this._readLen );
+
+ }
+ finally
+ {
+ sem.Release();
+ }
+ }
+
+
+ // Reading is done in blocks, but someone could read 1 byte from the buffer then write.
+ // At that point, the underlying stream's pointer is out of sync with this stream's position.
+ // All write functions should call this function to ensure that the buffered data is not lost.
+ private void FlushRead()
+ {
+
+ Contract.Assert( _writePos == 0, "BufferedStream: Write buffer must be empty in FlushRead!" );
+
+ if ( _readPos - _readLen != 0 )
+ _stream.Seek( _readPos - _readLen, SeekOrigin.Current );
+
+ _readPos = 0;
+ _readLen = 0;
+ }
+
+
+ private void ClearReadBufferBeforeWrite()
+ {
+
+ // This is called by write methods to clear the read buffer.
+
+ Contract.Assert( _readPos <= _readLen, "_readPos <= _readLen [" + _readPos + " <= " + _readLen + "]" );
+
+ // No READ data in the buffer:
+ if ( _readPos == _readLen )
+ {
+
+ _readPos = _readLen = 0;
+ return;
+ }
+
+ // Must have READ data.
+ Contract.Assert( _readPos < _readLen );
+
+ // If the underlying stream cannot seek, FlushRead would end up throwing NotSupported.
+ // However, since the user did not call a method that is intuitively expected to seek, a better message is in order.
+ // Ideally, we would throw an InvalidOperation here, but for backward compat we have to stick with NotSupported.
+ if ( !_stream.CanSeek )
+ throw new NotSupportedException( "Cannot write stream because read buffer cannot be flushed." );
+
+ FlushRead();
+ }
+
+
+ private void FlushWrite()
+ {
+
+ Contract.Assert( _readPos == 0 && _readLen == 0,
+ "BufferedStream: Read buffer must be empty in FlushWrite!" );
+ Contract.Assert( _buffer != null && _bufferSize >= _writePos,
+ "BufferedStream: Write buffer must be allocated and write position must be in the bounds of the buffer in FlushWrite!" );
+
+ _stream.Write( _buffer, 0, _writePos );
+ _writePos = 0;
+ _stream.Flush();
+ }
+
+
+ private async Task FlushWriteAsync( CancellationToken cancellationToken )
+ {
+
+ Contract.Assert( _readPos == 0 && _readLen == 0,
+ "BufferedStream: Read buffer must be empty in FlushWrite!" );
+ Contract.Assert( _buffer != null && _bufferSize >= _writePos,
+ "BufferedStream: Write buffer must be allocated and write position must be in the bounds of the buffer in FlushWrite!" );
+
+ await _stream.WriteAsync( _buffer, 0, _writePos, cancellationToken ).ConfigureAwait( false );
+ _writePos = 0;
+ await _stream.FlushAsync( cancellationToken ).ConfigureAwait( false );
+ }
+
+
+ private Int32 ReadFromBuffer( Byte[] array, Int32 offset, Int32 count )
+ {
+
+ Int32 readBytes = _readLen - _readPos;
+ Contract.Assert( readBytes >= 0 );
+
+ if ( readBytes == 0 )
+ return 0;
+
+ Contract.Assert( readBytes > 0 );
+
+ if ( readBytes > count )
+ readBytes = count;
+
+ Buffer.BlockCopy( _buffer, _readPos, array, offset, readBytes );
+ _readPos += readBytes;
+
+ return readBytes;
+ }
+
+
+ private Int32 ReadFromBuffer( Byte[] array, Int32 offset, Int32 count, out Exception error )
+ {
+
+ try
+ {
+
+ error = null;
+ return ReadFromBuffer( array, offset, count );
+
+ }
+ catch ( Exception ex )
+ {
+ error = ex;
+ return 0;
+ }
+ }
+
+
+ public override int Read( [In, Out] Byte[] array, Int32 offset, Int32 count )
+ {
+
+ if ( array == null )
+ throw new ArgumentNullException( "array" );
+ if ( offset < 0 )
+ throw new ArgumentOutOfRangeException( "offset", "The value cannot be negative." );
+ if ( count < 0 )
+ throw new ArgumentOutOfRangeException( "count", "The value cannot be negative." );
+ if ( array.Length - offset < count )
+ throw new ArgumentException( "The offset is too big for length." );
+ Contract.EndContractBlock();
+
+ EnsureNotClosed();
+ EnsureCanRead();
+
+ Int32 bytesFromBuffer = ReadFromBuffer(array, offset, count);
+
+ // We may have read less than the number of bytes the user asked for, but that is part of the Stream contract.
+
+ // Reading again for more data may cause us to block if we're using a device with no clear end of file,
+ // such as a serial port or pipe. If we blocked here and this code was used with redirected pipes for a
+ // process's standard output, this can lead to deadlocks involving two processes.
+ // BUT - this is a breaking change.
+ // So: If we could not read all bytes the user asked for from the buffer, we will try once from the underlying
+ // stream thus ensuring the same blocking behaviour as if the underlying stream was not wrapped in this BufferedStream.
+ if ( bytesFromBuffer == count )
+ return bytesFromBuffer;
+
+ Int32 alreadySatisfied = bytesFromBuffer;
+ if ( bytesFromBuffer > 0 )
+ {
+ count -= bytesFromBuffer;
+ offset += bytesFromBuffer;
+ }
+
+ // So the READ buffer is empty.
+ Contract.Assert( _readLen == _readPos );
+ _readPos = _readLen = 0;
+
+ // If there was anything in the WRITE buffer, clear it.
+ if ( _writePos > 0 )
+ FlushWrite();
+
+ // If the requested read is larger than buffer size, avoid the buffer and still use a single read:
+ if ( count >= _bufferSize )
+ {
+
+ return _stream.Read( array, offset, count ) + alreadySatisfied;
+ }
+
+ // Ok. We can fill the buffer:
+ EnsureBufferAllocated();
+ _readLen = _stream.Read( _buffer, 0, _bufferSize );
+
+ bytesFromBuffer = ReadFromBuffer( array, offset, count );
+
+ // We may have read less than the number of bytes the user asked for, but that is part of the Stream contract.
+ // Reading again for more data may cause us to block if we're using a device with no clear end of stream,
+ // such as a serial port or pipe. If we blocked here & this code was used with redirected pipes for a process's
+ // standard output, this can lead to deadlocks involving two processes. Additionally, translating one read on the
+ // BufferedStream to more than one read on the underlying Stream may defeat the whole purpose of buffering of the
+ // underlying reads are significantly more expensive.
+
+ return bytesFromBuffer + alreadySatisfied;
+ }
+
+ private Task LastSyncCompletedReadTask( Int32 val )
+ {
+
+ Task t = _lastSyncCompletedReadTask;
+ Contract.Assert( t == null || t.Status == TaskStatus.RanToCompletion );
+
+ if ( t != null && t.Result == val )
+ return t;
+
+ // ReSharper disable once RedundantTypeArgumentsOfMethod
+ t = Task.FromResult( val );
+ _lastSyncCompletedReadTask = t;
+ return t;
+ }
+
+
+ public override Task ReadAsync( Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken )
+ {
+
+ if ( buffer == null )
+ throw new ArgumentNullException( "buffer" );
+ if ( offset < 0 )
+ throw new ArgumentOutOfRangeException( "offset", "The value cannot be negative." );
+ if ( count < 0 )
+ throw new ArgumentOutOfRangeException( "count", "The value cannot be negative." );
+ if ( buffer.Length - offset < count )
+ throw new ArgumentException( "The offset is too big for length." );
+ Contract.EndContractBlock();
+
+ // Fast path check for cancellation already requested
+ if ( cancellationToken.IsCancellationRequested )
+ return _Task.FromCancellation( cancellationToken );
+
+ EnsureNotClosed();
+ EnsureCanRead();
+
+ Int32 bytesFromBuffer = 0;
+ // Try to satisfy the request from the buffer synchronously. But still need a sem-lock in case that another
+ // Async IO Task accesses the buffer concurrently. If we fail to acquire the lock without waiting, make this
+ // an Async operation.
+ SemaphoreSlim sem = this.EnsureAsyncActiveSemaphoreInitialized();
+ Task semaphoreLockTask = sem.WaitAsync();
+ if ( semaphoreLockTask.Status == TaskStatus.RanToCompletion )
+ {
+
+ bool completeSynchronously = true;
+ try
+ {
+ Exception error;
+ bytesFromBuffer = ReadFromBuffer( buffer, offset, count, out error );
+
+ // If we satistied enough data from the buffer, we can complete synchronously.
+ // Reading again for more data may cause us to block if we're using a device with no clear end of file,
+ // such as a serial port or pipe. If we blocked here and this code was used with redirected pipes for a
+ // process's standard output, this can lead to deadlocks involving two processes.
+ // BUT - this is a breaking change.
+ // So: If we could not read all bytes the user asked for from the buffer, we will try once from the underlying
+ // stream thus ensuring the same blocking behaviour as if the underlying stream was not wrapped in this BufferedStream.
+ completeSynchronously = ( bytesFromBuffer == count || error != null );
+
+ if ( completeSynchronously )
+ {
+
+ return ( error == null )
+ ? LastSyncCompletedReadTask( bytesFromBuffer )
+ : _Task.FromException( error );
+ }
+ }
+ finally
+ {
+ if ( completeSynchronously ) // if this is FALSE, we will be entering ReadFromUnderlyingStreamAsync and releasing there.
+ sem.Release();
+ }
+ }
+
+ // Delegate to the async implementation.
+ return ReadFromUnderlyingStreamAsync( buffer, offset + bytesFromBuffer, count - bytesFromBuffer, cancellationToken,
+ bytesFromBuffer, semaphoreLockTask );
+ }
+
+
+ /// BufferedStream should be as thin a wrapper as possible. We want that ReadAsync delegates to
+ /// ReadAsync of the underlying _stream and that BeginRead delegates to BeginRead of the underlying stream,
+ /// rather than calling the base Stream which implements the one in terms of the other. This allows BufferedStream
+ /// to affect the semantics of the stream it wraps as little as possible. At the same time, we want to share as
+ /// much code between the APM and the Async pattern implementations as possible. This method is called by both with
+ /// a corresponding useApmPattern value. Recall that Task implements IAsyncResult.
+ /// -2 if _bufferSize was set to 0 while waiting on the semaphore; otherwise num of bytes read.
+ private async Task ReadFromUnderlyingStreamAsync( Byte[] array, Int32 offset, Int32 count,
+ CancellationToken cancellationToken,
+ Int32 bytesAlreadySatisfied,
+ Task semaphoreLockTask )
+ {
+
+ // Same conditions validated with exceptions in ReadAsync:
+ // (These should be Contract.Requires(..) but that method had some issues in async methods; using Assert(..) for now.)
+ Contract.Assert( array != null );
+ Contract.Assert( offset >= 0 );
+ Contract.Assert( count >= 0 );
+ Contract.Assert( array.Length - offset >= count );
+ Contract.Assert( _stream != null );
+ Contract.Assert( _stream.CanRead );
+ Contract.Assert( _bufferSize > 0 );
+ Contract.Assert( semaphoreLockTask != null );
+
+ // Employ async waiting based on the same synchronization used in BeginRead of the abstract Stream.
+ await semaphoreLockTask.ConfigureAwait( false );
+ try
+ {
+
+ // The buffer might have been changed by another async task while we were waiting on the semaphore.
+ // Check it now again.
+ Int32 bytesFromBuffer = ReadFromBuffer(array, offset, count);
+ if ( bytesFromBuffer == count )
+ return bytesAlreadySatisfied + bytesFromBuffer;
+
+ if ( bytesFromBuffer > 0 )
+ {
+ count -= bytesFromBuffer;
+ offset += bytesFromBuffer;
+ bytesAlreadySatisfied += bytesFromBuffer;
+ }
+
+ Contract.Assert( _readLen == _readPos );
+ _readPos = _readLen = 0;
+
+ // If there was anything in the WRITE buffer, clear it.
+ if ( _writePos > 0 )
+ await FlushWriteAsync( cancellationToken ).ConfigureAwait( false ); // no Begin-End read version for Flush. Use Async.
+
+ // If the requested read is larger than buffer size, avoid the buffer and still use a single read:
+ if ( count >= _bufferSize )
+ {
+ return bytesAlreadySatisfied + await _stream.ReadAsync( array, offset, count, cancellationToken ).ConfigureAwait( false );
+ }
+
+ // Ok. We can fill the buffer:
+ EnsureBufferAllocated();
+ _readLen = await _stream.ReadAsync( _buffer, 0, _bufferSize, cancellationToken ).ConfigureAwait( false );
+
+ bytesFromBuffer = ReadFromBuffer( array, offset, count );
+ return bytesAlreadySatisfied + bytesFromBuffer;
+
+ }
+ finally
+ {
+ SemaphoreSlim sem = this.EnsureAsyncActiveSemaphoreInitialized();
+ sem.Release();
+ }
+ }
+
+
+ public override Int32 ReadByte()
+ {
+
+ EnsureNotClosed();
+ EnsureCanRead();
+
+ if ( _readPos == _readLen )
+ {
+
+ if ( _writePos > 0 )
+ FlushWrite();
+
+ EnsureBufferAllocated();
+ _readLen = _stream.Read( _buffer, 0, _bufferSize );
+ _readPos = 0;
+ }
+
+ if ( _readPos == _readLen )
+ return -1;
+
+ Int32 b = _buffer[_readPos++];
+ return b;
+ }
+
+
+ private void WriteToBuffer( Byte[] array, ref Int32 offset, ref Int32 count )
+ {
+
+ Int32 bytesToWrite = Math.Min(_bufferSize - _writePos, count);
+
+ if ( bytesToWrite <= 0 )
+ return;
+
+ EnsureBufferAllocated();
+ Buffer.BlockCopy( array, offset, _buffer, _writePos, bytesToWrite );
+
+ _writePos += bytesToWrite;
+ count -= bytesToWrite;
+ offset += bytesToWrite;
+ }
+
+
+ private void WriteToBuffer( Byte[] array, ref Int32 offset, ref Int32 count, out Exception error )
+ {
+
+ try
+ {
+
+ error = null;
+ WriteToBuffer( array, ref offset, ref count );
+
+ }
+ catch ( Exception ex )
+ {
+ error = ex;
+ }
+ }
+
+
+ public override void Write( Byte[] array, Int32 offset, Int32 count )
+ {
+
+ if ( array == null )
+ throw new ArgumentNullException( "array" );
+ if ( offset < 0 )
+ throw new ArgumentOutOfRangeException( "offset", "The value cannot be negative." );
+ if ( count < 0 )
+ throw new ArgumentOutOfRangeException( "count", "The value cannot be negative." );
+ if ( array.Length - offset < count )
+ throw new ArgumentException( "The offset is too big for length." );
+ Contract.EndContractBlock();
+
+ EnsureNotClosed();
+ EnsureCanWrite();
+
+ if ( _writePos == 0 )
+ ClearReadBufferBeforeWrite();
+
+ #region Write algorithm comment
+ // We need to use the buffer, while avoiding unnecessary buffer usage / memory copies.
+ // We ASSUME that memory copies are much cheaper than writes to the underlying stream, so if an extra copy is
+ // guaranteed to reduce the number of writes, we prefer it.
+ // We pick a simple strategy that makes degenerate cases rare if our assumptions are right.
+ //
+ // For every write, we use a simple heuristic (below) to decide whether to use the buffer.
+ // The heuristic has the desirable property (*) that if the specified user data can fit into the currently available
+ // buffer space without filling it up completely, the heuristic will always tell us to use the buffer. It will also
+ // tell us to use the buffer in cases where the current write would fill the buffer, but the remaining data is small
+ // enough such that subsequent operations can use the buffer again.
+ //
+ // Algorithm:
+ // Determine whether or not to buffer according to the heuristic (below).
+ // If we decided to use the buffer:
+ // Copy as much user data as we can into the buffer.
+ // If we consumed all data: We are finished.
+ // Otherwise, write the buffer out.
+ // Copy the rest of user data into the now cleared buffer (no need to write out the buffer again as the heuristic
+ // will prevent it from being filled twice).
+ // If we decided not to use the buffer:
+ // Can the data already in the buffer and current user data be combines to a single write
+ // by allocating a "shadow" buffer of up to twice the size of _bufferSize (up to a limit to avoid LOH)?
+ // Yes, it can:
+ // Allocate a larger "shadow" buffer and ensure the buffered data is moved there.
+ // Copy user data to the shadow buffer.
+ // Write shadow buffer to the underlying stream in a single operation.
+ // No, it cannot (amount of data is still too large):
+ // Write out any data possibly in the buffer.
+ // Write out user data directly.
+ //
+ // Heuristic:
+ // If the subsequent write operation that follows the current write operation will result in a write to the
+ // underlying stream in case that we use the buffer in the current write, while it would not have if we avoided
+ // using the buffer in the current write (by writing current user data to the underlying stream directly), then we
+ // prefer to avoid using the buffer since the corresponding memory copy is wasted (it will not reduce the number
+ // of writes to the underlying stream, which is what we are optimising for).
+ // ASSUME that the next write will be for the same amount of bytes as the current write (most common case) and
+ // determine if it will cause a write to the underlying stream. If the next write is actually larger, our heuristic
+ // still yields the right behaviour, if the next write is actually smaller, we may making an unnecessary write to
+ // the underlying stream. However, this can only occur if the current write is larger than half the buffer size and
+ // we will recover after one iteration.
+ // We have:
+ // useBuffer = (_writePos + count + count < _bufferSize + _bufferSize)
+ //
+ // Example with _bufferSize = 20, _writePos = 6, count = 10:
+ //
+ // +---------------------------------------+---------------------------------------+
+ // | current buffer | next iteration's "future" buffer |
+ // +---------------------------------------+---------------------------------------+
+ // |0| | | | | | | | | |1| | | | | | | | | |2| | | | | | | | | |3| | | | | | | | | |
+ // |0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|
+ // +-----------+-------------------+-------------------+---------------------------+
+ // | _writePos | current count | assumed next count|avail buff after next write|
+ // +-----------+-------------------+-------------------+---------------------------+
+ //
+ // A nice property (*) of this heuristic is that it will always succeed if the user data completely fits into the
+ // available buffer, i.e. if count < (_bufferSize - _writePos).
+ #endregion Write algorithm comment
+
+ Contract.Assert( _writePos < _bufferSize );
+
+ Int32 totalUserBytes;
+ bool useBuffer;
+ checked
+ { // We do not expect buffer sizes big enough for an overflow, but if it happens, lets fail early:
+ totalUserBytes = _writePos + count;
+ useBuffer = ( totalUserBytes + count < ( _bufferSize + _bufferSize ) );
+ }
+
+ if ( useBuffer )
+ {
+
+ WriteToBuffer( array, ref offset, ref count );
+
+ if ( _writePos < _bufferSize )
+ {
+
+ Contract.Assert( count == 0 );
+ return;
+ }
+
+ Contract.Assert( count >= 0 );
+ Contract.Assert( _writePos == _bufferSize );
+ Contract.Assert( _buffer != null );
+
+ _stream.Write( _buffer, 0, _writePos );
+ _writePos = 0;
+
+ WriteToBuffer( array, ref offset, ref count );
+
+ Contract.Assert( count == 0 );
+ Contract.Assert( _writePos < _bufferSize );
+
+ }
+ else
+ { // if (!useBuffer)
+
+ // Write out the buffer if necessary.
+ if ( _writePos > 0 )
+ {
+
+ Contract.Assert( _buffer != null );
+ Contract.Assert( totalUserBytes >= _bufferSize );
+
+ // Try avoiding extra write to underlying stream by combining previously buffered data with current user data:
+ if ( totalUserBytes <= ( _bufferSize + _bufferSize ) && totalUserBytes <= MaxShadowBufferSize )
+ {
+
+ EnsureShadowBufferAllocated();
+ Buffer.BlockCopy( array, offset, _buffer, _writePos, count );
+ _stream.Write( _buffer, 0, totalUserBytes );
+ _writePos = 0;
+ return;
+ }
+
+ _stream.Write( _buffer, 0, _writePos );
+ _writePos = 0;
+ }
+
+ // Write out user data.
+ _stream.Write( array, offset, count );
+ }
+ }
+
+ public override Task WriteAsync( Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken )
+ {
+
+ if ( buffer == null )
+ throw new ArgumentNullException( "buffer" );
+ if ( offset < 0 )
+ throw new ArgumentOutOfRangeException( "offset", "The value cannot be negative." );
+ if ( count < 0 )
+ throw new ArgumentOutOfRangeException( "count", "The value cannot be negative." );
+ if ( buffer.Length - offset < count )
+ throw new ArgumentException( "The offset is too big for length." );
+ Contract.EndContractBlock();
+
+ // Fast path check for cancellation already requested
+ if ( cancellationToken.IsCancellationRequested )
+ return _Task.FromCancellation( cancellationToken );
+
+ EnsureNotClosed();
+ EnsureCanWrite();
+
+ // Try to satisfy the request from the buffer synchronously. But still need a sem-lock in case that another
+ // Async IO Task accesses the buffer concurrently. If we fail to acquire the lock without waiting, make this
+ // an Async operation.
+ SemaphoreSlim sem = this.EnsureAsyncActiveSemaphoreInitialized();
+ Task semaphoreLockTask = sem.WaitAsync();
+ if ( semaphoreLockTask.Status == TaskStatus.RanToCompletion )
+ {
+
+ bool completeSynchronously = true;
+ try
+ {
+
+ if ( _writePos == 0 )
+ ClearReadBufferBeforeWrite();
+
+ Contract.Assert( _writePos < _bufferSize );
+
+ // If the write completely fits into the buffer, we can complete synchronously:
+ completeSynchronously = ( count < _bufferSize - _writePos );
+
+ if ( completeSynchronously )
+ {
+
+ Exception error;
+ WriteToBuffer( buffer, ref offset, ref count, out error );
+ Contract.Assert( count == 0 );
+
+ return ( error == null )
+ ? _Task.CompletedTask
+ : _Task.FromException( error );
+ }
+ }
+ finally
+ {
+ if ( completeSynchronously ) // if this is FALSE, we will be entering WriteToUnderlyingStreamAsync and releasing there.
+ sem.Release();
+ }
+ }
+
+ // Delegate to the async implementation.
+ return WriteToUnderlyingStreamAsync( buffer, offset, count, cancellationToken, semaphoreLockTask );
+ }
+
+
+ /// BufferedStream should be as thin a wrapper as possible. We want that WriteAsync delegates to
+ /// WriteAsync of the underlying _stream and that BeginWrite delegates to BeginWrite of the underlying stream,
+ /// rather than calling the base Stream which implements the one in terms of the other. This allows BufferedStream
+ /// to affect the semantics of the stream it wraps as little as possible. At the same time, we want to share as
+ /// much code between the APM and the Async pattern implementations as possible. This method is called by both with
+ /// a corresponding useApmPattern value. Recall that Task implements IAsyncResult.
+ private async Task WriteToUnderlyingStreamAsync( Byte[] array, Int32 offset, Int32 count,
+ CancellationToken cancellationToken,
+ Task semaphoreLockTask )
+ {
+
+ // (These should be Contract.Requires(..) but that method had some issues in async methods; using Assert(..) for now.)
+ Contract.Assert( array != null );
+ Contract.Assert( offset >= 0 );
+ Contract.Assert( count >= 0 );
+ Contract.Assert( array.Length - offset >= count );
+ Contract.Assert( _stream != null );
+ Contract.Assert( _stream.CanWrite );
+ Contract.Assert( _bufferSize > 0 );
+ Contract.Assert( semaphoreLockTask != null );
+
+ // See the LARGE COMMENT in Write(..) for the explanation of the write buffer algorithm.
+
+ await semaphoreLockTask.ConfigureAwait( false );
+ try
+ {
+
+ // The buffer might have been changed by another async task while we were waiting on the semaphore.
+ // However, note that if we recalculate the sync completion condition to TRUE, then useBuffer will also be TRUE.
+
+ if ( _writePos == 0 )
+ ClearReadBufferBeforeWrite();
+
+ Int32 totalUserBytes;
+ bool useBuffer;
+ checked
+ { // We do not expect buffer sizes big enough for an overflow, but if it happens, lets fail early:
+ totalUserBytes = _writePos + count;
+ useBuffer = ( totalUserBytes + count < ( _bufferSize + _bufferSize ) );
+ }
+
+ if ( useBuffer )
+ {
+
+ WriteToBuffer( array, ref offset, ref count );
+
+ if ( _writePos < _bufferSize )
+ {
+
+ Contract.Assert( count == 0 );
+ return;
+ }
+
+ Contract.Assert( count >= 0 );
+ Contract.Assert( _writePos == _bufferSize );
+ Contract.Assert( _buffer != null );
+
+ await _stream.WriteAsync( _buffer, 0, _writePos, cancellationToken ).ConfigureAwait( false );
+ _writePos = 0;
+
+ WriteToBuffer( array, ref offset, ref count );
+
+ Contract.Assert( count == 0 );
+ Contract.Assert( _writePos < _bufferSize );
+
+ }
+ else
+ { // if (!useBuffer)
+
+ // Write out the buffer if necessary.
+ if ( _writePos > 0 )
+ {
+
+ Contract.Assert( _buffer != null );
+ Contract.Assert( totalUserBytes >= _bufferSize );
+
+ // Try avoiding extra write to underlying stream by combining previously buffered data with current user data:
+ if ( totalUserBytes <= ( _bufferSize + _bufferSize ) && totalUserBytes <= MaxShadowBufferSize )
+ {
+
+ EnsureShadowBufferAllocated();
+ Buffer.BlockCopy( array, offset, _buffer, _writePos, count );
+ await _stream.WriteAsync( _buffer, 0, totalUserBytes, cancellationToken ).ConfigureAwait( false );
+ _writePos = 0;
+ return;
+ }
+
+ await _stream.WriteAsync( _buffer, 0, _writePos, cancellationToken ).ConfigureAwait( false );
+ _writePos = 0;
+ }
+
+ // Write out user data.
+ await _stream.WriteAsync( array, offset, count, cancellationToken ).ConfigureAwait( false );
+ }
+ }
+ finally
+ {
+ SemaphoreSlim sem = this.EnsureAsyncActiveSemaphoreInitialized();
+ sem.Release();
+ }
+ }
+
+
+ public override void WriteByte( Byte value )
+ {
+
+ EnsureNotClosed();
+
+ if ( _writePos == 0 )
+ {
+
+ EnsureCanWrite();
+ ClearReadBufferBeforeWrite();
+ EnsureBufferAllocated();
+ }
+
+ // We should not be flushing here, but only writing to the underlying stream, but previous version flushed, so we keep this.
+ if ( _writePos >= _bufferSize - 1 )
+ FlushWrite();
+
+ _buffer[ _writePos++ ] = value;
+
+ Contract.Assert( _writePos < _bufferSize );
+ }
+
+
+ public override Int64 Seek( Int64 offset, SeekOrigin origin )
+ {
+
+ EnsureNotClosed();
+ EnsureCanSeek();
+
+ // If we have bytes in the WRITE buffer, flush them out, seek and be done.
+ if ( _writePos > 0 )
+ {
+
+ // We should be only writing the buffer and not flushing,
+ // but the previous version did flush and we stick to it for back-compat reasons.
+ FlushWrite();
+ return _stream.Seek( offset, origin );
+ }
+
+ // The buffer is either empty or we have a buffered READ.
+
+ if ( _readLen - _readPos > 0 && origin == SeekOrigin.Current )
+ {
+
+ // If we have bytes in the READ buffer, adjust the seek offset to account for the resulting difference
+ // between this stream's position and the underlying stream's position.
+ offset -= ( _readLen - _readPos );
+ }
+
+ Int64 oldPos = Position;
+ Contract.Assert( oldPos == _stream.Position + ( _readPos - _readLen ) );
+
+ Int64 newPos = _stream.Seek(offset, origin);
+
+ // If the seek destination is still within the data currently in the buffer, we want to keep the buffer data and continue using it.
+ // Otherwise we will throw away the buffer. This can only happen on READ, as we flushed WRITE data above.
+
+ // The offset of the new/updated seek pointer within _buffer:
+ _readPos = ( Int32 )( newPos - ( oldPos - _readPos ) );
+
+ // If the offset of the updated seek pointer in the buffer is still legal, then we can keep using the buffer:
+ if ( 0 <= _readPos && _readPos < _readLen )
+ {
+
+ // Adjust the seek pointer of the underlying stream to reflect the amount of useful bytes in the read buffer:
+ _stream.Seek( _readLen - _readPos, SeekOrigin.Current );
+
+ }
+ else
+ { // The offset of the updated seek pointer is not a legal offset. Loose the buffer.
+
+ _readPos = _readLen = 0;
+ }
+
+ Contract.Assert( newPos == Position, "newPos (=" + newPos + ") == Position (=" + Position + ")" );
+ return newPos;
+ }
+
+
+ public override void SetLength( Int64 value )
+ {
+
+ if ( value < 0 )
+ throw new ArgumentOutOfRangeException( "value", "The size cannot be negative." );
+ Contract.EndContractBlock();
+
+ EnsureNotClosed();
+ EnsureCanSeek();
+ EnsureCanWrite();
+
+ Flush();
+ _stream.SetLength( value );
+ }
+
+ // From https://github.com/dotnet/coreclr/blob/master/src/mscorlib/src/System/IO/Stream.cs ef1e2ab328087c61a6878c1e84f4fc5d710aebce
+
+ // To implement Async IO operations on streams that don't support async IO
+
+ private SemaphoreSlim _asyncActiveSemaphore;
+
+ internal SemaphoreSlim EnsureAsyncActiveSemaphoreInitialized()
+ {
+ // Lazily-initialize _asyncActiveSemaphore. As we're never accessing the SemaphoreSlim's
+ // WaitHandle, we don't need to worry about Disposing it.
+ return LazyInitializer.EnsureInitialized( ref _asyncActiveSemaphore, () => new SemaphoreSlim( 1, 1 ) );
+ }
+
+ // End From Stream.cs
+
+ // From https://github.com/dotnet/coreclr/blob/master/src/mscorlib/src/System/IO/__Error.cs ef1e2ab328087c61a6878c1e84f4fc5d710aebce
+ private static class __Error
+ {
+ internal static void StreamIsClosed()
+ {
+ throw new ObjectDisposedException( null, "This stream is already closed." );
+ }
+
+ internal static void ReadNotSupported()
+ {
+ throw new NotSupportedException( "Cannot read on the current stream." );
+ }
+ internal static void WriteNotSupported()
+ {
+ throw new NotSupportedException( "Cannot write on the current stream." );
+ }
+
+ internal static void SeekNotSupported()
+ {
+ throw new NotSupportedException( "Cannot seek on the current stream." );
+ }
+ }
+
+ // From
+ private static class _Task
+ {
+ /// Gets a task that's already been completed successfully.
+ /// May not always return the same instance.
+ public static Task CompletedTask
+ {
+ get
+ {
+ var tcs = new TaskCompletionSource