├── .gitignore ├── .travis.yml ├── LICENSE ├── NOTICE ├── README.md ├── RSocket.Rpc.Core ├── .gitignore ├── RSocket.Rpc.Core.csproj ├── RSocket.Rpc.Core.sln ├── RSocketService.Metadata.cs └── RSocketService.cs ├── RSocket.Rpc.Protobuf ├── .gitignore ├── CMakeLists.txt ├── proto │ ├── google │ │ └── protobuf │ │ │ ├── any.proto │ │ │ ├── api.proto │ │ │ ├── descriptor.proto │ │ │ ├── duration.proto │ │ │ ├── empty.proto │ │ │ ├── field_mask.proto │ │ │ ├── source_context.proto │ │ │ ├── struct.proto │ │ │ ├── timestamp.proto │ │ │ ├── type.proto │ │ │ └── wrappers.proto │ └── rsocket │ │ └── options.proto └── src │ ├── csharp_generator.cc │ ├── csharp_generator.h │ ├── csharp_generator_helpers.h │ ├── csharp_plugin.cc │ └── rsocket │ ├── options.pb.cc │ └── options.pb.h ├── RSocket.Rpc.Sample ├── EchoService.cs ├── Program.cs ├── RSocket.Rpc.Sample.csproj └── echo.proto ├── RSocket.Rpc.Tools.Tests ├── CSharpGeneratorTest.cs ├── CppGeneratorTest.cs ├── DepFileUtilTest.cs ├── GeneratorTest.cs ├── ProtoCompileBasicTest.cs ├── ProtoCompileCommandLineGeneratorTest.cs ├── ProtoCompileCommandLinePrinterTest.cs ├── ProtoToolsPlatformTaskTest.cs ├── RSocket.Rpc.Tools.Tests.csproj └── Utils.cs ├── RSocket.Rpc.Tools ├── Common.cs ├── DepFileUtil.cs ├── GeneratorServices.cs ├── ProtoCompile.cs ├── ProtoCompilerOutputs.cs ├── ProtoReadDependencies.cs ├── ProtoToolsPlatform.cs ├── RSocket.Rpc.Tools.csproj └── build │ ├── RSocket.Rpc.Tools.props │ ├── RSocket.Rpc.Tools.targets │ ├── _protobuf │ ├── Google.Protobuf.Tools.props │ ├── Google.Protobuf.Tools.targets │ ├── Protobuf.CSharp.xml │ └── README │ ├── _rsocket │ ├── README │ ├── RSocket.Rpc.CSharp.xml │ ├── _RSocket.Rpc.Tools.props │ └── _RSocket.Rpc.Tools.targets │ └── native │ └── RSocket.Rpc.Tools.props ├── RSocket.Rpc.nuspec ├── RSocket.Rpc.sln └── tests.json /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Build results 17 | [Dd]ebug/ 18 | [Dd]ebugPublic/ 19 | [Rr]elease/ 20 | [Rr]eleases/ 21 | x64/ 22 | x86/ 23 | bld/ 24 | [Bb]in/ 25 | [Oo]bj/ 26 | [Ll]og/ 27 | 28 | # Visual Studio 2015/2017 cache/options directory 29 | .vs/ 30 | # Uncomment if you have tasks that create the project's static files in wwwroot 31 | #wwwroot/ 32 | 33 | # Visual Studio 2017 auto generated files 34 | Generated\ Files/ 35 | 36 | # MSTest test Results 37 | [Tt]est[Rr]esult*/ 38 | [Bb]uild[Ll]og.* 39 | 40 | # NUNIT 41 | *.VisualState.xml 42 | TestResult.xml 43 | 44 | # Build Results of an ATL Project 45 | [Dd]ebugPS/ 46 | [Rr]eleasePS/ 47 | dlldata.c 48 | 49 | # Benchmark Results 50 | BenchmarkDotNet.Artifacts/ 51 | 52 | # .NET Core 53 | project.lock.json 54 | project.fragment.lock.json 55 | artifacts/ 56 | 57 | # StyleCop 58 | StyleCopReport.xml 59 | 60 | # Files built by Visual Studio 61 | *_i.c 62 | *_p.c 63 | *_h.h 64 | *.ilk 65 | *.meta 66 | *.obj 67 | *.iobj 68 | *.pch 69 | *.pdb 70 | *.ipdb 71 | *.pgc 72 | *.pgd 73 | *.rsp 74 | *.sbr 75 | *.tlb 76 | *.tli 77 | *.tlh 78 | *.tmp 79 | *.tmp_proj 80 | *_wpftmp.csproj 81 | *.log 82 | *.vspscc 83 | *.vssscc 84 | .builds 85 | *.pidb 86 | *.svclog 87 | *.scc 88 | 89 | # Chutzpah Test files 90 | _Chutzpah* 91 | 92 | # Visual C++ cache files 93 | ipch/ 94 | *.aps 95 | *.ncb 96 | *.opendb 97 | *.opensdf 98 | *.sdf 99 | *.cachefile 100 | *.VC.db 101 | *.VC.VC.opendb 102 | 103 | # Visual Studio profiler 104 | *.psess 105 | *.vsp 106 | *.vspx 107 | *.sap 108 | 109 | # Visual Studio Trace Files 110 | *.e2e 111 | 112 | # TFS 2012 Local Workspace 113 | $tf/ 114 | 115 | # Guidance Automation Toolkit 116 | *.gpState 117 | 118 | # ReSharper is a .NET coding add-in 119 | _ReSharper*/ 120 | *.[Rr]e[Ss]harper 121 | *.DotSettings.user 122 | 123 | # JustCode is a .NET coding add-in 124 | .JustCode 125 | 126 | # TeamCity is a build add-in 127 | _TeamCity* 128 | 129 | # DotCover is a Code Coverage Tool 130 | *.dotCover 131 | 132 | # AxoCover is a Code Coverage Tool 133 | .axoCover/* 134 | !.axoCover/settings.json 135 | 136 | # Visual Studio code coverage results 137 | *.coverage 138 | *.coveragexml 139 | 140 | # NCrunch 141 | _NCrunch_* 142 | .*crunch*.local.xml 143 | nCrunchTemp_* 144 | 145 | # MightyMoose 146 | *.mm.* 147 | AutoTest.Net/ 148 | 149 | # Web workbench (sass) 150 | .sass-cache/ 151 | 152 | # Installshield output folder 153 | [Ee]xpress/ 154 | 155 | # DocProject is a documentation generator add-in 156 | DocProject/buildhelp/ 157 | DocProject/Help/*.HxT 158 | DocProject/Help/*.HxC 159 | DocProject/Help/*.hhc 160 | DocProject/Help/*.hhk 161 | DocProject/Help/*.hhp 162 | DocProject/Help/Html2 163 | DocProject/Help/html 164 | 165 | # Click-Once directory 166 | publish/ 167 | 168 | # Publish Web Output 169 | *.[Pp]ublish.xml 170 | *.azurePubxml 171 | # Note: Comment the next line if you want to checkin your web deploy settings, 172 | # but database connection strings (with potential passwords) will be unencrypted 173 | *.pubxml 174 | *.publishproj 175 | 176 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 177 | # checkin your Azure Web App publish settings, but sensitive information contained 178 | # in these scripts will be unencrypted 179 | PublishScripts/ 180 | 181 | # NuGet Packages 182 | *.nupkg 183 | # The packages folder can be ignored because of Package Restore 184 | **/[Pp]ackages/* 185 | # except build/, which is used as an MSBuild target. 186 | !**/[Pp]ackages/build/ 187 | # Uncomment if necessary however generally it will be regenerated when needed 188 | #!**/[Pp]ackages/repositories.config 189 | # NuGet v3's project.json files produces more ignorable files 190 | *.nuget.props 191 | *.nuget.targets 192 | 193 | # Microsoft Azure Build Output 194 | csx/ 195 | *.build.csdef 196 | 197 | # Microsoft Azure Emulator 198 | ecf/ 199 | rcf/ 200 | 201 | # Windows Store app package directories and files 202 | AppPackages/ 203 | BundleArtifacts/ 204 | Package.StoreAssociation.xml 205 | _pkginfo.txt 206 | *.appx 207 | 208 | # Visual Studio cache files 209 | # files ending in .cache can be ignored 210 | *.[Cc]ache 211 | # but keep track of directories ending in .cache 212 | !*.[Cc]ache/ 213 | 214 | # Others 215 | ClientBin/ 216 | ~$* 217 | *~ 218 | *.dbmdl 219 | *.dbproj.schemaview 220 | *.jfm 221 | *.pfx 222 | *.publishsettings 223 | orleans.codegen.cs 224 | 225 | # Including strong name files can present a security risk 226 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 227 | #*.snk 228 | 229 | # Since there are multiple workflows, uncomment next line to ignore bower_components 230 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 231 | #bower_components/ 232 | 233 | # RIA/Silverlight projects 234 | Generated_Code/ 235 | 236 | # Backup & report files from converting an old project file 237 | # to a newer Visual Studio version. Backup files are not needed, 238 | # because we have git ;-) 239 | _UpgradeReport_Files/ 240 | Backup*/ 241 | UpgradeLog*.XML 242 | UpgradeLog*.htm 243 | ServiceFabricBackup/ 244 | *.rptproj.bak 245 | 246 | # SQL Server files 247 | *.mdf 248 | *.ldf 249 | *.ndf 250 | 251 | # Business Intelligence projects 252 | *.rdl.data 253 | *.bim.layout 254 | *.bim_*.settings 255 | *.rptproj.rsuser 256 | 257 | # Microsoft Fakes 258 | FakesAssemblies/ 259 | 260 | # GhostDoc plugin setting file 261 | *.GhostDoc.xml 262 | 263 | # Node.js Tools for Visual Studio 264 | .ntvs_analysis.dat 265 | node_modules/ 266 | 267 | # Visual Studio 6 build log 268 | *.plg 269 | 270 | # Visual Studio 6 workspace options file 271 | *.opt 272 | 273 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 274 | *.vbw 275 | 276 | # Visual Studio LightSwitch build output 277 | **/*.HTMLClient/GeneratedArtifacts 278 | **/*.DesktopClient/GeneratedArtifacts 279 | **/*.DesktopClient/ModelManifest.xml 280 | **/*.Server/GeneratedArtifacts 281 | **/*.Server/ModelManifest.xml 282 | _Pvt_Extensions 283 | 284 | # Paket dependency manager 285 | .paket/paket.exe 286 | paket-files/ 287 | 288 | # FAKE - F# Make 289 | .fake/ 290 | 291 | # JetBrains Rider 292 | .idea/ 293 | *.sln.iml 294 | 295 | # CodeRush personal settings 296 | .cr/personal 297 | 298 | # Python Tools for Visual Studio (PTVS) 299 | __pycache__/ 300 | *.pyc 301 | 302 | # Cake - Uncomment if you are using it 303 | # tools/** 304 | # !tools/packages.config 305 | 306 | # Tabs Studio 307 | *.tss 308 | 309 | # Telerik's JustMock configuration file 310 | *.jmconfig 311 | 312 | # BizTalk build output 313 | *.btp.cs 314 | *.btm.cs 315 | *.odx.cs 316 | *.xsd.cs 317 | 318 | # OpenCover UI analysis results 319 | OpenCover/ 320 | 321 | # Azure Stream Analytics local run output 322 | ASALocalRun/ 323 | 324 | # MSBuild Binary and Structured Log 325 | *.binlog 326 | 327 | # NVidia Nsight GPU debugger configuration file 328 | *.nvuser 329 | 330 | # MFractors (Xamarin productivity tool) working folder 331 | .mfractor/ 332 | 333 | # Local History for Visual Studio 334 | .localhistory/ 335 | 336 | 337 | 338 | ###Original Integrators Contents with duplicates removed: 339 | *.lock.json 340 | /protoc_plugins/ 341 | 342 | test-results/ 343 | coverage_results.xml 344 | /TestResults 345 | 346 | *.DS_Store -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | matrix: 2 | include: 3 | - language: csharp 4 | os: linux 5 | dist: xenial 6 | mono: none 7 | dotnet: 2.1 8 | env: 9 | secure: Zdf/jHNSdMalt4Czp7Q7TngZrDpcplQ0JKJpQYAPZsCPqDJ7Xw9mcoR0VKMm5z06cZsmF/r4yXtJMbWMedfgaPkCTK7rI5Z2iIQWgkIL7b+x6pn/FODjFA+Llhj9xjy5GrHE9nx/f6Qta0F7BvwTzCW4HTBQceFtdzBOz2NbqrHgwJrONF1rON6PIqapKPfIh6pNRr5Ud6u9/pHSZceCrB+kjua7R687vFVqHj7I7P5RxQn7dnNJNCjCQdwauwejG42UmAkLshrdV00g82HZqNzAYGxP2FdGkcueIbTssDB8DODT4UE/5bde6Ol2uW7vlx9FDxFsXNfv9MiqCjfMweGnuODOeJfQfvtvRWpX6GeVhTvzTCp8/MxFZo5tnWedhrWBBT6Hjmnc+kCYyCMra7hO0xOORRnUn8P9fyTYjWu0gQEpS3Z2nZx2v+ZbVVEoHD2tPEF2+B7QMILO/HgsLZChnrgZNPW5fTcmLncTvv5VAnb55mUj8yclZq3Fu5EJwj00kTgH5w+3KykPo1YjIC6KBYj9u2KveKQuquyqUoIcWtYh8IXWi+3jyLvMjLc7ZWQmqKfaNuskB3mUD2khtZPUjRihPaEzJ4+TGqeqoaYoFT2TwLg/AFqbzbuvNr6FnXAhzL8vM5FtcIW8FeeubOOKZm9R42U/jdlCuIUzGPE= 10 | script: 11 | - dotnet build -c Release 12 | - dotnet test -c Release 13 | before_deploy: 14 | - dotnet pack RSocket.Rpc.Core -c Release -p:Version=$TRAVIS_TAG 15 | deploy: 16 | provider: script 17 | script: dotnet nuget push RSocket.Rpc.Core/bin/Release/RSocket.Rpc.Core.*.nupkg --api-key $NUGET_API_KEY --source https://api.nuget.org/v3/index.json 18 | skip_cleanup: true 19 | on: 20 | repo: rsocket/rsocket-rpc-net 21 | tags: true 22 | - language: cpp 23 | os: linux 24 | dist: xenial 25 | compiler: gcc 26 | before_install: 27 | - wget https://github.com/google/protobuf/releases/download/v3.6.1/protobuf-cpp-3.6.1.tar.gz 28 | - tar -xzvf protobuf-cpp-3.6.1.tar.gz 29 | - pushd protobuf-3.6.1 30 | - ./configure --disable-shared && make && sudo make install 31 | - popd 32 | script: 33 | - pushd RSocket.Rpc.Protobuf 34 | - cmake . -Bbuild && make -Cbuild 35 | - popd 36 | before_deploy: 37 | - pushd RSocket.Rpc.Protobuf/build 38 | - tar -czvf rsocket-rpc-protobuf-v${TRAVIS_TAG}-${TRAVIS_OS_NAME}-x64.tar.gz rsocket_rpc_csharp_plugin 39 | - popd 40 | deploy: 41 | provider: releases 42 | api_key: 43 | secure: Bfj44G+KzB8M9zLJoH/QMLVC/Es6ra6I+qoHVxtkZAhaqlmPaIpvtJF6AZluEMu/gEBdDtPdY8GmTJZQ+kPyYszRC7DmOZFsqLJ8EQvH0fjKduIIk0kL7ywMbvvQiZ+2uGBRb3+D4zwpRAPw5ebvj2P0D2golkV33vNCczp2NWDhCoeRY1bm+EbjsWZuB4jpuStdDeVpKSsgbtSJhgnqXhjBlt4AeOIj1eC/cp39jTpGnNDco2ZsbutRrJ1hudONbYZGm4hSSviW2F6nAXRL/jmtSHPEXq2OcZOOfn5r68uLC0qiXVDaoobTEPIHtHIz/K6qgkrQ1u5JbwmWbAhakG7gFpsVOKtNGgAqdamFC2TgsowMQdAOJxsPbKDjaiJ0paYE0bvLy5E+9l222c9MsgBkmtRjnfETipwShuFJ155FbSSejIOuj8iksLwY17crvg2fpeRgWsc0zo15chYHITSLi8SXRE/aA3yLDk2dQGEFPSaVY452+meOQFympFStbyGJ3yrb7bg+X5M3Nn8GgD70j1OnL3aBN8XlgRI2pX4+HBnEUoE8210D8Ksi8D1rOYzib64w94jrGEiiqZzfZTiQCssFEI7TInZXmL3qWOWzMWVVLZl6azy4G1nvxK+vy69odrhrX3G/0TtmBj4sLochifrFGDbTXByO0LqAKjc= 44 | file: RSocket.Rpc.Protobuf/build/rsocket-rpc-protobuf-v${TRAVIS_TAG}-${TRAVIS_OS_NAME}-x64.tar.gz 45 | skip_cleanup: true 46 | on: 47 | repo: rsocket/rsocket-rpc-net 48 | tags: true 49 | - language: cpp 50 | os: osx 51 | osx_image: xcode10.1 52 | compiler: clang 53 | before_install: 54 | - curl -O -L https://github.com/google/protobuf/releases/download/v3.6.1/protobuf-cpp-3.6.1.tar.gz 55 | - tar -xzf protobuf-cpp-3.6.1.tar.gz 56 | - pushd protobuf-3.6.1 57 | - ./autogen.sh 58 | - ./configure --disable-shared && make && sudo make install 59 | - popd 60 | script: 61 | - pushd RSocket.Rpc.Protobuf 62 | - cmake . -Bbuild && make -Cbuild 63 | - popd 64 | before_deploy: 65 | - pushd RSocket.Rpc.Protobuf/build 66 | - tar -czvf rsocket-rpc-protobuf-v${TRAVIS_TAG}-${TRAVIS_OS_NAME}-x64.tar.gz rsocket_rpc_csharp_plugin 67 | - popd 68 | deploy: 69 | provider: releases 70 | api_key: 71 | secure: Bfj44G+KzB8M9zLJoH/QMLVC/Es6ra6I+qoHVxtkZAhaqlmPaIpvtJF6AZluEMu/gEBdDtPdY8GmTJZQ+kPyYszRC7DmOZFsqLJ8EQvH0fjKduIIk0kL7ywMbvvQiZ+2uGBRb3+D4zwpRAPw5ebvj2P0D2golkV33vNCczp2NWDhCoeRY1bm+EbjsWZuB4jpuStdDeVpKSsgbtSJhgnqXhjBlt4AeOIj1eC/cp39jTpGnNDco2ZsbutRrJ1hudONbYZGm4hSSviW2F6nAXRL/jmtSHPEXq2OcZOOfn5r68uLC0qiXVDaoobTEPIHtHIz/K6qgkrQ1u5JbwmWbAhakG7gFpsVOKtNGgAqdamFC2TgsowMQdAOJxsPbKDjaiJ0paYE0bvLy5E+9l222c9MsgBkmtRjnfETipwShuFJ155FbSSejIOuj8iksLwY17crvg2fpeRgWsc0zo15chYHITSLi8SXRE/aA3yLDk2dQGEFPSaVY452+meOQFympFStbyGJ3yrb7bg+X5M3Nn8GgD70j1OnL3aBN8XlgRI2pX4+HBnEUoE8210D8Ksi8D1rOYzib64w94jrGEiiqZzfZTiQCssFEI7TInZXmL3qWOWzMWVVLZl6azy4G1nvxK+vy69odrhrX3G/0TtmBj4sLochifrFGDbTXByO0LqAKjc= 72 | file: RSocket.Rpc.Protobuf/build/rsocket-rpc-protobuf-v${TRAVIS_TAG}-${TRAVIS_OS_NAME}-x64.tar.gz 73 | skip_cleanup: true 74 | on: 75 | repo: rsocket/rsocket-rpc-net 76 | tags: true 77 | - language: cpp 78 | os: windows 79 | before_install: 80 | - wget https://github.com/google/protobuf/releases/download/v3.6.1/protobuf-cpp-3.6.1.tar.gz 81 | - tar -xzvf protobuf-cpp-3.6.1.tar.gz 82 | - pushd protobuf-3.6.1/cmake 83 | - mkdir build && cd build 84 | - cmake -DCMAKE_CXX_FLAGS="-std=c++11" -Dprotobuf_BUILD_TESTS=OFF .. 85 | - cmake --build . --config Release 86 | - cmake --build . --config Release --target install 87 | - popd 88 | script: 89 | - pushd RSocket.Rpc.Protobuf 90 | - mkdir build && cd build 91 | - cmake -DProtobuf_LIBRARIES=/c/Program\ Files\ \(x86\)/protobuf/lib/ -DProtobuf_INCLUDE_DIR=/c/Program\ Files\ \(x86\)/protobuf/include/ -DProtobuf_LIBRARY=/c/Program\ Files\ \(x86\)/protobuf/lib/libprotobuf.lib -DProtobuf_PROTOC_LIBRARY=/c/Program\ Files\ \(x86\)/protobuf/lib/libprotoc.lib .. 92 | - cmake --build . --config Release 93 | - popd 94 | before_deploy: 95 | - pushd RSocket.Rpc.Protobuf/build 96 | - tar -czvf rsocket-rpc-protobuf-v${TRAVIS_TAG}-${TRAVIS_OS_NAME}-x64.tar.gz -C Release rsocket_rpc_csharp_plugin.exe 97 | - popd 98 | deploy: 99 | provider: releases 100 | api_key: 101 | secure: Bfj44G+KzB8M9zLJoH/QMLVC/Es6ra6I+qoHVxtkZAhaqlmPaIpvtJF6AZluEMu/gEBdDtPdY8GmTJZQ+kPyYszRC7DmOZFsqLJ8EQvH0fjKduIIk0kL7ywMbvvQiZ+2uGBRb3+D4zwpRAPw5ebvj2P0D2golkV33vNCczp2NWDhCoeRY1bm+EbjsWZuB4jpuStdDeVpKSsgbtSJhgnqXhjBlt4AeOIj1eC/cp39jTpGnNDco2ZsbutRrJ1hudONbYZGm4hSSviW2F6nAXRL/jmtSHPEXq2OcZOOfn5r68uLC0qiXVDaoobTEPIHtHIz/K6qgkrQ1u5JbwmWbAhakG7gFpsVOKtNGgAqdamFC2TgsowMQdAOJxsPbKDjaiJ0paYE0bvLy5E+9l222c9MsgBkmtRjnfETipwShuFJ155FbSSejIOuj8iksLwY17crvg2fpeRgWsc0zo15chYHITSLi8SXRE/aA3yLDk2dQGEFPSaVY452+meOQFympFStbyGJ3yrb7bg+X5M3Nn8GgD70j1OnL3aBN8XlgRI2pX4+HBnEUoE8210D8Ksi8D1rOYzib64w94jrGEiiqZzfZTiQCssFEI7TInZXmL3qWOWzMWVVLZl6azy4G1nvxK+vy69odrhrX3G/0TtmBj4sLochifrFGDbTXByO0LqAKjc= 102 | file: RSocket.Rpc.Protobuf/build/rsocket-rpc-protobuf-v${TRAVIS_TAG}-${TRAVIS_OS_NAME}-x64.tar.gz 103 | skip_cleanup: true 104 | on: 105 | repo: rsocket/rsocket-rpc-net 106 | tags: true 107 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2019 Netifi, Inc. 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | 204 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | RSocket RPC .NET 2 | 3 | Copyright 2018-2019 the original author or authors. 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RSocket RPC .NET 2 | An implementation of RSocket RPC for .NET. 3 | 4 | ## Builds 5 | [![Build Status](https://travis-ci.com/rsocket/rsocket-rpc-net.svg?branch=master)](https://travis-ci.com/rsocket/rsocket-rpc-net) 6 | [![NuGet Version](https://badge.fury.io/nu/RSocket.Rpc.Core.svg)](https://badge.fury.io/nu/RSocket.Rpc.Core) 7 | Releases are available via NuGet. 8 | -------------------------------------------------------------------------------- /RSocket.Rpc.Core/.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | obj 3 | -------------------------------------------------------------------------------- /RSocket.Rpc.Core/RSocket.Rpc.Core.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Copyright 2018-2019 the original author or authors. 5 | RSocket RPC Core 6 | RSocket RPC authors. 7 | netstandard2.0 8 | RSocket.Rpc.Core 9 | https://github.com/rsocket/rsocket-rpc-net 10 | Apache-2.0 11 | true 12 | latest 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /RSocket.Rpc.Core/RSocket.Rpc.Core.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RSocket.Rpc.Core", "RSocket.Rpc.Core.csproj", "{DEE7A938-6AC7-467F-ABCE-887465892FE6}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Any CPU = Debug|Any CPU 9 | Release|Any CPU = Release|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {DEE7A938-6AC7-467F-ABCE-887465892FE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {DEE7A938-6AC7-467F-ABCE-887465892FE6}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {DEE7A938-6AC7-467F-ABCE-887465892FE6}.Release|Any CPU.ActiveCfg = Release|Any CPU 15 | {DEE7A938-6AC7-467F-ABCE-887465892FE6}.Release|Any CPU.Build.0 = Release|Any CPU 16 | EndGlobalSection 17 | EndGlobal 18 | -------------------------------------------------------------------------------- /RSocket.Rpc.Core/RSocketService.Metadata.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers; 3 | using System.Text; 4 | 5 | namespace RSocket.RPC 6 | { 7 | partial class RSocketService 8 | { 9 | public struct RemoteProcedureCallMetadata //SPEC: https://github.com/rsocket/rsocket-rpc-java/blob/master/rsocket-rpc-core/src/main/java/io/rsocket/rpc/frames/Metadata.java 10 | { 11 | public const UInt16 VERSION = 1; 12 | 13 | public string Service; 14 | public string Method; 15 | public ReadOnlySequence Tracing; 16 | public ReadOnlySequence Metadata; 17 | static public readonly Encoding DefaultEncoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false); 18 | public int Length => sizeof(UInt16) + sizeof(UInt16) + DefaultEncoding.GetByteCount(Service) + sizeof(UInt16) + DefaultEncoding.GetByteCount(Method) + sizeof(UInt16) + (int)Tracing.Length + (int)Metadata.Length; 19 | public (string Service, string Method, ReadOnlySequence Tracing, ReadOnlySequence Metadata) AsTuple() => (Service, Method, Tracing, Metadata); 20 | 21 | public RemoteProcedureCallMetadata(string service, string method, ReadOnlySequence metadata, ReadOnlySequence tracing) { Service = service; Method = method; Metadata = metadata; Tracing = tracing; } 22 | 23 | public RemoteProcedureCallMetadata(ReadOnlySequence metadata) 24 | { 25 | var reader = new SequenceReader(metadata); 26 | if (!reader.TryReadBigEndian(out UInt16 version)) { throw new ArgumentOutOfRangeException(nameof(version), $"Invalid RPC Metadata."); } 27 | if (version != VERSION) { throw new ArgumentOutOfRangeException(nameof(version), $"Unsupported RPC Version {version}, expected {VERSION}."); } 28 | if (!reader.TryReadBigEndian(out UInt16 servicelength)) { throw new ArgumentOutOfRangeException(nameof(servicelength), $"Invalid RPC Metadata."); } 29 | if (reader.TryRead(out string service, servicelength)) { Service = service; } else { throw new ArgumentOutOfRangeException(nameof(service), $"Invalid RPC Metadata."); } 30 | if (!reader.TryReadBigEndian(out UInt16 methodlength)) { throw new ArgumentOutOfRangeException(nameof(methodlength), $"Invalid RPC Metadata."); } 31 | if (reader.TryRead(out string method, methodlength)) { Method = method; } else { throw new ArgumentOutOfRangeException(nameof(method), $"Invalid RPC Metadata."); } 32 | if (!reader.TryReadBigEndian(out UInt16 tracinglength)) { throw new ArgumentOutOfRangeException(nameof(tracinglength), $"Invalid RPC Metadata."); } 33 | Tracing = reader.Sequence.Slice(reader.Position, tracinglength); 34 | reader.Advance(tracinglength); 35 | Metadata = reader.Sequence.Slice(reader.Position, reader.Remaining); 36 | } 37 | 38 | public static RemoteProcedureCallMetadata create(ReadOnlySequence metadata) 39 | { 40 | return new RemoteProcedureCallMetadata(metadata); 41 | } 42 | 43 | public static implicit operator ReadOnlySequence(RemoteProcedureCallMetadata _) 44 | { 45 | var memory = new Memory(new byte[_.Length]); //FUTURE PERFORMANCE: Someday, maybe use a buffer pool instead of allocating. These are presumed small, but the string scan adds some overhead. 46 | _.Write(new BufferWriter(new Writer(memory), DefaultEncoding)); 47 | return new ReadOnlySequence(memory); 48 | } 49 | 50 | int Write(BufferWriter writer) 51 | { 52 | var written = writer.WriteUInt16BigEndian(VERSION); 53 | written += writer.WritePrefixShort(Service); 54 | written += writer.WritePrefixShort(Method); 55 | written += writer.WritePrefixShort(Tracing); 56 | written += writer.Write(Metadata); 57 | return written; 58 | } 59 | 60 | private struct Writer : IBufferWriter 61 | { 62 | int Position; 63 | Memory Buffer; 64 | public Writer(Memory buffer) { Buffer = buffer; Position = 0; } 65 | void IBufferWriter.Advance(int count) => Position += count; 66 | Memory IBufferWriter.GetMemory(int sizeHint) => Buffer.Slice(Position); 67 | Span IBufferWriter.GetSpan(int sizeHint) => Buffer.Slice(Position).Span; 68 | } 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /RSocket.Rpc.Core/RSocketService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Runtime.CompilerServices; 6 | using System.Threading.Tasks; 7 | 8 | namespace RSocket.RPC 9 | { 10 | public interface IRSocketService 11 | { 12 | string ServiceName { get; } 13 | IAsyncEnumerable> Dispatch(ReadOnlySequence data, string method, ReadOnlySequence tracing, ReadOnlySequence metadata, IAsyncEnumerable> messages); 14 | } 15 | 16 | public abstract partial class RSocketService 17 | { 18 | private readonly RSocket Socket; 19 | 20 | public RSocketService(RSocket socket) { Socket = socket; } 21 | 22 | protected Task __RequestFireAndForget(TMessage message, Func messagemapper, 23 | ReadOnlySequence metadata = default, ReadOnlySequence tracing = default, string service = default, [CallerMemberName]string method = default) 24 | => __RequestFireAndForget(new ReadOnlySequence(messagemapper(message)), metadata, tracing, service: service, method: method); 25 | 26 | protected Task __RequestFireAndForget(TMessage message, Func> messagemapper, 27 | ReadOnlySequence metadata = default, ReadOnlySequence tracing = default, string service = default, [CallerMemberName]string method = default) 28 | => __RequestFireAndForget(messagemapper(message), metadata, tracing, service: service, method: method); 29 | 30 | private protected Task __RequestFireAndForget( 31 | ReadOnlySequence data, ReadOnlySequence metadata = default, ReadOnlySequence tracing = default, string service = default, [CallerMemberName]string method = default) 32 | => Socket.RequestFireAndForget(data, new RemoteProcedureCallMetadata(service, method, metadata, tracing)); 33 | 34 | 35 | protected Task __RequestResponse(TMessage message, Func messagemapper, 36 | Func resultmapper, 37 | ReadOnlySequence metadata = default, ReadOnlySequence tracing = default, string service = default, [CallerMemberName]string method = default) 38 | => __RequestResponse(_ => resultmapper(_.data.ToArray()), new ReadOnlySequence(messagemapper(message)), metadata, tracing, service: service, method: method); 39 | 40 | protected Task __RequestResponse(TMessage message, Func> messagemapper, 41 | Func, TResult> resultmapper, 42 | ReadOnlySequence metadata = default, ReadOnlySequence tracing = default, string service = default, [CallerMemberName]string method = default) 43 | => __RequestResponse(_ => resultmapper(_.data), messagemapper(message), metadata, tracing, service: service, method: method); 44 | 45 | private protected Task __RequestResponse( 46 | Func<(ReadOnlySequence data, ReadOnlySequence metadata), T> resultmapper, 47 | ReadOnlySequence data = default, ReadOnlySequence metadata = default, ReadOnlySequence tracing = default, string service = default, [CallerMemberName]string method = default) 48 | => Socket.RequestResponse(resultmapper, data, new RemoteProcedureCallMetadata(service, method, metadata, tracing)); 49 | 50 | 51 | protected IAsyncEnumerable __RequestStream(TMessage message, 52 | Func sourcemapper, Func resultmapper, 53 | ReadOnlySequence metadata, ReadOnlySequence tracing = default, string service = default, [CallerMemberName]string method = default) 54 | => __RequestStream(resultmapper: value => resultmapper(value.data.ToArray()), new ReadOnlySequence(sourcemapper(message)), metadata, tracing, service: service, method: method); 55 | 56 | protected IAsyncEnumerable __RequestStream(TMessage message, 57 | Func> sourcemapper, Func, TResult> resultmapper, 58 | ReadOnlySequence metadata = default, ReadOnlySequence tracing = default, string service = default, [CallerMemberName]string method = default) 59 | => __RequestStream(result => resultmapper(result.data), sourcemapper(message), metadata, tracing, service: service, method: method); 60 | 61 | private protected IAsyncEnumerable __RequestStream( 62 | Func<(ReadOnlySequence data, ReadOnlySequence metadata), T> resultmapper, 63 | ReadOnlySequence data = default, ReadOnlySequence metadata = default, 64 | ReadOnlySequence tracing = default, string service = default, [CallerMemberName]string method = default) 65 | => Socket.RequestStream(resultmapper, data, new RemoteProcedureCallMetadata(service, method, metadata, tracing)); 66 | 67 | 68 | protected IAsyncEnumerable __RequestChannel(IAsyncEnumerable messages, 69 | Func sourcemapper, Func resultmapper, 70 | ReadOnlySequence data = default, ReadOnlySequence metadata = default, ReadOnlySequence tracing = default, string service = default, [CallerMemberName]string method = default) 71 | => __RequestChannel(messages, message => new ReadOnlySequence(sourcemapper(message)), result => resultmapper(result.data.ToArray()), data, metadata, tracing, service: service, method: method); 72 | 73 | protected IAsyncEnumerable __RequestChannel(IAsyncEnumerable messages, 74 | Func> sourcemapper, Func, TResult> resultmapper, 75 | ReadOnlySequence data = default, ReadOnlySequence metadata = default, ReadOnlySequence tracing = default, string service = default, [CallerMemberName]string method = default) 76 | => __RequestChannel(messages, message => sourcemapper(message), result => resultmapper(result.data), data, metadata, tracing, service: service, method: method); 77 | 78 | private protected IAsyncEnumerable __RequestChannel(IAsyncEnumerable source, 79 | Func> sourcemapper, Func<(ReadOnlySequence data, ReadOnlySequence metadata), T> resultmapper, 80 | ReadOnlySequence data = default, ReadOnlySequence metadata = default, ReadOnlySequence tracing = default, string service = default, [CallerMemberName]string method = default) 81 | => Socket.RequestChannel(source, sourcemapper, resultmapper, data, new RemoteProcedureCallMetadata(service, method, metadata, tracing)); 82 | 83 | 84 | // ****** Producer-side dispatching ***** // 85 | 86 | //TODO! Non-static, per-socket 87 | 88 | static System.Collections.Concurrent.ConcurrentDictionary Services = new System.Collections.Concurrent.ConcurrentDictionary(); 89 | 90 | static public void Register(RSocket socket, IRSocketService service, Func, RSocketService.RemoteProcedureCallMetadata> metadataMapper = null) 91 | { 92 | Services[service.ServiceName] = service; 93 | 94 | metadataMapper = metadataMapper ?? RemoteProcedureCallMetadata.create; 95 | //TODO Need to ensure that this really only happens once per Socket. 96 | 97 | socket.Respond(message => (RPC: metadataMapper(message.Metadata), message.Data), 98 | request => Dispatch(request.Data, request.RPC.Service, request.RPC.Method, request.RPC.Tracing, request.RPC.Metadata), 99 | result => (Data: result, Metadata: default)); 100 | 101 | //TODO This looks data/metadata backwards? 102 | socket.Stream(message => (RPC: metadataMapper(message.Metadata), message.Data), 103 | request => Dispatch(request.Data, request.RPC.Service, request.RPC.Method, request.RPC.Tracing, request.RPC.Metadata), 104 | result => (Data: result, Metadata: default)); 105 | 106 | socket.Channel((request, messages) => Dispatch(request.Data, request.RPC.Service, request.RPC.Method, request.RPC.Tracing, request.RPC.Metadata, messages.ToAsyncEnumerable()), 107 | message => (RPC: metadataMapper(message.Metadata), message.Data), 108 | incoming => incoming.Data, 109 | result => (Data: result, Metadata: default)); 110 | } 111 | 112 | static IAsyncEnumerable> Dispatch(ReadOnlySequence data, string service, string method, ReadOnlySequence tracing, ReadOnlySequence metadata, IAsyncEnumerable> messages = default) 113 | => (Services.TryGetValue(service, out var target)) ? target.Dispatch(data, method, tracing, metadata, messages ?? AsyncEnumerable.Empty>()) : throw new InvalidOperationException(); //TODO Handle invalid service name request. 114 | } 115 | 116 | static public class RSocketServiceExtensions 117 | { 118 | ////TODO Java style 119 | //socket.AddService(new MyEchoServiceServer()); 120 | 121 | static public void AddService(this RSocketServer socket, IRSocketService service) => RSocketService.Register(socket, service); 122 | } 123 | } -------------------------------------------------------------------------------- /RSocket.Rpc.Protobuf/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | cmake-build-debug -------------------------------------------------------------------------------- /RSocket.Rpc.Protobuf/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.2) 2 | 3 | project(rsocket_rpc_csharp_plugin) 4 | 5 | set(Protobuf_USE_STATIC_LIBS ON) 6 | set(CMAKE_CXX_STANDARD 11) 7 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") 8 | 9 | if (APPLE) 10 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libstdc++") 11 | else() 12 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libstdc++ -static-libgcc") 13 | endif() 14 | 15 | if(MSVC) 16 | set(CompilerFlags 17 | CMAKE_CXX_FLAGS 18 | CMAKE_CXX_FLAGS_DEBUG 19 | CMAKE_CXX_FLAGS_RELEASE) 20 | foreach(CompilerFlag ${CompilerFlags}) 21 | string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}") 22 | endforeach() 23 | endif() 24 | 25 | include(FindProtobuf) 26 | find_package(Protobuf REQUIRED) 27 | 28 | include_directories(${PROTOBUF_INCLUDE_DIR}) 29 | 30 | add_executable(${PROJECT_NAME} 31 | src/rsocket/options.pb.cc 32 | src/csharp_plugin.cc 33 | src/csharp_generator.cc) 34 | 35 | set_target_properties(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}") 36 | target_link_libraries(${PROJECT_NAME} ${PROTOBUF_LIBRARY} ${Protobuf_PROTOC_LIBRARY} ${EXTRA_LIBS}) 37 | -------------------------------------------------------------------------------- /RSocket.Rpc.Protobuf/proto/google/protobuf/any.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 36 | option go_package = "github.com/golang/protobuf/ptypes/any"; 37 | option java_package = "com.google.protobuf"; 38 | option java_outer_classname = "AnyProto"; 39 | option java_multiple_files = true; 40 | option objc_class_prefix = "GPB"; 41 | 42 | // `Any` contains an arbitrary serialized protocol buffer message along with a 43 | // URL that describes the type of the serialized message. 44 | // 45 | // Protobuf library provides support to pack/unpack Any values in the form 46 | // of utility functions or additional generated methods of the Any type. 47 | // 48 | // Example 1: Pack and unpack a message in C++. 49 | // 50 | // Foo foo = ...; 51 | // Any any; 52 | // any.PackFrom(foo); 53 | // ... 54 | // if (any.UnpackTo(&foo)) { 55 | // ... 56 | // } 57 | // 58 | // Example 2: Pack and unpack a message in Java. 59 | // 60 | // Foo foo = ...; 61 | // Any any = Any.pack(foo); 62 | // ... 63 | // if (any.is(Foo.class)) { 64 | // foo = any.unpack(Foo.class); 65 | // } 66 | // 67 | // Example 3: Pack and unpack a message in Python. 68 | // 69 | // foo = Foo(...) 70 | // any = Any() 71 | // any.Pack(foo) 72 | // ... 73 | // if any.Is(Foo.DESCRIPTOR): 74 | // any.Unpack(foo) 75 | // ... 76 | // 77 | // Example 4: Pack and unpack a message in Go 78 | // 79 | // foo := &pb.Foo{...} 80 | // any, err := ptypes.MarshalAny(foo) 81 | // ... 82 | // foo := &pb.Foo{} 83 | // if err := ptypes.UnmarshalAny(any, foo); err != nil { 84 | // ... 85 | // } 86 | // 87 | // The pack methods provided by protobuf library will by default use 88 | // 'type.googleapis.com/full.type.name' as the type URL and the unpack 89 | // methods only use the fully qualified type name after the last '/' 90 | // in the type URL, for example "foo.bar.com/x/y.z" will yield type 91 | // name "y.z". 92 | // 93 | // 94 | // JSON 95 | // ==== 96 | // The JSON representation of an `Any` value uses the regular 97 | // representation of the deserialized, embedded message, with an 98 | // additional field `@type` which contains the type URL. Example: 99 | // 100 | // package google.profile; 101 | // message Person { 102 | // string first_name = 1; 103 | // string last_name = 2; 104 | // } 105 | // 106 | // { 107 | // "@type": "type.googleapis.com/google.profile.Person", 108 | // "firstName": , 109 | // "lastName": 110 | // } 111 | // 112 | // If the embedded message type is well-known and has a custom JSON 113 | // representation, that representation will be embedded adding a field 114 | // `value` which holds the custom JSON in addition to the `@type` 115 | // field. Example (for message [google.protobuf.Duration][]): 116 | // 117 | // { 118 | // "@type": "type.googleapis.com/google.protobuf.Duration", 119 | // "value": "1.212s" 120 | // } 121 | // 122 | message Any { 123 | // A URL/resource name that uniquely identifies the type of the serialized 124 | // protocol buffer message. The last segment of the URL's path must represent 125 | // the fully qualified name of the type (as in 126 | // `path/google.protobuf.Duration`). The name should be in a canonical form 127 | // (e.g., leading "." is not accepted). 128 | // 129 | // In practice, teams usually precompile into the binary all types that they 130 | // expect it to use in the context of Any. However, for URLs which use the 131 | // scheme `http`, `https`, or no scheme, one can optionally set up a type 132 | // server that maps type URLs to message definitions as follows: 133 | // 134 | // * If no scheme is provided, `https` is assumed. 135 | // * An HTTP GET on the URL must yield a [google.protobuf.Type][] 136 | // value in binary format, or produce an error. 137 | // * Applications are allowed to cache lookup results based on the 138 | // URL, or have them precompiled into a binary to avoid any 139 | // lookup. Therefore, binary compatibility needs to be preserved 140 | // on changes to types. (Use versioned type names to manage 141 | // breaking changes.) 142 | // 143 | // Note: this functionality is not currently available in the official 144 | // protobuf release, and it is not used for type URLs beginning with 145 | // type.googleapis.com. 146 | // 147 | // Schemes other than `http`, `https` (or the empty scheme) might be 148 | // used with implementation specific semantics. 149 | // 150 | string type_url = 1; 151 | 152 | // Must be a valid serialized protocol buffer of the above specified type. 153 | bytes value = 2; 154 | } 155 | -------------------------------------------------------------------------------- /RSocket.Rpc.Protobuf/proto/google/protobuf/api.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | import "google/protobuf/source_context.proto"; 36 | import "google/protobuf/type.proto"; 37 | 38 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 39 | option java_package = "com.google.protobuf"; 40 | option java_outer_classname = "ApiProto"; 41 | option java_multiple_files = true; 42 | option objc_class_prefix = "GPB"; 43 | option go_package = "google.golang.org/genproto/protobuf/api;api"; 44 | 45 | // Api is a light-weight descriptor for an API Interface. 46 | // 47 | // Interfaces are also described as "protocol buffer services" in some contexts, 48 | // such as by the "service" keyword in a .proto file, but they are different 49 | // from API Services, which represent a concrete implementation of an interface 50 | // as opposed to simply a description of methods and bindings. They are also 51 | // sometimes simply referred to as "APIs" in other contexts, such as the name of 52 | // this message itself. See https://cloud.google.com/apis/design/glossary for 53 | // detailed terminology. 54 | message Api { 55 | 56 | // The fully qualified name of this interface, including package name 57 | // followed by the interface's simple name. 58 | string name = 1; 59 | 60 | // The methods of this interface, in unspecified order. 61 | repeated Method methods = 2; 62 | 63 | // Any metadata attached to the interface. 64 | repeated Option options = 3; 65 | 66 | // A version string for this interface. If specified, must have the form 67 | // `major-version.minor-version`, as in `1.10`. If the minor version is 68 | // omitted, it defaults to zero. If the entire version field is empty, the 69 | // major version is derived from the package name, as outlined below. If the 70 | // field is not empty, the version in the package name will be verified to be 71 | // consistent with what is provided here. 72 | // 73 | // The versioning schema uses [semantic 74 | // versioning](http://semver.org) where the major version number 75 | // indicates a breaking change and the minor version an additive, 76 | // non-breaking change. Both version numbers are signals to users 77 | // what to expect from different versions, and should be carefully 78 | // chosen based on the product plan. 79 | // 80 | // The major version is also reflected in the package name of the 81 | // interface, which must end in `v`, as in 82 | // `google.feature.v1`. For major versions 0 and 1, the suffix can 83 | // be omitted. Zero major versions must only be used for 84 | // experimental, non-GA interfaces. 85 | // 86 | // 87 | string version = 4; 88 | 89 | // Source context for the protocol buffer service represented by this 90 | // message. 91 | SourceContext source_context = 5; 92 | 93 | // Included interfaces. See [Mixin][]. 94 | repeated Mixin mixins = 6; 95 | 96 | // The source syntax of the service. 97 | Syntax syntax = 7; 98 | } 99 | 100 | // Method represents a method of an API interface. 101 | message Method { 102 | 103 | // The simple name of this method. 104 | string name = 1; 105 | 106 | // A URL of the input message type. 107 | string request_type_url = 2; 108 | 109 | // If true, the request is streamed. 110 | bool request_streaming = 3; 111 | 112 | // The URL of the output message type. 113 | string response_type_url = 4; 114 | 115 | // If true, the response is streamed. 116 | bool response_streaming = 5; 117 | 118 | // Any metadata attached to the method. 119 | repeated Option options = 6; 120 | 121 | // The source syntax of this method. 122 | Syntax syntax = 7; 123 | } 124 | 125 | // Declares an API Interface to be included in this interface. The including 126 | // interface must redeclare all the methods from the included interface, but 127 | // documentation and options are inherited as follows: 128 | // 129 | // - If after comment and whitespace stripping, the documentation 130 | // string of the redeclared method is empty, it will be inherited 131 | // from the original method. 132 | // 133 | // - Each annotation belonging to the service config (http, 134 | // visibility) which is not set in the redeclared method will be 135 | // inherited. 136 | // 137 | // - If an http annotation is inherited, the path pattern will be 138 | // modified as follows. Any version prefix will be replaced by the 139 | // version of the including interface plus the [root][] path if 140 | // specified. 141 | // 142 | // Example of a simple mixin: 143 | // 144 | // package google.acl.v1; 145 | // service AccessControl { 146 | // // Get the underlying ACL object. 147 | // rpc GetAcl(GetAclRequest) returns (Acl) { 148 | // option (google.api.http).get = "/v1/{resource=**}:getAcl"; 149 | // } 150 | // } 151 | // 152 | // package google.storage.v2; 153 | // service Storage { 154 | // rpc GetAcl(GetAclRequest) returns (Acl); 155 | // 156 | // // Get a data record. 157 | // rpc GetData(GetDataRequest) returns (Data) { 158 | // option (google.api.http).get = "/v2/{resource=**}"; 159 | // } 160 | // } 161 | // 162 | // Example of a mixin configuration: 163 | // 164 | // apis: 165 | // - name: google.storage.v2.Storage 166 | // mixins: 167 | // - name: google.acl.v1.AccessControl 168 | // 169 | // The mixin construct implies that all methods in `AccessControl` are 170 | // also declared with same name and request/response types in 171 | // `Storage`. A documentation generator or annotation processor will 172 | // see the effective `Storage.GetAcl` method after inherting 173 | // documentation and annotations as follows: 174 | // 175 | // service Storage { 176 | // // Get the underlying ACL object. 177 | // rpc GetAcl(GetAclRequest) returns (Acl) { 178 | // option (google.api.http).get = "/v2/{resource=**}:getAcl"; 179 | // } 180 | // ... 181 | // } 182 | // 183 | // Note how the version in the path pattern changed from `v1` to `v2`. 184 | // 185 | // If the `root` field in the mixin is specified, it should be a 186 | // relative path under which inherited HTTP paths are placed. Example: 187 | // 188 | // apis: 189 | // - name: google.storage.v2.Storage 190 | // mixins: 191 | // - name: google.acl.v1.AccessControl 192 | // root: acls 193 | // 194 | // This implies the following inherited HTTP annotation: 195 | // 196 | // service Storage { 197 | // // Get the underlying ACL object. 198 | // rpc GetAcl(GetAclRequest) returns (Acl) { 199 | // option (google.api.http).get = "/v2/acls/{resource=**}:getAcl"; 200 | // } 201 | // ... 202 | // } 203 | message Mixin { 204 | // The fully qualified name of the interface which is included. 205 | string name = 1; 206 | 207 | // If non-empty specifies a path under which inherited HTTP paths 208 | // are rooted. 209 | string root = 2; 210 | } 211 | -------------------------------------------------------------------------------- /RSocket.Rpc.Protobuf/proto/google/protobuf/duration.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 36 | option cc_enable_arenas = true; 37 | option go_package = "github.com/golang/protobuf/ptypes/duration"; 38 | option java_package = "com.google.protobuf"; 39 | option java_outer_classname = "DurationProto"; 40 | option java_multiple_files = true; 41 | option objc_class_prefix = "GPB"; 42 | 43 | // A Duration represents a signed, fixed-length span of time represented 44 | // as a count of seconds and fractions of seconds at nanosecond 45 | // resolution. It is independent of any calendar and concepts like "day" 46 | // or "month". It is related to Timestamp in that the difference between 47 | // two Timestamp values is a Duration and it can be added or subtracted 48 | // from a Timestamp. Range is approximately +-10,000 years. 49 | // 50 | // # Examples 51 | // 52 | // Example 1: Compute Duration from two Timestamps in pseudo code. 53 | // 54 | // Timestamp start = ...; 55 | // Timestamp end = ...; 56 | // Duration duration = ...; 57 | // 58 | // duration.seconds = end.seconds - start.seconds; 59 | // duration.nanos = end.nanos - start.nanos; 60 | // 61 | // if (duration.seconds < 0 && duration.nanos > 0) { 62 | // duration.seconds += 1; 63 | // duration.nanos -= 1000000000; 64 | // } else if (durations.seconds > 0 && duration.nanos < 0) { 65 | // duration.seconds -= 1; 66 | // duration.nanos += 1000000000; 67 | // } 68 | // 69 | // Example 2: Compute Timestamp from Timestamp + Duration in pseudo code. 70 | // 71 | // Timestamp start = ...; 72 | // Duration duration = ...; 73 | // Timestamp end = ...; 74 | // 75 | // end.seconds = start.seconds + duration.seconds; 76 | // end.nanos = start.nanos + duration.nanos; 77 | // 78 | // if (end.nanos < 0) { 79 | // end.seconds -= 1; 80 | // end.nanos += 1000000000; 81 | // } else if (end.nanos >= 1000000000) { 82 | // end.seconds += 1; 83 | // end.nanos -= 1000000000; 84 | // } 85 | // 86 | // Example 3: Compute Duration from datetime.timedelta in Python. 87 | // 88 | // td = datetime.timedelta(days=3, minutes=10) 89 | // duration = Duration() 90 | // duration.FromTimedelta(td) 91 | // 92 | // # JSON Mapping 93 | // 94 | // In JSON format, the Duration type is encoded as a string rather than an 95 | // object, where the string ends in the suffix "s" (indicating seconds) and 96 | // is preceded by the number of seconds, with nanoseconds expressed as 97 | // fractional seconds. For example, 3 seconds with 0 nanoseconds should be 98 | // encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should 99 | // be expressed in JSON format as "3.000000001s", and 3 seconds and 1 100 | // microsecond should be expressed in JSON format as "3.000001s". 101 | // 102 | // 103 | message Duration { 104 | 105 | // Signed seconds of the span of time. Must be from -315,576,000,000 106 | // to +315,576,000,000 inclusive. Note: these bounds are computed from: 107 | // 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years 108 | int64 seconds = 1; 109 | 110 | // Signed fractions of a second at nanosecond resolution of the span 111 | // of time. Durations less than one second are represented with a 0 112 | // `seconds` field and a positive or negative `nanos` field. For durations 113 | // of one second or more, a non-zero value for the `nanos` field must be 114 | // of the same sign as the `seconds` field. Must be from -999,999,999 115 | // to +999,999,999 inclusive. 116 | int32 nanos = 2; 117 | } 118 | -------------------------------------------------------------------------------- /RSocket.Rpc.Protobuf/proto/google/protobuf/empty.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 36 | option go_package = "github.com/golang/protobuf/ptypes/empty"; 37 | option java_package = "com.google.protobuf"; 38 | option java_outer_classname = "EmptyProto"; 39 | option java_multiple_files = true; 40 | option objc_class_prefix = "GPB"; 41 | option cc_enable_arenas = true; 42 | 43 | // A generic empty message that you can re-use to avoid defining duplicated 44 | // empty messages in your APIs. A typical example is to use it as the request 45 | // or the response type of an API method. For instance: 46 | // 47 | // service Foo { 48 | // rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); 49 | // } 50 | // 51 | // The JSON representation for `Empty` is empty JSON object `{}`. 52 | message Empty {} 53 | -------------------------------------------------------------------------------- /RSocket.Rpc.Protobuf/proto/google/protobuf/field_mask.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 36 | option java_package = "com.google.protobuf"; 37 | option java_outer_classname = "FieldMaskProto"; 38 | option java_multiple_files = true; 39 | option objc_class_prefix = "GPB"; 40 | option go_package = "google.golang.org/genproto/protobuf/field_mask;field_mask"; 41 | 42 | // `FieldMask` represents a set of symbolic field paths, for example: 43 | // 44 | // paths: "f.a" 45 | // paths: "f.b.d" 46 | // 47 | // Here `f` represents a field in some root message, `a` and `b` 48 | // fields in the message found in `f`, and `d` a field found in the 49 | // message in `f.b`. 50 | // 51 | // Field masks are used to specify a subset of fields that should be 52 | // returned by a get operation or modified by an update operation. 53 | // Field masks also have a custom JSON encoding (see below). 54 | // 55 | // # Field Masks in Projections 56 | // 57 | // When used in the context of a projection, a response message or 58 | // sub-message is filtered by the API to only contain those fields as 59 | // specified in the mask. For example, if the mask in the previous 60 | // example is applied to a response message as follows: 61 | // 62 | // f { 63 | // a : 22 64 | // b { 65 | // d : 1 66 | // x : 2 67 | // } 68 | // y : 13 69 | // } 70 | // z: 8 71 | // 72 | // The result will not contain specific values for fields x,y and z 73 | // (their value will be set to the default, and omitted in proto text 74 | // output): 75 | // 76 | // 77 | // f { 78 | // a : 22 79 | // b { 80 | // d : 1 81 | // } 82 | // } 83 | // 84 | // A repeated field is not allowed except at the last position of a 85 | // paths string. 86 | // 87 | // If a FieldMask object is not present in a get operation, the 88 | // operation applies to all fields (as if a FieldMask of all fields 89 | // had been specified). 90 | // 91 | // Note that a field mask does not necessarily apply to the 92 | // top-level response message. In case of a REST get operation, the 93 | // field mask applies directly to the response, but in case of a REST 94 | // list operation, the mask instead applies to each individual message 95 | // in the returned resource list. In case of a REST custom method, 96 | // other definitions may be used. Where the mask applies will be 97 | // clearly documented together with its declaration in the API. In 98 | // any case, the effect on the returned resource/resources is required 99 | // behavior for APIs. 100 | // 101 | // # Field Masks in Update Operations 102 | // 103 | // A field mask in update operations specifies which fields of the 104 | // targeted resource are going to be updated. The API is required 105 | // to only change the values of the fields as specified in the mask 106 | // and leave the others untouched. If a resource is passed in to 107 | // describe the updated values, the API ignores the values of all 108 | // fields not covered by the mask. 109 | // 110 | // If a repeated field is specified for an update operation, the existing 111 | // repeated values in the target resource will be overwritten by the new values. 112 | // Note that a repeated field is only allowed in the last position of a `paths` 113 | // string. 114 | // 115 | // If a sub-message is specified in the last position of the field mask for an 116 | // update operation, then the existing sub-message in the target resource is 117 | // overwritten. Given the target message: 118 | // 119 | // f { 120 | // b { 121 | // d : 1 122 | // x : 2 123 | // } 124 | // c : 1 125 | // } 126 | // 127 | // And an update message: 128 | // 129 | // f { 130 | // b { 131 | // d : 10 132 | // } 133 | // } 134 | // 135 | // then if the field mask is: 136 | // 137 | // paths: "f.b" 138 | // 139 | // then the result will be: 140 | // 141 | // f { 142 | // b { 143 | // d : 10 144 | // } 145 | // c : 1 146 | // } 147 | // 148 | // However, if the update mask was: 149 | // 150 | // paths: "f.b.d" 151 | // 152 | // then the result would be: 153 | // 154 | // f { 155 | // b { 156 | // d : 10 157 | // x : 2 158 | // } 159 | // c : 1 160 | // } 161 | // 162 | // In order to reset a field's value to the default, the field must 163 | // be in the mask and set to the default value in the provided resource. 164 | // Hence, in order to reset all fields of a resource, provide a default 165 | // instance of the resource and set all fields in the mask, or do 166 | // not provide a mask as described below. 167 | // 168 | // If a field mask is not present on update, the operation applies to 169 | // all fields (as if a field mask of all fields has been specified). 170 | // Note that in the presence of schema evolution, this may mean that 171 | // fields the client does not know and has therefore not filled into 172 | // the request will be reset to their default. If this is unwanted 173 | // behavior, a specific service may require a client to always specify 174 | // a field mask, producing an error if not. 175 | // 176 | // As with get operations, the location of the resource which 177 | // describes the updated values in the request message depends on the 178 | // operation kind. In any case, the effect of the field mask is 179 | // required to be honored by the API. 180 | // 181 | // ## Considerations for HTTP REST 182 | // 183 | // The HTTP kind of an update operation which uses a field mask must 184 | // be set to PATCH instead of PUT in order to satisfy HTTP semantics 185 | // (PUT must only be used for full updates). 186 | // 187 | // # JSON Encoding of Field Masks 188 | // 189 | // In JSON, a field mask is encoded as a single string where paths are 190 | // separated by a comma. Fields name in each path are converted 191 | // to/from lower-camel naming conventions. 192 | // 193 | // As an example, consider the following message declarations: 194 | // 195 | // message Profile { 196 | // User user = 1; 197 | // Photo photo = 2; 198 | // } 199 | // message User { 200 | // string display_name = 1; 201 | // string address = 2; 202 | // } 203 | // 204 | // In proto a field mask for `Profile` may look as such: 205 | // 206 | // mask { 207 | // paths: "user.display_name" 208 | // paths: "photo" 209 | // } 210 | // 211 | // In JSON, the same mask is represented as below: 212 | // 213 | // { 214 | // mask: "user.displayName,photo" 215 | // } 216 | // 217 | // # Field Masks and Oneof Fields 218 | // 219 | // Field masks treat fields in oneofs just as regular fields. Consider the 220 | // following message: 221 | // 222 | // message SampleMessage { 223 | // oneof test_oneof { 224 | // string name = 4; 225 | // SubMessage sub_message = 9; 226 | // } 227 | // } 228 | // 229 | // The field mask can be: 230 | // 231 | // mask { 232 | // paths: "name" 233 | // } 234 | // 235 | // Or: 236 | // 237 | // mask { 238 | // paths: "sub_message" 239 | // } 240 | // 241 | // Note that oneof type names ("test_oneof" in this case) cannot be used in 242 | // paths. 243 | // 244 | // ## Field Mask Verification 245 | // 246 | // The implementation of any API method which has a FieldMask type field in the 247 | // request should verify the included field paths, and return an 248 | // `INVALID_ARGUMENT` error if any path is duplicated or unmappable. 249 | message FieldMask { 250 | // The set of field mask paths. 251 | repeated string paths = 1; 252 | } 253 | -------------------------------------------------------------------------------- /RSocket.Rpc.Protobuf/proto/google/protobuf/source_context.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 36 | option java_package = "com.google.protobuf"; 37 | option java_outer_classname = "SourceContextProto"; 38 | option java_multiple_files = true; 39 | option objc_class_prefix = "GPB"; 40 | option go_package = "google.golang.org/genproto/protobuf/source_context;source_context"; 41 | 42 | // `SourceContext` represents information about the source of a 43 | // protobuf element, like the file in which it is defined. 44 | message SourceContext { 45 | // The path-qualified name of the .proto file that contained the associated 46 | // protobuf element. For example: `"google/protobuf/source_context.proto"`. 47 | string file_name = 1; 48 | } 49 | -------------------------------------------------------------------------------- /RSocket.Rpc.Protobuf/proto/google/protobuf/struct.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 36 | option cc_enable_arenas = true; 37 | option go_package = "github.com/golang/protobuf/ptypes/struct;structpb"; 38 | option java_package = "com.google.protobuf"; 39 | option java_outer_classname = "StructProto"; 40 | option java_multiple_files = true; 41 | option objc_class_prefix = "GPB"; 42 | 43 | 44 | // `Struct` represents a structured data value, consisting of fields 45 | // which map to dynamically typed values. In some languages, `Struct` 46 | // might be supported by a native representation. For example, in 47 | // scripting languages like JS a struct is represented as an 48 | // object. The details of that representation are described together 49 | // with the proto support for the language. 50 | // 51 | // The JSON representation for `Struct` is JSON object. 52 | message Struct { 53 | // Unordered map of dynamically typed values. 54 | map fields = 1; 55 | } 56 | 57 | // `Value` represents a dynamically typed value which can be either 58 | // null, a number, a string, a boolean, a recursive struct value, or a 59 | // list of values. A producer of value is expected to set one of that 60 | // variants, absence of any variant indicates an error. 61 | // 62 | // The JSON representation for `Value` is JSON value. 63 | message Value { 64 | // The kind of value. 65 | oneof kind { 66 | // Represents a null value. 67 | NullValue null_value = 1; 68 | // Represents a double value. 69 | double number_value = 2; 70 | // Represents a string value. 71 | string string_value = 3; 72 | // Represents a boolean value. 73 | bool bool_value = 4; 74 | // Represents a structured value. 75 | Struct struct_value = 5; 76 | // Represents a repeated `Value`. 77 | ListValue list_value = 6; 78 | } 79 | } 80 | 81 | // `NullValue` is a singleton enumeration to represent the null value for the 82 | // `Value` type union. 83 | // 84 | // The JSON representation for `NullValue` is JSON `null`. 85 | enum NullValue { 86 | // Null value. 87 | NULL_VALUE = 0; 88 | } 89 | 90 | // `ListValue` is a wrapper around a repeated field of values. 91 | // 92 | // The JSON representation for `ListValue` is JSON array. 93 | message ListValue { 94 | // Repeated field of dynamically typed values. 95 | repeated Value values = 1; 96 | } 97 | -------------------------------------------------------------------------------- /RSocket.Rpc.Protobuf/proto/google/protobuf/timestamp.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 36 | option cc_enable_arenas = true; 37 | option go_package = "github.com/golang/protobuf/ptypes/timestamp"; 38 | option java_package = "com.google.protobuf"; 39 | option java_outer_classname = "TimestampProto"; 40 | option java_multiple_files = true; 41 | option objc_class_prefix = "GPB"; 42 | 43 | // A Timestamp represents a point in time independent of any time zone 44 | // or calendar, represented as seconds and fractions of seconds at 45 | // nanosecond resolution in UTC Epoch time. It is encoded using the 46 | // Proleptic Gregorian Calendar which extends the Gregorian calendar 47 | // backwards to year one. It is encoded assuming all minutes are 60 48 | // seconds long, i.e. leap seconds are "smeared" so that no leap second 49 | // table is needed for interpretation. Range is from 50 | // 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. 51 | // By restricting to that range, we ensure that we can convert to 52 | // and from RFC 3339 date strings. 53 | // See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt). 54 | // 55 | // # Examples 56 | // 57 | // Example 1: Compute Timestamp from POSIX `time()`. 58 | // 59 | // Timestamp timestamp; 60 | // timestamp.set_seconds(time(NULL)); 61 | // timestamp.set_nanos(0); 62 | // 63 | // Example 2: Compute Timestamp from POSIX `gettimeofday()`. 64 | // 65 | // struct timeval tv; 66 | // gettimeofday(&tv, NULL); 67 | // 68 | // Timestamp timestamp; 69 | // timestamp.set_seconds(tv.tv_sec); 70 | // timestamp.set_nanos(tv.tv_usec * 1000); 71 | // 72 | // Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. 73 | // 74 | // FILETIME ft; 75 | // GetSystemTimeAsFileTime(&ft); 76 | // UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; 77 | // 78 | // // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z 79 | // // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. 80 | // Timestamp timestamp; 81 | // timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); 82 | // timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); 83 | // 84 | // Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. 85 | // 86 | // long millis = System.currentTimeMillis(); 87 | // 88 | // Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) 89 | // .setNanos((int) ((millis % 1000) * 1000000)).build(); 90 | // 91 | // 92 | // Example 5: Compute Timestamp from current time in Python. 93 | // 94 | // timestamp = Timestamp() 95 | // timestamp.GetCurrentTime() 96 | // 97 | // # JSON Mapping 98 | // 99 | // In JSON format, the Timestamp type is encoded as a string in the 100 | // [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the 101 | // format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" 102 | // where {year} is always expressed using four digits while {month}, {day}, 103 | // {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional 104 | // seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), 105 | // are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone 106 | // is required. A proto3 JSON serializer should always use UTC (as indicated by 107 | // "Z") when printing the Timestamp type and a proto3 JSON parser should be 108 | // able to accept both UTC and other timezones (as indicated by an offset). 109 | // 110 | // For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past 111 | // 01:30 UTC on January 15, 2017. 112 | // 113 | // In JavaScript, one can convert a Date object to this format using the 114 | // standard [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString] 115 | // method. In Python, a standard `datetime.datetime` object can be converted 116 | // to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) 117 | // with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one 118 | // can use the Joda Time's [`ISODateTimeFormat.dateTime()`]( 119 | // http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime-- 120 | // ) to obtain a formatter capable of generating timestamps in this format. 121 | // 122 | // 123 | message Timestamp { 124 | 125 | // Represents seconds of UTC time since Unix epoch 126 | // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to 127 | // 9999-12-31T23:59:59Z inclusive. 128 | int64 seconds = 1; 129 | 130 | // Non-negative fractions of a second at nanosecond resolution. Negative 131 | // second values with fractions must still have non-negative nanos values 132 | // that count forward in time. Must be from 0 to 999,999,999 133 | // inclusive. 134 | int32 nanos = 2; 135 | } 136 | -------------------------------------------------------------------------------- /RSocket.Rpc.Protobuf/proto/google/protobuf/type.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | import "google/protobuf/any.proto"; 36 | import "google/protobuf/source_context.proto"; 37 | 38 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 39 | option cc_enable_arenas = true; 40 | option java_package = "com.google.protobuf"; 41 | option java_outer_classname = "TypeProto"; 42 | option java_multiple_files = true; 43 | option objc_class_prefix = "GPB"; 44 | option go_package = "google.golang.org/genproto/protobuf/ptype;ptype"; 45 | 46 | // A protocol buffer message type. 47 | message Type { 48 | // The fully qualified message name. 49 | string name = 1; 50 | // The list of fields. 51 | repeated Field fields = 2; 52 | // The list of types appearing in `oneof` definitions in this type. 53 | repeated string oneofs = 3; 54 | // The protocol buffer options. 55 | repeated Option options = 4; 56 | // The source context. 57 | SourceContext source_context = 5; 58 | // The source syntax. 59 | Syntax syntax = 6; 60 | } 61 | 62 | // A single field of a message type. 63 | message Field { 64 | // Basic field types. 65 | enum Kind { 66 | // Field type unknown. 67 | TYPE_UNKNOWN = 0; 68 | // Field type double. 69 | TYPE_DOUBLE = 1; 70 | // Field type float. 71 | TYPE_FLOAT = 2; 72 | // Field type int64. 73 | TYPE_INT64 = 3; 74 | // Field type uint64. 75 | TYPE_UINT64 = 4; 76 | // Field type int32. 77 | TYPE_INT32 = 5; 78 | // Field type fixed64. 79 | TYPE_FIXED64 = 6; 80 | // Field type fixed32. 81 | TYPE_FIXED32 = 7; 82 | // Field type bool. 83 | TYPE_BOOL = 8; 84 | // Field type string. 85 | TYPE_STRING = 9; 86 | // Field type group. Proto2 syntax only, and deprecated. 87 | TYPE_GROUP = 10; 88 | // Field type message. 89 | TYPE_MESSAGE = 11; 90 | // Field type bytes. 91 | TYPE_BYTES = 12; 92 | // Field type uint32. 93 | TYPE_UINT32 = 13; 94 | // Field type enum. 95 | TYPE_ENUM = 14; 96 | // Field type sfixed32. 97 | TYPE_SFIXED32 = 15; 98 | // Field type sfixed64. 99 | TYPE_SFIXED64 = 16; 100 | // Field type sint32. 101 | TYPE_SINT32 = 17; 102 | // Field type sint64. 103 | TYPE_SINT64 = 18; 104 | }; 105 | 106 | // Whether a field is optional, required, or repeated. 107 | enum Cardinality { 108 | // For fields with unknown cardinality. 109 | CARDINALITY_UNKNOWN = 0; 110 | // For optional fields. 111 | CARDINALITY_OPTIONAL = 1; 112 | // For required fields. Proto2 syntax only. 113 | CARDINALITY_REQUIRED = 2; 114 | // For repeated fields. 115 | CARDINALITY_REPEATED = 3; 116 | }; 117 | 118 | // The field type. 119 | Kind kind = 1; 120 | // The field cardinality. 121 | Cardinality cardinality = 2; 122 | // The field number. 123 | int32 number = 3; 124 | // The field name. 125 | string name = 4; 126 | // The field type URL, without the scheme, for message or enumeration 127 | // types. Example: `"type.googleapis.com/google.protobuf.Timestamp"`. 128 | string type_url = 6; 129 | // The index of the field type in `Type.oneofs`, for message or enumeration 130 | // types. The first type has index 1; zero means the type is not in the list. 131 | int32 oneof_index = 7; 132 | // Whether to use alternative packed wire representation. 133 | bool packed = 8; 134 | // The protocol buffer options. 135 | repeated Option options = 9; 136 | // The field JSON name. 137 | string json_name = 10; 138 | // The string value of the default value of this field. Proto2 syntax only. 139 | string default_value = 11; 140 | } 141 | 142 | // Enum type definition. 143 | message Enum { 144 | // Enum type name. 145 | string name = 1; 146 | // Enum value definitions. 147 | repeated EnumValue enumvalue = 2; 148 | // Protocol buffer options. 149 | repeated Option options = 3; 150 | // The source context. 151 | SourceContext source_context = 4; 152 | // The source syntax. 153 | Syntax syntax = 5; 154 | } 155 | 156 | // Enum value definition. 157 | message EnumValue { 158 | // Enum value name. 159 | string name = 1; 160 | // Enum value number. 161 | int32 number = 2; 162 | // Protocol buffer options. 163 | repeated Option options = 3; 164 | } 165 | 166 | // A protocol buffer option, which can be attached to a message, field, 167 | // enumeration, etc. 168 | message Option { 169 | // The option's name. For protobuf built-in options (options defined in 170 | // descriptor.proto), this is the short name. For example, `"map_entry"`. 171 | // For custom options, it should be the fully-qualified name. For example, 172 | // `"google.api.http"`. 173 | string name = 1; 174 | // The option's value packed in an Any message. If the value is a primitive, 175 | // the corresponding wrapper type defined in google/protobuf/wrappers.proto 176 | // should be used. If the value is an enum, it should be stored as an int32 177 | // value using the google.protobuf.Int32Value type. 178 | Any value = 2; 179 | } 180 | 181 | // The syntax in which a protocol buffer element is defined. 182 | enum Syntax { 183 | // Syntax `proto2`. 184 | SYNTAX_PROTO2 = 0; 185 | // Syntax `proto3`. 186 | SYNTAX_PROTO3 = 1; 187 | } 188 | -------------------------------------------------------------------------------- /RSocket.Rpc.Protobuf/proto/google/protobuf/wrappers.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | // Wrappers for primitive (non-message) types. These types are useful 32 | // for embedding primitives in the `google.protobuf.Any` type and for places 33 | // where we need to distinguish between the absence of a primitive 34 | // typed field and its default value. 35 | 36 | syntax = "proto3"; 37 | 38 | package google.protobuf; 39 | 40 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 41 | option cc_enable_arenas = true; 42 | option go_package = "github.com/golang/protobuf/ptypes/wrappers"; 43 | option java_package = "com.google.protobuf"; 44 | option java_outer_classname = "WrappersProto"; 45 | option java_multiple_files = true; 46 | option objc_class_prefix = "GPB"; 47 | 48 | // Wrapper message for `double`. 49 | // 50 | // The JSON representation for `DoubleValue` is JSON number. 51 | message DoubleValue { 52 | // The double value. 53 | double value = 1; 54 | } 55 | 56 | // Wrapper message for `float`. 57 | // 58 | // The JSON representation for `FloatValue` is JSON number. 59 | message FloatValue { 60 | // The float value. 61 | float value = 1; 62 | } 63 | 64 | // Wrapper message for `int64`. 65 | // 66 | // The JSON representation for `Int64Value` is JSON string. 67 | message Int64Value { 68 | // The int64 value. 69 | int64 value = 1; 70 | } 71 | 72 | // Wrapper message for `uint64`. 73 | // 74 | // The JSON representation for `UInt64Value` is JSON string. 75 | message UInt64Value { 76 | // The uint64 value. 77 | uint64 value = 1; 78 | } 79 | 80 | // Wrapper message for `int32`. 81 | // 82 | // The JSON representation for `Int32Value` is JSON number. 83 | message Int32Value { 84 | // The int32 value. 85 | int32 value = 1; 86 | } 87 | 88 | // Wrapper message for `uint32`. 89 | // 90 | // The JSON representation for `UInt32Value` is JSON number. 91 | message UInt32Value { 92 | // The uint32 value. 93 | uint32 value = 1; 94 | } 95 | 96 | // Wrapper message for `bool`. 97 | // 98 | // The JSON representation for `BoolValue` is JSON `true` and `false`. 99 | message BoolValue { 100 | // The bool value. 101 | bool value = 1; 102 | } 103 | 104 | // Wrapper message for `string`. 105 | // 106 | // The JSON representation for `StringValue` is JSON string. 107 | message StringValue { 108 | // The string value. 109 | string value = 1; 110 | } 111 | 112 | // Wrapper message for `bytes`. 113 | // 114 | // The JSON representation for `BytesValue` is JSON string. 115 | message BytesValue { 116 | // The bytes value. 117 | bytes value = 1; 118 | } 119 | -------------------------------------------------------------------------------- /RSocket.Rpc.Protobuf/proto/rsocket/options.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package io.rsocket.rpc; 4 | 5 | import "google/protobuf/descriptor.proto"; 6 | 7 | option java_package = "io.rsocket.rpc"; 8 | option java_outer_classname = "RSocketOptions"; 9 | option java_multiple_files = true; 10 | 11 | extend google.protobuf.MethodOptions { 12 | RSocketMethodOptions options = 1057; 13 | } 14 | 15 | message RSocketMethodOptions { 16 | bool fire_and_forget = 1; 17 | } -------------------------------------------------------------------------------- /RSocket.Rpc.Protobuf/src/csharp_generator.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (c) 2017-present, Netifi Inc. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #ifndef RSOCKET_RPC_COMPILER_CSHARP_GENERATOR_H 20 | #define RSOCKET_RPC_COMPILER_CSHARP_GENERATOR_H 21 | 22 | #include 23 | 24 | using namespace std; 25 | 26 | namespace rsocket_rpc_csharp_generator { 27 | 28 | string GetServices(const google::protobuf::FileDescriptor* file, 29 | bool generate_client, bool generate_server); 30 | 31 | } // namespace rsocket_rpc_csharp_generator 32 | 33 | #endif // RSOCKET_RPC_COMPILER_CSHARP_GENERATOR_H 34 | -------------------------------------------------------------------------------- /RSocket.Rpc.Protobuf/src/csharp_generator_helpers.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (c) 2017-present, Netifi Inc. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #ifndef RSOCKET_RPC_COMPILER_CSHARP_GENERATOR_HELPERS_H 20 | #define RSOCKET_RPC_COMPILER_CSHARP_GENERATOR_HELPERS_H 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | using namespace std; 31 | 32 | namespace rsocket_rpc_csharp_generator { 33 | 34 | inline bool StripSuffix(string* filename, const string& suffix) { 35 | if (filename->length() >= suffix.length()) { 36 | size_t suffix_pos = filename->length() - suffix.length(); 37 | if (filename->compare(suffix_pos, string::npos, suffix) == 0) { 38 | filename->resize(filename->size() - suffix.size()); 39 | return true; 40 | } 41 | } 42 | 43 | return false; 44 | } 45 | 46 | inline bool StripPrefix(string* name, const string& prefix) { 47 | if (name->length() >= prefix.length()) { 48 | if (name->substr(0, prefix.size()) == prefix) { 49 | *name = name->substr(prefix.size()); 50 | return true; 51 | } 52 | } 53 | return false; 54 | } 55 | 56 | inline string StripProto(string filename) { 57 | if (!StripSuffix(&filename, ".protodevel")) { 58 | StripSuffix(&filename, ".proto"); 59 | } 60 | return filename; 61 | } 62 | 63 | inline string StringReplace(string str, const string& from, 64 | const string& to, bool replace_all) { 65 | size_t pos = 0; 66 | 67 | do { 68 | pos = str.find(from, pos); 69 | if (pos == string::npos) { 70 | break; 71 | } 72 | str.replace(pos, from.length(), to); 73 | pos += to.length(); 74 | } while (replace_all); 75 | 76 | return str; 77 | } 78 | 79 | inline string StringReplace(string str, const string& from, 80 | const string& to) { 81 | return StringReplace(str, from, to, true); 82 | } 83 | 84 | inline std::vector tokenize(const string& input, 85 | const string& delimiters) { 86 | std::vector tokens; 87 | size_t pos, last_pos = 0; 88 | 89 | for (;;) { 90 | bool done = false; 91 | pos = input.find_first_of(delimiters, last_pos); 92 | if (pos == string::npos) { 93 | done = true; 94 | pos = input.length(); 95 | } 96 | 97 | tokens.push_back(input.substr(last_pos, pos - last_pos)); 98 | if (done) return tokens; 99 | 100 | last_pos = pos + 1; 101 | } 102 | } 103 | 104 | inline string CapitalizeFirstLetter(string s) { 105 | if (s.empty()) { 106 | return s; 107 | } 108 | s[0] = ::toupper(s[0]); 109 | return s; 110 | } 111 | 112 | inline string LowercaseFirstLetter(string s) { 113 | if (s.empty()) { 114 | return s; 115 | } 116 | s[0] = ::tolower(s[0]); 117 | return s; 118 | } 119 | 120 | inline string LowerUnderscoreToUpperCamel(string str) { 121 | std::vector tokens = tokenize(str, "_"); 122 | string result = ""; 123 | for (unsigned int i = 0; i < tokens.size(); i++) { 124 | result += CapitalizeFirstLetter(tokens[i]); 125 | } 126 | return result; 127 | } 128 | 129 | inline string FileNameInUpperCamel( 130 | const google::protobuf::FileDescriptor* file, bool include_package_path) { 131 | std::vector tokens = tokenize(StripProto(file->name()), "/"); 132 | string result = ""; 133 | if (include_package_path) { 134 | for (unsigned int i = 0; i < tokens.size() - 1; i++) { 135 | result += tokens[i] + "/"; 136 | } 137 | } 138 | result += LowerUnderscoreToUpperCamel(tokens.back()); 139 | return result; 140 | } 141 | 142 | inline string FileNameInUpperCamel( 143 | const google::protobuf::FileDescriptor* file) { 144 | return FileNameInUpperCamel(file, true); 145 | } 146 | 147 | inline void Split(const string& s, char delim, 148 | std::vector* append_to) { 149 | std::istringstream iss(s); 150 | string piece; 151 | while (std::getline(iss, piece)) { 152 | append_to->push_back(piece); 153 | } 154 | } 155 | 156 | enum CommentType { 157 | COMMENTTYPE_LEADING, 158 | COMMENTTYPE_TRAILING, 159 | COMMENTTYPE_LEADING_DETACHED 160 | }; 161 | 162 | // Get all the raw comments and append each line without newline to out. 163 | template 164 | inline void GetComment(const DescriptorType* desc, CommentType type, 165 | std::vector* out) { 166 | google::protobuf::SourceLocation location; 167 | if (!desc->GetSourceLocation(&location)) { 168 | return; 169 | } 170 | if (type == COMMENTTYPE_LEADING || type == COMMENTTYPE_TRAILING) { 171 | const string& comments = type == COMMENTTYPE_LEADING 172 | ? location.leading_comments 173 | : location.trailing_comments; 174 | Split(comments, '\n', out); 175 | } else if (type == COMMENTTYPE_LEADING_DETACHED) { 176 | for (unsigned int i = 0; i < location.leading_detached_comments.size(); 177 | i++) { 178 | Split(location.leading_detached_comments[i], '\n', out); 179 | out->push_back(""); 180 | } 181 | } else { 182 | std::cerr << "Unknown comment type " << type << std::endl; 183 | abort(); 184 | } 185 | } 186 | 187 | // Each raw comment line without newline is appended to out. 188 | // For file level leading and detached leading comments, we return comments 189 | // above syntax line. Return nothing for trailing comments. 190 | template <> 191 | inline void GetComment(const google::protobuf::FileDescriptor* desc, 192 | CommentType type, std::vector* out) { 193 | if (type == COMMENTTYPE_TRAILING) { 194 | return; 195 | } 196 | google::protobuf::SourceLocation location; 197 | std::vector path; 198 | path.push_back(google::protobuf::FileDescriptorProto::kSyntaxFieldNumber); 199 | if (!desc->GetSourceLocation(path, &location)) { 200 | return; 201 | } 202 | if (type == COMMENTTYPE_LEADING) { 203 | Split(location.leading_comments, '\n', out); 204 | } else if (type == COMMENTTYPE_LEADING_DETACHED) { 205 | for (unsigned int i = 0; i < location.leading_detached_comments.size(); 206 | i++) { 207 | Split(location.leading_detached_comments[i], '\n', out); 208 | out->push_back(""); 209 | } 210 | } else { 211 | std::cerr << "Unknown comment type " << type << std::endl; 212 | abort(); 213 | } 214 | } 215 | 216 | // Add prefix and newline to each comment line and concatenate them together. 217 | // Make sure there is a space after the prefix unless the line is empty. 218 | inline string GenerateCommentsWithPrefix( 219 | const std::vector& in, const string& prefix) { 220 | std::ostringstream oss; 221 | for (auto it = in.begin(); it != in.end(); it++) { 222 | const string& elem = *it; 223 | if (elem.empty()) { 224 | oss << prefix << "\n"; 225 | } else if (elem[0] == ' ') { 226 | oss << prefix << elem << "\n"; 227 | } else { 228 | oss << prefix << " " << elem << "\n"; 229 | } 230 | } 231 | return oss.str(); 232 | } 233 | 234 | template 235 | inline string GetPrefixedComments(const DescriptorType* desc, 236 | bool leading, 237 | const string& prefix) { 238 | std::vector out; 239 | if (leading) { 240 | GetComment( 241 | desc, COMMENTTYPE_LEADING_DETACHED, &out); 242 | std::vector leading; 243 | GetComment(desc, COMMENTTYPE_LEADING, 244 | &leading); 245 | out.insert(out.end(), leading.begin(), leading.end()); 246 | } else { 247 | GetComment(desc, COMMENTTYPE_TRAILING, 248 | &out); 249 | } 250 | return GenerateCommentsWithPrefix(out, prefix); 251 | } 252 | 253 | inline bool ServicesFilename(const google::protobuf::FileDescriptor* file, 254 | string* file_name_or_error) { 255 | *file_name_or_error = 256 | FileNameInUpperCamel(file, false) + "RSocketRpc.cs"; 257 | return true; 258 | } 259 | 260 | // Get leading or trailing comments in a string. Comment lines start with "// ". 261 | // Leading detached comments are put in in front of leading comments. 262 | template 263 | inline string GetCsharpComments(const DescriptorType* desc, 264 | bool leading) { 265 | return GetPrefixedComments(desc, leading, "//"); 266 | } 267 | 268 | } // namespace rsocket_rpc_csharp_generator 269 | 270 | #endif // RSOCKET_RPC_COMPILER_CSHARP_GENERATOR_HELPERS_H 271 | -------------------------------------------------------------------------------- /RSocket.Rpc.Protobuf/src/csharp_plugin.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (c) 2017-present, Netifi Inc. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | // Generates C# RSocket RPC service interface out of Protobuf IDL. 20 | 21 | #include 22 | 23 | #include "csharp_generator.h" 24 | #include "csharp_generator_helpers.h" 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | class CSharpRSocketGenerator : public google::protobuf::compiler::CodeGenerator { 32 | public: 33 | CSharpRSocketGenerator() {} 34 | ~CSharpRSocketGenerator() {} 35 | 36 | bool Generate(const google::protobuf::FileDescriptor* file, 37 | const string& parameter, 38 | google::protobuf::compiler::GeneratorContext* context, 39 | string* error) const { 40 | std::vector > options; 41 | google::protobuf::compiler::ParseGeneratorParameter(parameter, &options); 42 | 43 | bool generate_client = true; 44 | bool generate_server = true; 45 | for (size_t i = 0; i < options.size(); i++) { 46 | if (options[i].first == "no_client") { 47 | generate_client = false; 48 | } else if (options[i].first == "no_server") { 49 | generate_server = false; 50 | } else { 51 | *error = "Unknown generator option: " + options[i].first; 52 | return false; 53 | } 54 | } 55 | 56 | string code = rsocket_rpc_csharp_generator::GetServices( 57 | file, generate_client, generate_server); 58 | if (code.size() == 0) { 59 | return true; // don't generate a file if there are no services 60 | } 61 | 62 | // Get output file name. 63 | string file_name; 64 | if (!rsocket_rpc_csharp_generator::ServicesFilename(file, &file_name)) { 65 | return false; 66 | } 67 | std::unique_ptr output( 68 | context->Open(file_name)); 69 | google::protobuf::io::CodedOutputStream coded_out(output.get()); 70 | coded_out.WriteRaw(code.data(), code.size()); 71 | return true; 72 | } 73 | }; 74 | 75 | int main(int argc, char* argv[]) { 76 | CSharpRSocketGenerator generator; 77 | return google::protobuf::compiler::PluginMain(argc, argv, &generator); 78 | } 79 | -------------------------------------------------------------------------------- /RSocket.Rpc.Protobuf/src/rsocket/options.pb.h: -------------------------------------------------------------------------------- 1 | // Generated by the protocol buffer compiler. DO NOT EDIT! 2 | // source: rsocket/options.proto 3 | 4 | #ifndef PROTOBUF_INCLUDED_rsocket_2foptions_2eproto 5 | #define PROTOBUF_INCLUDED_rsocket_2foptions_2eproto 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include // IWYU pragma: export 20 | #include // IWYU pragma: export 21 | #include 22 | #include 23 | // @@protoc_insertion_point(includes) 24 | #define PROTOBUF_INTERNAL_EXPORT_protobuf_rsocket_2foptions_2eproto 25 | 26 | namespace protobuf_rsocket_2foptions_2eproto { 27 | // Internal implementation detail -- do not use these members. 28 | struct TableStruct { 29 | static const ::google::protobuf::internal::ParseTableField entries[]; 30 | static const ::google::protobuf::internal::AuxillaryParseTableField aux[]; 31 | static const ::google::protobuf::internal::ParseTable schema[1]; 32 | static const ::google::protobuf::internal::FieldMetadata field_metadata[]; 33 | static const ::google::protobuf::internal::SerializationTable serialization_table[]; 34 | static const ::google::protobuf::uint32 offsets[]; 35 | }; 36 | void AddDescriptors(); 37 | } // namespace protobuf_rsocket_2foptions_2eproto 38 | namespace io { 39 | namespace rsocket { 40 | namespace rpc { 41 | class RSocketMethodOptions; 42 | class RSocketMethodOptionsDefaultTypeInternal; 43 | extern RSocketMethodOptionsDefaultTypeInternal _RSocketMethodOptions_default_instance_; 44 | } // namespace rpc 45 | } // namespace rsocket 46 | } // namespace io 47 | namespace google { 48 | namespace protobuf { 49 | template<> ::io::rsocket::rpc::RSocketMethodOptions* Arena::CreateMaybeMessage<::io::rsocket::rpc::RSocketMethodOptions>(Arena*); 50 | } // namespace protobuf 51 | } // namespace google 52 | namespace io { 53 | namespace rsocket { 54 | namespace rpc { 55 | 56 | // =================================================================== 57 | 58 | class RSocketMethodOptions : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:io.rsocket.rpc.RSocketMethodOptions) */ { 59 | public: 60 | RSocketMethodOptions(); 61 | virtual ~RSocketMethodOptions(); 62 | 63 | RSocketMethodOptions(const RSocketMethodOptions& from); 64 | 65 | inline RSocketMethodOptions& operator=(const RSocketMethodOptions& from) { 66 | CopyFrom(from); 67 | return *this; 68 | } 69 | #if LANG_CXX11 70 | RSocketMethodOptions(RSocketMethodOptions&& from) noexcept 71 | : RSocketMethodOptions() { 72 | *this = ::std::move(from); 73 | } 74 | 75 | inline RSocketMethodOptions& operator=(RSocketMethodOptions&& from) noexcept { 76 | if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { 77 | if (this != &from) InternalSwap(&from); 78 | } else { 79 | CopyFrom(from); 80 | } 81 | return *this; 82 | } 83 | #endif 84 | static const ::google::protobuf::Descriptor* descriptor(); 85 | static const RSocketMethodOptions& default_instance(); 86 | 87 | static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY 88 | static inline const RSocketMethodOptions* internal_default_instance() { 89 | return reinterpret_cast( 90 | &_RSocketMethodOptions_default_instance_); 91 | } 92 | static constexpr int kIndexInFileMessages = 93 | 0; 94 | 95 | void Swap(RSocketMethodOptions* other); 96 | friend void swap(RSocketMethodOptions& a, RSocketMethodOptions& b) { 97 | a.Swap(&b); 98 | } 99 | 100 | // implements Message ---------------------------------------------- 101 | 102 | inline RSocketMethodOptions* New() const final { 103 | return CreateMaybeMessage(NULL); 104 | } 105 | 106 | RSocketMethodOptions* New(::google::protobuf::Arena* arena) const final { 107 | return CreateMaybeMessage(arena); 108 | } 109 | void CopyFrom(const ::google::protobuf::Message& from) final; 110 | void MergeFrom(const ::google::protobuf::Message& from) final; 111 | void CopyFrom(const RSocketMethodOptions& from); 112 | void MergeFrom(const RSocketMethodOptions& from); 113 | void Clear() final; 114 | bool IsInitialized() const final; 115 | 116 | size_t ByteSizeLong() const final; 117 | bool MergePartialFromCodedStream( 118 | ::google::protobuf::io::CodedInputStream* input) final; 119 | void SerializeWithCachedSizes( 120 | ::google::protobuf::io::CodedOutputStream* output) const final; 121 | ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( 122 | bool deterministic, ::google::protobuf::uint8* target) const final; 123 | int GetCachedSize() const final { return _cached_size_.Get(); } 124 | 125 | private: 126 | void SharedCtor(); 127 | void SharedDtor(); 128 | void SetCachedSize(int size) const final; 129 | void InternalSwap(RSocketMethodOptions* other); 130 | private: 131 | inline ::google::protobuf::Arena* GetArenaNoVirtual() const { 132 | return NULL; 133 | } 134 | inline void* MaybeArenaPtr() const { 135 | return NULL; 136 | } 137 | public: 138 | 139 | ::google::protobuf::Metadata GetMetadata() const final; 140 | 141 | // nested types ---------------------------------------------------- 142 | 143 | // accessors ------------------------------------------------------- 144 | 145 | // bool fire_and_forget = 1; 146 | void clear_fire_and_forget(); 147 | static const int kFireAndForgetFieldNumber = 1; 148 | bool fire_and_forget() const; 149 | void set_fire_and_forget(bool value); 150 | 151 | // @@protoc_insertion_point(class_scope:io.rsocket.rpc.RSocketMethodOptions) 152 | private: 153 | 154 | ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; 155 | bool fire_and_forget_; 156 | mutable ::google::protobuf::internal::CachedSize _cached_size_; 157 | friend struct ::protobuf_rsocket_2foptions_2eproto::TableStruct; 158 | }; 159 | // =================================================================== 160 | 161 | static const int kOptionsFieldNumber = 1057; 162 | extern ::google::protobuf::internal::ExtensionIdentifier< ::google::protobuf::MethodOptions, 163 | ::google::protobuf::internal::MessageTypeTraits< ::io::rsocket::rpc::RSocketMethodOptions >, 11, false > 164 | options; 165 | 166 | // =================================================================== 167 | 168 | #ifdef __GNUC__ 169 | #pragma GCC diagnostic push 170 | #pragma GCC diagnostic ignored "-Wstrict-aliasing" 171 | #endif // __GNUC__ 172 | // RSocketMethodOptions 173 | 174 | // bool fire_and_forget = 1; 175 | inline void RSocketMethodOptions::clear_fire_and_forget() { 176 | fire_and_forget_ = false; 177 | } 178 | inline bool RSocketMethodOptions::fire_and_forget() const { 179 | // @@protoc_insertion_point(field_get:io.rsocket.rpc.RSocketMethodOptions.fire_and_forget) 180 | return fire_and_forget_; 181 | } 182 | inline void RSocketMethodOptions::set_fire_and_forget(bool value) { 183 | 184 | fire_and_forget_ = value; 185 | // @@protoc_insertion_point(field_set:io.rsocket.rpc.RSocketMethodOptions.fire_and_forget) 186 | } 187 | 188 | #ifdef __GNUC__ 189 | #pragma GCC diagnostic pop 190 | #endif // __GNUC__ 191 | 192 | // @@protoc_insertion_point(namespace_scope) 193 | 194 | } // namespace rpc 195 | } // namespace rsocket 196 | } // namespace io 197 | 198 | // @@protoc_insertion_point(global_scope) 199 | 200 | #endif // PROTOBUF_INCLUDED_rsocket_2foptions_2eproto 201 | -------------------------------------------------------------------------------- /RSocket.Rpc.Sample/EchoService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers; 3 | using System.Collections.Generic; 4 | using System.Threading.Tasks; 5 | using RSocket; 6 | using RSocket.RPC; 7 | using System.Threading; 8 | using System.Linq; 9 | 10 | namespace RSocketRPCSample 11 | { 12 | [System.Runtime.CompilerServices.CompilerGenerated] 13 | public static class EchoService 14 | { 15 | public const string Service = "io.rsocket.rpc.echo.EchoService"; 16 | public const string Method_fireAndForget = "fireAndForget"; 17 | public const string Method_requestResponse = "requestResponse"; 18 | public const string Method_requestStream = "requestStream"; 19 | public const string Method_requestChannel = "requestChannel"; 20 | 21 | [System.Runtime.CompilerServices.CompilerGenerated] 22 | public interface IEchoService 23 | { 24 | Task FireAndForget(Google.Protobuf.WellKnownTypes.Value message, ReadOnlySequence metadata); 25 | 26 | Task RequestResponse(Google.Protobuf.WellKnownTypes.Value message, 27 | ReadOnlySequence metadata); 28 | 29 | IAsyncEnumerable RequestStream( 30 | Google.Protobuf.WellKnownTypes.Value message, ReadOnlySequence metadata); 31 | 32 | IAsyncEnumerable RequestChannel( 33 | IAsyncEnumerable messages, ReadOnlySequence metadata); 34 | } 35 | 36 | [System.Runtime.CompilerServices.CompilerGenerated] 37 | public class EchoServiceClient : RSocketService, IEchoService 38 | { 39 | public EchoServiceClient(RSocketClient client) : base(client) 40 | { 41 | } 42 | 43 | public Task FireAndForget(Google.Protobuf.WellKnownTypes.Value message, 44 | ReadOnlySequence metadata = default) => 45 | __RequestFireAndForget(message, Google.Protobuf.MessageExtensions.ToByteArray, metadata, 46 | service: EchoService.Service, method: EchoService.Method_fireAndForget); 47 | 48 | public Task RequestResponse( 49 | Google.Protobuf.WellKnownTypes.Value message, ReadOnlySequence metadata = default) => 50 | __RequestResponse(message, Google.Protobuf.MessageExtensions.ToByteArray, 51 | Google.Protobuf.WellKnownTypes.Value.Parser.ParseFrom, metadata, service: EchoService.Service, 52 | method: EchoService.Method_requestResponse); 53 | 54 | public IAsyncEnumerable RequestStream( 55 | Google.Protobuf.WellKnownTypes.Value message, ReadOnlySequence metadata = default) => 56 | __RequestStream(message, Google.Protobuf.MessageExtensions.ToByteArray, 57 | Google.Protobuf.WellKnownTypes.Value.Parser.ParseFrom, metadata, service: EchoService.Service, 58 | method: EchoService.Method_requestStream); 59 | 60 | public IAsyncEnumerable RequestChannel( 61 | IAsyncEnumerable messages, 62 | ReadOnlySequence metadata = default) => 63 | __RequestChannel(messages, Google.Protobuf.MessageExtensions.ToByteArray, 64 | Google.Protobuf.WellKnownTypes.Value.Parser.ParseFrom, metadata, service: EchoService.Service, 65 | method: EchoService.Method_requestChannel); 66 | 67 | 68 | #region Adapters to allow compilation in .NET Core 3.0 to call .NET Standard 2.0 Library using proper IAsyncEnumerable 69 | #if NETCOREAPP3_0 70 | private async new IAsyncEnumerable __RequestStream(TMessage message, Func sourcemapper, Func resultmapper, ReadOnlySequence metadata, ReadOnlySequence tracing = default, string service = default, string method = default) 71 | { await foreach (var _ in base.__RequestStream(message, sourcemapper, resultmapper, metadata, tracing, service, method)) { yield return _; } } 72 | 73 | private async IAsyncEnumerable __RequestChannel(IAsyncEnumerable messages, Func sourcemapper, Func resultmapper, ReadOnlySequence data = default, ReadOnlySequence metadata = default, ReadOnlySequence tracing = default, string service = default, string method = default) 74 | { await foreach (var _ in base.__RequestChannel(new AsyncEnumerable(messages), sourcemapper, resultmapper, data, metadata, tracing, service, method)) { yield return _; } } 75 | 76 | /// Interface forwarding from RSocket...IAsyncEnumerable to IAsyncEnumerable 77 | private class AsyncEnumerable : RSocket.Collections.Generic.IAsyncEnumerable 78 | { 79 | readonly IAsyncEnumerable Source; 80 | public AsyncEnumerable(IAsyncEnumerable source) { Source = source; } 81 | public RSocket.Collections.Generic.IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) => new Enumerator(Source.GetAsyncEnumerator(cancellationToken)); 82 | private class Enumerator : RSocket.Collections.Generic.IAsyncEnumerator 83 | { 84 | readonly IAsyncEnumerator Source; 85 | public Enumerator(IAsyncEnumerator source) { Source = source; } 86 | public T Current => Source.Current; 87 | public ValueTask DisposeAsync() => Source.DisposeAsync(); 88 | public ValueTask MoveNextAsync() => Source.MoveNextAsync(); 89 | } 90 | } 91 | 92 | #endif 93 | #endregion 94 | } 95 | 96 | public abstract class EchoServiceServer : IEchoService, IRSocketService 97 | { 98 | string IRSocketService.ServiceName => Service; 99 | IAsyncEnumerable> IRSocketService.Dispatch(ReadOnlySequence data, string method, ReadOnlySequence tracing, ReadOnlySequence metadata, IAsyncEnumerable> messages) 100 | => from result in Dispatch(this, data, method, tracing, metadata, from message in messages select message.ToArray()) select new ReadOnlySequence(result); 101 | 102 | public abstract Task FireAndForget(Google.Protobuf.WellKnownTypes.Value message, ReadOnlySequence metadata); 103 | public abstract Task RequestResponse(Google.Protobuf.WellKnownTypes.Value message, ReadOnlySequence metadata); 104 | public abstract IAsyncEnumerable RequestStream(Google.Protobuf.WellKnownTypes.Value message, ReadOnlySequence metadata); 105 | public abstract IAsyncEnumerable RequestChannel(IAsyncEnumerable messages, ReadOnlySequence metadata); 106 | 107 | public EchoServiceServer(RSocket.RSocket socket) 108 | { 109 | RSocketService.Register(socket, this); 110 | } 111 | 112 | static IAsyncEnumerable Dispatch(IEchoService service, ReadOnlySequence data, string method, in ReadOnlySequence tracing, in ReadOnlySequence metadata, IAsyncEnumerable messages) 113 | { 114 | switch (method) 115 | { 116 | case Method_fireAndForget: service.FireAndForget(Google.Protobuf.WellKnownTypes.Value.Parser.ParseFrom(data.ToArray()), metadata); return AsyncEnumerable.Empty(); 117 | case Method_requestResponse: return from result in service.RequestResponse(Google.Protobuf.WellKnownTypes.Value.Parser.ParseFrom(data.ToArray()), metadata).ToAsyncEnumerable() select Google.Protobuf.MessageExtensions.ToByteArray(result); 118 | case Method_requestStream: return from result in service.RequestStream(Google.Protobuf.WellKnownTypes.Value.Parser.ParseFrom(data.ToArray()), metadata) select Google.Protobuf.MessageExtensions.ToByteArray(result); 119 | case Method_requestChannel: return from result in service.RequestChannel(from message in messages select Google.Protobuf.WellKnownTypes.Value.Parser.ParseFrom(message), metadata) select Google.Protobuf.MessageExtensions.ToByteArray(result); 120 | default: throw new InvalidOperationException($"Unknown method {Service}.{method}."); 121 | } 122 | } 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /RSocket.Rpc.Sample/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using RSocket; 4 | using RSocket.Transports; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Threading; 8 | using Google.Protobuf.WellKnownTypes; 9 | using System.Buffers; 10 | 11 | namespace RSocketRPCSample 12 | { 13 | 14 | class Program 15 | { 16 | static async Task Main(string[] args) 17 | { 18 | var transport = new LoopbackTransport(); 19 | // new WebSocketTransport("ws://localhost:9092/")); 20 | // new SocketTransport("tcp://localhost:9091/") 21 | 22 | var client = new RSocketClient(transport); 23 | var service = new EchoService.EchoServiceClient(client); 24 | 25 | var server = new RSocketServer(transport.Beyond); 26 | var producer = new MyEchoServer(server); 27 | 28 | //TODO ASK: Should these be present in the generated methods to allow one-line construction? 29 | await server.ConnectAsync(); 30 | await client.ConnectAsync(); 31 | 32 | //await service.FireAndForget(Value.ForString("Fire and Forget Test Requrest")); 33 | //Console.WriteLine($"{nameof(service.FireAndForget)}() => void"); 34 | 35 | var responseresult = await service.RequestResponse(Value.ForString("Request Response Test Requrest")); 36 | Console.WriteLine($"{nameof(service.RequestResponse)}() => {responseresult.StringValue}"); 37 | 38 | 39 | var streamresults = await service.RequestStream(Value.ForString("Test Stream Request")) 40 | .ToListAsync(); //Collect all of the results. In C#8, this can be an async foreach - nice! 41 | streamresults.ForEach(result => Console.WriteLine($"{nameof(service.RequestStream)}() => {result.StringValue}")); 42 | 43 | 44 | var channelresults = await service.RequestChannel(( 45 | from value in Enumerable.Range(1, 3) select Value.ForString($"Test Channel Value {value}") 46 | ).ToAsyncEnumerable()).ToListAsync(); 47 | 48 | //Wait for a keypress to end session. 49 | { Console.WriteLine($"Press any key to continue..."); Console.ReadKey(); } 50 | } 51 | 52 | 53 | //Implementors have two choices, implement IEchoService directly or override the provided abstract base class - shown below: 54 | class MyEchoServer : EchoService.EchoServiceServer 55 | { 56 | public MyEchoServer(RSocket.RSocket socket) : base(socket) { } 57 | 58 | public async override Task FireAndForget(Value message, ReadOnlySequence metadata) 59 | { 60 | Console.WriteLine($"{nameof(EchoService.EchoServiceServer)}.{nameof(FireAndForget)}({message.StringValue}) request received."); 61 | await Task.CompletedTask; 62 | } 63 | 64 | public override Task RequestResponse(Value message, ReadOnlySequence metadata) 65 | { 66 | Console.WriteLine($"{nameof(EchoService.EchoServiceServer)}.{nameof(RequestResponse)}({message.StringValue}) request received."); 67 | return Task.FromResult(Value.ForString(message.StringValue + "and a Result")); 68 | } 69 | 70 | public override IAsyncEnumerable RequestStream(Value message, ReadOnlySequence metadata) 71 | { 72 | Console.WriteLine($"{nameof(EchoService.EchoServiceServer)}.{nameof(RequestStream)}({message.StringValue}) request received."); 73 | return new[] 74 | { 75 | Value.ForString(message.StringValue + " and Result 1"), 76 | Value.ForString(message.StringValue + " and Result 2"), 77 | Value.ForString(message.StringValue + " and Result 3"), 78 | }.ToAsyncEnumerable(); 79 | } 80 | 81 | public override IAsyncEnumerable RequestChannel(IAsyncEnumerable messages, ReadOnlySequence metadata) 82 | { 83 | Console.WriteLine($"{nameof(EchoService.EchoServiceServer)}.{nameof(RequestChannel)} request received."); 84 | return from message in messages 85 | select Value.ForString(message.StringValue + " REFLECTED!"); 86 | } 87 | } 88 | 89 | 90 | static async Task Main1(string[] args) 91 | { 92 | //Create a new Client. 93 | var client = new RSocketClient( 94 | new WebSocketTransport("ws://localhost:9092/")); 95 | // new SocketTransport("tcp://localhost:9091/")); 96 | 97 | //Bind a Service to this Client. 98 | var service = new EchoService.EchoServiceClient(client); 99 | 100 | //Connect to a Server and establish communications. 101 | await client.ConnectAsync(); 102 | 103 | //Make a service method call with no return to the server. 104 | await service.FireAndForget(Value.ForString($"{nameof(service.FireAndForget)}: Calling service...")); 105 | 106 | //Make a service method call returning a single value. 107 | var result = await service.RequestResponse(Value.ForString($"{nameof(service.RequestResponse)}: Calling service...")); 108 | Console.WriteLine($"Sample Result: {result.StringValue}"); 109 | 110 | 111 | //C# 8.0: Change the target language version to see IAsyncEnumerable iteration using built-in language constructs. (Project -> Properties -> Build -> Advanced -> Language Version) 112 | #if CSHARP8 113 | //Make a service call and asynchronously iterate the returning values. 114 | var stream = service.RequestStream(Value.ForString($"{nameof(service.RequestStream)}: Calling service...")); 115 | await foreach (var value in stream) 116 | { 117 | Console.WriteLine($"Stream Result: {value.StringValue}"); 118 | } 119 | Console.WriteLine("Stream Done"); 120 | 121 | 122 | //Make a service call taking asynchronous values and asynchronously iterate the returning values. 123 | var channel = service.RequestChannel(GenerateValues()); 124 | await foreach (var value in channel) 125 | { 126 | Console.WriteLine($"Channel Result: {value.StringValue}"); 127 | } 128 | Console.WriteLine("Channel Done"); 129 | 130 | #else 131 | //Make a service call and asynchronously iterate the returning values. 132 | var stream = service.RequestStream(Value.ForString($"{nameof(service.RequestStream)}: Calling service...")); 133 | await ForEach(stream, value => Console.WriteLine($"Stream Result: {value.StringValue}"), () => Console.WriteLine("Stream Done")); 134 | 135 | 136 | //Make a service call taking asynchronous values and asynchronously iterate the returning values. 137 | var channel = service.RequestChannel(GenerateValues()); 138 | await ForEach(channel, value => Console.WriteLine($"Channel Result: {value.StringValue}"), () => Console.WriteLine("Channel Done")); 139 | 140 | //Wait for a keypress to end session. 141 | { Console.WriteLine($"Press any key to continue..."); Console.ReadKey(); } 142 | #endif 143 | } 144 | 145 | 146 | //.Net Core 3.0: Change the Framework Version to include the genuine IAsyncEnumerable Interface. (Project -> Properties -> Application -> Target Framework) 147 | #if NETCOREAPP3_0 148 | 149 | //Use the state machine compiler to create an awaitable generator. 150 | static async IAsyncEnumerable GenerateValues() 151 | { 152 | yield return Value.ForString($"Initial Value"); 153 | await Task.Delay(100); 154 | foreach (var value in from value in new[] { 2, 3, 4 } select Value.ForString($"Value {value}")) 155 | { yield return value; } 156 | } 157 | #else 158 | 159 | //Use a helper class create an awaitable generator. 160 | static IAsyncEnumerable GenerateValues() 161 | { 162 | return new AsyncValues( 163 | Task.FromResult(from value in new[] { Value.ForString($"Initial Value"), } select value), 164 | Task.FromResult(from value in new[] { 2, 3, 4 } select Value.ForString($"Value {value}"))); 165 | } 166 | 167 | /// An asynchronously enumerable set of values. 168 | public class AsyncValues : IAsyncEnumerable 169 | { 170 | readonly IEnumerable>> From; 171 | 172 | public AsyncValues(params Task>[] from) { From = from; } 173 | public AsyncValues(IEnumerable>> from) { From = from; } 174 | 175 | public IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) => new Enumerator(From); 176 | 177 | private class Enumerator : IAsyncEnumerator 178 | { 179 | readonly IEnumerator>> under; 180 | IEnumerator into; 181 | public T Current => into.Current; 182 | 183 | public Enumerator(IEnumerable>> from) { under = from.GetEnumerator(); } 184 | 185 | public async ValueTask MoveNextAsync() 186 | { 187 | while (true) 188 | { 189 | if (into == default) 190 | { 191 | if (!under.MoveNext()) { return false; } 192 | into = (await under.Current).GetEnumerator(); 193 | } 194 | if (into.MoveNext()) { return true; } else { into = default; } 195 | } 196 | } 197 | 198 | public ValueTask DisposeAsync() => new ValueTask(); 199 | } 200 | } 201 | #endif 202 | 203 | /// Helper method to show Asynchronous Enumeration in C#7. This is not needed in C#8 204 | static public async Task ForEach(IAsyncEnumerable enumerable, Action action, Action final = default) 205 | { 206 | var enumerator = enumerable.GetAsyncEnumerator(); 207 | try 208 | { 209 | while (await enumerator.MoveNextAsync()) { action(enumerator.Current); } 210 | final?.Invoke(); 211 | } 212 | finally { await enumerator.DisposeAsync(); } 213 | } 214 | } 215 | } 216 | -------------------------------------------------------------------------------- /RSocket.Rpc.Sample/RSocket.Rpc.Sample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp2.1 6 | latest 7 | CSHARP8 8 | 9 | 10 | 11 | 12 | 13 | 14 | $(RestoreSources);../RSocket.Rpc.Tools/bin/$(Configuration);https://api.nuget.org/v3/index.json 15 | 16 | 17 | 18 | 19 | all 20 | runtime; build; native; contentfiles; analyzers 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | all 29 | runtime; build; native; contentfiles; analyzers 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /RSocket.Rpc.Sample/echo.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package io.rsocket.rpc.echo; 4 | 5 | import "google/protobuf/empty.proto"; 6 | import "google/protobuf/struct.proto"; 7 | import "rsocket/options.proto"; 8 | 9 | option java_package = "io.rsocket.rpc.echo"; 10 | option java_outer_classname = "EchoServiceProto"; 11 | option java_multiple_files = true; 12 | 13 | service EchoService { 14 | rpc fireAndForget (google.protobuf.Value) returns (google.protobuf.Empty) { 15 | option (io.rsocket.rpc.options) = { 16 | fire_and_forget: true 17 | }; 18 | } 19 | rpc requestResponse (google.protobuf.Value) returns (google.protobuf.Value); 20 | rpc requestStream (google.protobuf.Value) returns (stream google.protobuf.Value); 21 | rpc requestChannel(stream google.protobuf.Value) returns (stream google.protobuf.Value); 22 | } -------------------------------------------------------------------------------- /RSocket.Rpc.Tools.Tests/CSharpGeneratorTest.cs: -------------------------------------------------------------------------------- 1 | #region Copyright notice and license 2 | 3 | // Copyright 2018-2019 the original author or authors. 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #endregion 18 | 19 | using NUnit.Framework; 20 | 21 | namespace RSocket.Rpc.Tools.Tests 22 | { 23 | public class CSharpGeneratorTest : GeneratorTest 24 | { 25 | GeneratorServices _generator; 26 | 27 | [SetUp] 28 | public new void SetUp() 29 | { 30 | _generator = GeneratorServices.GetForLanguage("CSharp", _log); 31 | } 32 | 33 | [TestCase("foo.proto", "Foo.cs", "FooRSocketRpc.cs")] 34 | [TestCase("sub/foo.proto", "Foo.cs", "FooRSocketRpc.cs")] 35 | [TestCase("one_two.proto", "OneTwo.cs", "OneTwoRSocketRpc.cs")] 36 | [TestCase("__one_two!.proto", "OneTwo!.cs", "OneTwo!RSocketRpc.cs")] 37 | [TestCase("one(two).proto", "One(two).cs", "One(two)RSocketRpc.cs")] 38 | [TestCase("one_(two).proto", "One(two).cs", "One(two)RSocketRpc.cs")] 39 | [TestCase("one two.proto", "One two.cs", "One twoRSocketRpc.cs")] 40 | [TestCase("one_ two.proto", "One two.cs", "One twoRSocketRpc.cs")] 41 | [TestCase("one .proto", "One .cs", "One RSocketRpc.cs")] 42 | public void NameMangling(string proto, string expectCs, string expectRSocketRpcCs) 43 | { 44 | var poss = _generator.GetPossibleOutputs(Utils.MakeItem(proto, "RSocketRpcServices", "Both")); 45 | Assert.AreEqual(2, poss.Length); 46 | Assert.Contains(expectCs, poss); 47 | Assert.Contains(expectRSocketRpcCs, poss); 48 | } 49 | 50 | [Test] 51 | public void NoRSocketRpcOneOutput() 52 | { 53 | var poss = _generator.GetPossibleOutputs(Utils.MakeItem("foo.proto")); 54 | Assert.AreEqual(1, poss.Length); 55 | } 56 | 57 | [TestCase("none")] 58 | [TestCase("")] 59 | public void RSocketRpcNoneOneOutput(string services) 60 | { 61 | var item = Utils.MakeItem("foo.proto", "RSocketRpcServices", services); 62 | var poss = _generator.GetPossibleOutputs(item); 63 | Assert.AreEqual(1, poss.Length); 64 | } 65 | 66 | [TestCase("client")] 67 | [TestCase("server")] 68 | [TestCase("both")] 69 | public void RSocketRpcEnabledTwoOutputs(string services) 70 | { 71 | var item = Utils.MakeItem("foo.proto", "RSocketRpcServices", services); 72 | var poss = _generator.GetPossibleOutputs(item); 73 | Assert.AreEqual(2, poss.Length); 74 | } 75 | 76 | [Test] 77 | public void OutputDirMetadataRecognized() 78 | { 79 | var item = Utils.MakeItem("foo.proto", "OutputDir", "out"); 80 | var poss = _generator.GetPossibleOutputs(item); 81 | Assert.AreEqual(1, poss.Length); 82 | Assert.That(poss[0], Is.EqualTo("out/Foo.cs") | Is.EqualTo("out\\Foo.cs")); 83 | } 84 | }; 85 | } 86 | -------------------------------------------------------------------------------- /RSocket.Rpc.Tools.Tests/CppGeneratorTest.cs: -------------------------------------------------------------------------------- 1 | #region Copyright notice and license 2 | 3 | // Copyright 2018-2019 the original author or authors. 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #endregion 18 | 19 | using System.IO; 20 | using NUnit.Framework; 21 | 22 | namespace RSocket.Rpc.Tools.Tests 23 | { 24 | public class CppGeneratorTest : GeneratorTest 25 | { 26 | GeneratorServices _generator; 27 | 28 | [SetUp] 29 | public new void SetUp() 30 | { 31 | _generator = GeneratorServices.GetForLanguage("Cpp", _log); 32 | } 33 | 34 | [TestCase("foo.proto", "", "foo")] 35 | [TestCase("foo.proto", ".", "foo")] 36 | [TestCase("foo.proto", "./", "foo")] 37 | [TestCase("sub/foo.proto", "", "sub/foo")] 38 | [TestCase("root/sub/foo.proto", "root", "sub/foo")] 39 | [TestCase("root/sub/foo.proto", "root", "sub/foo")] 40 | [TestCase("/root/sub/foo.proto", "/root", "sub/foo")] 41 | public void RelativeDirectoryCompute(string proto, string root, string expectStem) 42 | { 43 | if (Path.DirectorySeparatorChar == '\\') 44 | expectStem = expectStem.Replace('/', '\\'); 45 | var poss = _generator.GetPossibleOutputs(Utils.MakeItem(proto, "ProtoRoot", root)); 46 | Assert.AreEqual(2, poss.Length); 47 | Assert.Contains(expectStem + ".pb.cc", poss); 48 | Assert.Contains(expectStem + ".pb.h", poss); 49 | } 50 | 51 | [Test] 52 | public void NoRSocketRpcTwoOutputs() 53 | { 54 | var poss = _generator.GetPossibleOutputs(Utils.MakeItem("foo.proto")); 55 | Assert.AreEqual(2, poss.Length); 56 | } 57 | 58 | [TestCase("false")] 59 | [TestCase("")] 60 | public void RSocketRpcDisabledTwoOutput(string services) 61 | { 62 | var item = Utils.MakeItem("foo.proto", "RSocketRpcServices", services); 63 | var poss = _generator.GetPossibleOutputs(item); 64 | Assert.AreEqual(2, poss.Length); 65 | } 66 | 67 | [TestCase("true")] 68 | public void RSocketRpcEnabledFourOutputs(string services) 69 | { 70 | var item = Utils.MakeItem("foo.proto", "RSocketRpcServices", services); 71 | var poss = _generator.GetPossibleOutputs(item); 72 | Assert.AreEqual(4, poss.Length); 73 | Assert.Contains("foo.pb.cc", poss); 74 | Assert.Contains("foo.pb.h", poss); 75 | Assert.Contains("foo_rsocket_rpc.pb.cc", poss); 76 | Assert.Contains("foo_rsocket_rpc.pb.h", poss); 77 | } 78 | 79 | [Test] 80 | public void OutputDirMetadataRecognized() 81 | { 82 | var item = Utils.MakeItem("foo.proto", "OutputDir", "out"); 83 | var poss = _generator.GetPossibleOutputs(item); 84 | Assert.AreEqual(2, poss.Length); 85 | Assert.That(Path.GetDirectoryName(poss[0]), Is.EqualTo("out")); 86 | } 87 | }; 88 | } 89 | -------------------------------------------------------------------------------- /RSocket.Rpc.Tools.Tests/DepFileUtilTest.cs: -------------------------------------------------------------------------------- 1 | #region Copyright notice and license 2 | 3 | // Copyright 2018-2019 the original author or authors. 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #endregion 18 | 19 | using System.IO; 20 | using Microsoft.Build.Framework; 21 | using Microsoft.Build.Utilities; 22 | using NUnit.Framework; 23 | 24 | namespace RSocket.Rpc.Tools.Tests 25 | { 26 | public class DepFileUtilTest 27 | { 28 | 29 | [Test] 30 | public void HashString64Hex_IsSane() 31 | { 32 | string hashFoo1 = DepFileUtil.HashString64Hex("foo"); 33 | string hashEmpty = DepFileUtil.HashString64Hex(""); 34 | string hashFoo2 = DepFileUtil.HashString64Hex("foo"); 35 | 36 | StringAssert.IsMatch("^[a-f0-9]{16}$", hashFoo1); 37 | Assert.AreEqual(hashFoo1, hashFoo2); 38 | Assert.AreNotEqual(hashFoo1, hashEmpty); 39 | } 40 | 41 | [Test] 42 | public void GetDepFilenameForProto_IsSane() 43 | { 44 | StringAssert.IsMatch(@"^out[\\/][a-f0-9]{16}_foo.protodep$", 45 | DepFileUtil.GetDepFilenameForProto("out", "foo.proto")); 46 | StringAssert.IsMatch(@"^[a-f0-9]{16}_foo.protodep$", 47 | DepFileUtil.GetDepFilenameForProto("", "foo.proto")); 48 | } 49 | 50 | [Test] 51 | public void GetDepFilenameForProto_HashesDir() 52 | { 53 | string PickHash(string fname) => 54 | DepFileUtil.GetDepFilenameForProto("", fname).Substring(0, 16); 55 | 56 | string same1 = PickHash("dir1/dir2/foo.proto"); 57 | string same2 = PickHash("dir1/dir2/proto.foo"); 58 | string same3 = PickHash("dir1/dir2/proto"); 59 | string same4 = PickHash("dir1/dir2/.proto"); 60 | string unsame1 = PickHash("dir2/foo.proto"); 61 | string unsame2 = PickHash("/dir2/foo.proto"); 62 | 63 | Assert.AreEqual(same1, same2); 64 | Assert.AreEqual(same1, same3); 65 | Assert.AreEqual(same1, same4); 66 | Assert.AreNotEqual(same1, unsame1); 67 | Assert.AreNotEqual(unsame1, unsame2); 68 | } 69 | 70 | ////////////////////////////////////////////////////////////////////////// 71 | // Full file reading tests 72 | 73 | // Generated by protoc on Windows. Slashes vary. 74 | const string depFile1 = 75 | @"C:\projects\foo\src\./foo.rsocket_rpc.pb.cc \ 76 | C:\projects\foo\src\./foo.rsocket_rpc.pb.h \ 77 | C:\projects\foo\src\./foo.pb.cc \ 78 | C:\projects\foo\src\./foo.pb.h: C:/usr/include/google/protobuf/wrappers.proto\ 79 | C:/usr/include/google/protobuf/any.proto\ 80 | C:/usr/include/google/protobuf/source_context.proto\ 81 | C:/usr/include/google/protobuf/type.proto\ 82 | foo.proto"; 83 | 84 | // This has a nasty output directory with a space. 85 | const string depFile2 = 86 | @"obj\Release x64\net45\/Foo.cs \ 87 | obj\Release x64\net45\/FooRSocketRpc.cs: C:/usr/include/google/protobuf/wrappers.proto\ 88 | C:/projects/foo/src//foo.proto"; 89 | 90 | [Test] 91 | public void ReadDependencyInput_FullFile1() 92 | { 93 | string[] deps = ReadDependencyInputFromFileData(depFile1, "foo.proto"); 94 | 95 | Assert.NotNull(deps); 96 | Assert.That(deps, Has.Length.InRange(4, 5)); // foo.proto may or may not be listed. 97 | Assert.That(deps, Has.One.EndsWith("wrappers.proto")); 98 | Assert.That(deps, Has.One.EndsWith("type.proto")); 99 | Assert.That(deps, Has.None.StartWith(" ")); 100 | } 101 | 102 | [Test] 103 | public void ReadDependencyInput_FullFile2() 104 | { 105 | string[] deps = ReadDependencyInputFromFileData(depFile2, "C:/projects/foo/src/foo.proto"); 106 | 107 | Assert.NotNull(deps); 108 | Assert.That(deps, Has.Length.InRange(1, 2)); 109 | Assert.That(deps, Has.One.EndsWith("wrappers.proto")); 110 | Assert.That(deps, Has.None.StartWith(" ")); 111 | } 112 | 113 | [Test] 114 | public void ReadDependencyInput_FullFileUnparsable() 115 | { 116 | string[] deps = ReadDependencyInputFromFileData("a:/foo.proto", "/foo.proto"); 117 | Assert.NotNull(deps); 118 | Assert.Zero(deps.Length); 119 | } 120 | 121 | // NB in our tests files are put into the temp directory but all have 122 | // different names. Avoid adding files with the same directory path and 123 | // name, or add reasonable handling for it if required. Tests are run in 124 | // parallel and will collide otherwise. 125 | private string[] ReadDependencyInputFromFileData(string fileData, string protoName) 126 | { 127 | string tempPath = Path.GetTempPath(); 128 | string tempfile = DepFileUtil.GetDepFilenameForProto(tempPath, protoName); 129 | try 130 | { 131 | File.WriteAllText(tempfile, fileData); 132 | var mockEng = new Moq.Mock(); 133 | var log = new TaskLoggingHelper(mockEng.Object, "x"); 134 | return DepFileUtil.ReadDependencyInputs(tempPath, protoName, log); 135 | } 136 | finally 137 | { 138 | try 139 | { 140 | File.Delete(tempfile); 141 | } 142 | catch { } 143 | } 144 | } 145 | }; 146 | } 147 | -------------------------------------------------------------------------------- /RSocket.Rpc.Tools.Tests/GeneratorTest.cs: -------------------------------------------------------------------------------- 1 | #region Copyright notice and license 2 | 3 | // Copyright 2018-2019 the original author or authors. 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #endregion 18 | 19 | using Microsoft.Build.Framework; 20 | using Microsoft.Build.Utilities; 21 | using Moq; 22 | using NUnit.Framework; 23 | 24 | namespace RSocket.Rpc.Tools.Tests 25 | { 26 | public class GeneratorTest 27 | { 28 | protected Mock _mockEngine; 29 | protected TaskLoggingHelper _log; 30 | 31 | [SetUp] 32 | public void SetUp() 33 | { 34 | _mockEngine = new Mock(); 35 | _log = new TaskLoggingHelper(_mockEngine.Object, "dummy"); 36 | } 37 | 38 | [TestCase("csharp")] 39 | [TestCase("CSharp")] 40 | [TestCase("cpp")] 41 | public void ValidLanguages(string lang) 42 | { 43 | Assert.IsNotNull(GeneratorServices.GetForLanguage(lang, _log)); 44 | _mockEngine.Verify(me => me.LogErrorEvent(It.IsAny()), Times.Never); 45 | } 46 | 47 | [TestCase("")] 48 | [TestCase("COBOL")] 49 | public void InvalidLanguages(string lang) 50 | { 51 | Assert.IsNull(GeneratorServices.GetForLanguage(lang, _log)); 52 | _mockEngine.Verify(me => me.LogErrorEvent(It.IsAny()), Times.Once); 53 | } 54 | }; 55 | } 56 | -------------------------------------------------------------------------------- /RSocket.Rpc.Tools.Tests/ProtoCompileBasicTest.cs: -------------------------------------------------------------------------------- 1 | #region Copyright notice and license 2 | 3 | // Copyright 2018-2019 the original author or authors. 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #endregion 18 | 19 | using System.Reflection; // UWYU: Object.GetType() extension. 20 | using Microsoft.Build.Framework; 21 | using Moq; 22 | using NUnit.Framework; 23 | 24 | namespace RSocket.Rpc.Tools.Tests 25 | { 26 | public class ProtoCompileBasicTest 27 | { 28 | // Mock task class that stops right before invoking protoc. 29 | public class ProtoCompileTestable : ProtoCompile 30 | { 31 | public string LastPathToTool { get; private set; } 32 | public string[] LastResponseFile { get; private set; } 33 | 34 | protected override int ExecuteTool(string pathToTool, 35 | string response, 36 | string commandLine) 37 | { 38 | // We should never be using command line commands. 39 | Assert.That(commandLine, Is.Null | Is.Empty); 40 | 41 | // Must receive a path to tool 42 | Assert.That(pathToTool, Is.Not.Null & Is.Not.Empty); 43 | Assert.That(response, Is.Not.Null & Does.EndWith("\n")); 44 | 45 | LastPathToTool = pathToTool; 46 | LastResponseFile = response.Remove(response.Length - 1).Split('\n'); 47 | 48 | // Do not run the tool, but pretend it ran successfully. 49 | return 0; 50 | } 51 | }; 52 | 53 | protected Mock _mockEngine; 54 | protected ProtoCompileTestable _task; 55 | 56 | [SetUp] 57 | public void SetUp() 58 | { 59 | _mockEngine = new Mock(); 60 | _task = new ProtoCompileTestable { 61 | BuildEngine = _mockEngine.Object 62 | }; 63 | } 64 | 65 | [TestCase("ProtoBuf")] 66 | [TestCase("Generator")] 67 | [TestCase("OutputDir")] 68 | [Description("We trust MSBuild to initialize these properties.")] 69 | public void RequiredAttributePresentOnProperty(string prop) 70 | { 71 | var pinfo = _task.GetType()?.GetProperty(prop); 72 | Assert.NotNull(pinfo); 73 | Assert.That(pinfo, Has.Attribute()); 74 | } 75 | }; 76 | } 77 | -------------------------------------------------------------------------------- /RSocket.Rpc.Tools.Tests/ProtoCompileCommandLineGeneratorTest.cs: -------------------------------------------------------------------------------- 1 | #region Copyright notice and license 2 | 3 | // Copyright 2018-2019 the original author or authors. 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #endregion 18 | 19 | using System.IO; 20 | using Microsoft.Build.Framework; 21 | using Moq; 22 | using NUnit.Framework; 23 | 24 | namespace RSocket.Rpc.Tools.Tests 25 | { 26 | public class ProtoCompileCommandLineGeneratorTest : ProtoCompileBasicTest 27 | { 28 | [SetUp] 29 | public new void SetUp() 30 | { 31 | _task.Generator = "csharp"; 32 | _task.OutputDir = "outdir"; 33 | _task.ProtoBuf = Utils.MakeSimpleItems("a.proto"); 34 | } 35 | 36 | void ExecuteExpectSuccess() 37 | { 38 | _mockEngine 39 | .Setup(me => me.LogErrorEvent(It.IsAny())) 40 | .Callback((BuildErrorEventArgs e) => 41 | Assert.Fail($"Error logged by build engine:\n{e.Message}")); 42 | bool result = _task.Execute(); 43 | Assert.IsTrue(result); 44 | } 45 | 46 | [Test] 47 | public void MinimalCompile() 48 | { 49 | ExecuteExpectSuccess(); 50 | Assert.That(_task.LastPathToTool, Does.Match(@"protoc(.exe)?$")); 51 | Assert.That(_task.LastResponseFile, Is.EqualTo(new[] { 52 | "--csharp_out=outdir", "a.proto" })); 53 | } 54 | 55 | [Test] 56 | public void CompileTwoFiles() 57 | { 58 | _task.ProtoBuf = Utils.MakeSimpleItems("a.proto", "foo/b.proto"); 59 | ExecuteExpectSuccess(); 60 | Assert.That(_task.LastResponseFile, Is.EqualTo(new[] { 61 | "--csharp_out=outdir", "a.proto", "foo/b.proto" })); 62 | } 63 | 64 | [Test] 65 | public void CompileWithProtoPaths() 66 | { 67 | _task.ProtoPath = new[] { "/path1", "/path2" }; 68 | ExecuteExpectSuccess(); 69 | Assert.That(_task.LastResponseFile, Is.EqualTo(new[] { 70 | "--csharp_out=outdir", "--proto_path=/path1", 71 | "--proto_path=/path2", "a.proto" })); 72 | } 73 | 74 | [TestCase("Cpp")] 75 | [TestCase("CSharp")] 76 | [TestCase("Java")] 77 | [TestCase("Javanano")] 78 | [TestCase("Js")] 79 | [TestCase("Objc")] 80 | [TestCase("Php")] 81 | [TestCase("Python")] 82 | [TestCase("Ruby")] 83 | public void CompileWithOptions(string gen) 84 | { 85 | _task.Generator = gen; 86 | _task.OutputOptions = new[] { "foo", "bar" }; 87 | ExecuteExpectSuccess(); 88 | gen = gen.ToLowerInvariant(); 89 | Assert.That(_task.LastResponseFile, Is.EqualTo(new[] { 90 | $"--{gen}_out=outdir", $"--{gen}_opt=foo,bar", "a.proto" })); 91 | } 92 | 93 | [Test] 94 | public void OutputDependencyFile() 95 | { 96 | _task.DependencyOut = "foo/my.protodep"; 97 | // Task fails trying to read the non-generated file; we ignore that. 98 | _task.Execute(); 99 | Assert.That(_task.LastResponseFile, 100 | Does.Contain("--dependency_out=foo/my.protodep")); 101 | } 102 | 103 | [Test] 104 | public void OutputDependencyWithProtoDepDir() 105 | { 106 | _task.ProtoDepDir = "foo"; 107 | // Task fails trying to read the non-generated file; we ignore that. 108 | _task.Execute(); 109 | Assert.That(_task.LastResponseFile, 110 | Has.One.Match(@"^--dependency_out=foo[/\\].+_a.protodep$")); 111 | } 112 | 113 | [Test] 114 | public void GenerateRSocketRpc() 115 | { 116 | _task.RSocketRpcPluginExe = "/foo/rsocket_rpc_gen"; 117 | ExecuteExpectSuccess(); 118 | Assert.That(_task.LastResponseFile, Is.SupersetOf(new[] { 119 | "--csharp_out=outdir", "--rsocket_rpc_out=outdir", 120 | "--plugin=protoc-gen-rsocket_rpc=/foo/rsocket_rpc_gen" })); 121 | } 122 | 123 | [Test] 124 | public void GenerateRSocketRpcWithOutDir() 125 | { 126 | _task.RSocketRpcPluginExe = "/foo/rsocket_rpc_gen"; 127 | _task.RSocketRpcOutputDir = "gen-out"; 128 | ExecuteExpectSuccess(); 129 | Assert.That(_task.LastResponseFile, Is.SupersetOf(new[] { 130 | "--csharp_out=outdir", "--rsocket_rpc_out=gen-out" })); 131 | } 132 | 133 | [Test] 134 | public void GenerateRSocketRpcWithOptions() 135 | { 136 | _task.RSocketRpcPluginExe = "/foo/rsocket_rpc_gen"; 137 | _task.RSocketRpcOutputOptions = new[] { "baz", "quux" }; 138 | ExecuteExpectSuccess(); 139 | Assert.That(_task.LastResponseFile, 140 | Does.Contain("--rsocket_rpc_opt=baz,quux")); 141 | } 142 | 143 | [Test] 144 | public void DirectoryArgumentsSlashTrimmed() 145 | { 146 | _task.RSocketRpcPluginExe = "/foo/rsocket_rpc_gen"; 147 | _task.RSocketRpcOutputDir = "gen-out/"; 148 | _task.OutputDir = "outdir/"; 149 | _task.ProtoPath = new[] { "/path1/", "/path2/" }; 150 | ExecuteExpectSuccess(); 151 | Assert.That(_task.LastResponseFile, Is.SupersetOf(new[] { 152 | "--proto_path=/path1", "--proto_path=/path2", 153 | "--csharp_out=outdir", "--rsocket_rpc_out=gen-out" })); 154 | } 155 | 156 | [TestCase(".", ".")] 157 | [TestCase("/", "/")] 158 | [TestCase("//", "/")] 159 | [TestCase("/foo/", "/foo")] 160 | [TestCase("/foo", "/foo")] 161 | [TestCase("foo/", "foo")] 162 | [TestCase("foo//", "foo")] 163 | [TestCase("foo/\\", "foo")] 164 | [TestCase("foo\\/", "foo")] 165 | [TestCase("C:\\foo", "C:\\foo")] 166 | [TestCase("C:", "C:")] 167 | [TestCase("C:\\", "C:\\")] 168 | [TestCase("C:\\\\", "C:\\")] 169 | public void DirectorySlashTrimmingCases(string given, string expect) 170 | { 171 | if (Path.DirectorySeparatorChar == '/') 172 | expect = expect.Replace('\\', '/'); 173 | _task.OutputDir = given; 174 | ExecuteExpectSuccess(); 175 | Assert.That(_task.LastResponseFile, 176 | Does.Contain("--csharp_out=" + expect)); 177 | } 178 | }; 179 | } 180 | -------------------------------------------------------------------------------- /RSocket.Rpc.Tools.Tests/ProtoCompileCommandLinePrinterTest.cs: -------------------------------------------------------------------------------- 1 | #region Copyright notice and license 2 | 3 | // Copyright 2018-2019 the original author or authors. 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #endregion 18 | 19 | using Microsoft.Build.Framework; 20 | using Moq; 21 | using NUnit.Framework; 22 | 23 | namespace RSocket.Rpc.Tools.Tests 24 | { 25 | public class ProtoCompileCommandLinePrinterTest : ProtoCompileBasicTest 26 | { 27 | [SetUp] 28 | public new void SetUp() 29 | { 30 | _task.Generator = "csharp"; 31 | _task.OutputDir = "outdir"; 32 | _task.ProtoBuf = Utils.MakeSimpleItems("a.proto"); 33 | 34 | _mockEngine 35 | .Setup(me => me.LogMessageEvent(It.IsAny())) 36 | .Callback((BuildMessageEventArgs e) => 37 | Assert.Fail($"Error logged by build engine:\n{e.Message}")) 38 | .Verifiable("Command line was not output by the task."); 39 | } 40 | 41 | void ExecuteExpectSuccess() 42 | { 43 | _mockEngine 44 | .Setup(me => me.LogErrorEvent(It.IsAny())) 45 | .Callback((BuildErrorEventArgs e) => 46 | Assert.Fail($"Error logged by build engine:\n{e.Message}")); 47 | bool result = _task.Execute(); 48 | Assert.IsTrue(result); 49 | } 50 | }; 51 | } 52 | -------------------------------------------------------------------------------- /RSocket.Rpc.Tools.Tests/ProtoToolsPlatformTaskTest.cs: -------------------------------------------------------------------------------- 1 | #region Copyright notice and license 2 | 3 | // Copyright 2018-2019 the original author or authors. 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #endregion 18 | 19 | using System.Runtime.InteropServices; 20 | using Microsoft.Build.Framework; 21 | using Moq; 22 | using NUnit.Framework; 23 | 24 | namespace RSocket.Rpc.Tools.Tests 25 | { 26 | public class ProtoToolsPlatformTaskTest 27 | { 28 | ProtoToolsPlatform _task; 29 | int _cpuMatched, _osMatched; 30 | 31 | [OneTimeSetUp] 32 | public void SetUp() 33 | { 34 | var mockEng = new Mock(); 35 | _task = new ProtoToolsPlatform() { BuildEngine = mockEng.Object }; 36 | _task.Execute(); 37 | } 38 | 39 | [OneTimeTearDown] 40 | public void TearDown() 41 | { 42 | Assert.AreEqual(1, _cpuMatched, "CPU type detection failed"); 43 | Assert.AreEqual(1, _osMatched, "OS detection failed"); 44 | } 45 | 46 | // PlatformAttribute not yet available in NUnit, coming soon: 47 | // https://github.com/nunit/nunit/pull/3003. 48 | // Use same test case names as under the full framework. 49 | [Test] 50 | public void CpuIsX86() 51 | { 52 | if (RuntimeInformation.OSArchitecture == Architecture.X86) 53 | { 54 | _cpuMatched++; 55 | Assert.AreEqual("x86", _task.Cpu); 56 | } 57 | } 58 | 59 | [Test] 60 | public void CpuIsX64() 61 | { 62 | if (RuntimeInformation.OSArchitecture == Architecture.X64) 63 | { 64 | _cpuMatched++; 65 | Assert.AreEqual("x64", _task.Cpu); 66 | } 67 | } 68 | 69 | [Test] 70 | public void OsIsWindows() 71 | { 72 | if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) 73 | { 74 | _osMatched++; 75 | Assert.AreEqual("windows", _task.Os); 76 | } 77 | } 78 | 79 | [Test] 80 | public void OsIsLinux() 81 | { 82 | if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) 83 | { 84 | _osMatched++; 85 | Assert.AreEqual("linux", _task.Os); 86 | } 87 | } 88 | 89 | [Test] 90 | public void OsIsMacOsX() 91 | { 92 | if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) 93 | { 94 | _osMatched++; 95 | Assert.AreEqual("macosx", _task.Os); 96 | } 97 | } 98 | }; 99 | } 100 | -------------------------------------------------------------------------------- /RSocket.Rpc.Tools.Tests/RSocket.Rpc.Tools.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp2.1 5 | Exe 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /RSocket.Rpc.Tools.Tests/Utils.cs: -------------------------------------------------------------------------------- 1 | #region Copyright notice and license 2 | 3 | // Copyright 2018-2019 the original author or authors. 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #endregion 18 | 19 | using System.Linq; 20 | using Microsoft.Build.Framework; 21 | using Microsoft.Build.Utilities; 22 | 23 | namespace RSocket.Rpc.Tools.Tests 24 | { 25 | static class Utils 26 | { 27 | // Build an item with a name from args[0] and metadata key-value pairs 28 | // from the rest of args, interleaved. 29 | // This does not do any checking, and expects an odd number of args. 30 | public static ITaskItem MakeItem(params string[] args) 31 | { 32 | var item = new TaskItem(args[0]); 33 | for (int i = 1; i < args.Length; i += 2) 34 | { 35 | item.SetMetadata(args[i], args[i + 1]); 36 | } 37 | return item; 38 | } 39 | 40 | // Return an array of items from given itemspecs. 41 | public static ITaskItem[] MakeSimpleItems(params string[] specs) 42 | { 43 | return specs.Select(s => new TaskItem(s)).ToArray(); 44 | } 45 | }; 46 | } 47 | -------------------------------------------------------------------------------- /RSocket.Rpc.Tools/Common.cs: -------------------------------------------------------------------------------- 1 | #region Copyright notice and license 2 | 3 | // Copyright 2018-2019 the original author or authors. 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #endregion 18 | 19 | using System; 20 | using System.IO; 21 | using System.Runtime.CompilerServices; 22 | using System.Runtime.InteropServices; 23 | using System.Security; 24 | 25 | [assembly: InternalsVisibleTo("RSocket.Rpc.Tools.Tests")] 26 | 27 | namespace RSocket.Rpc.Tools 28 | { 29 | // Metadata names (MSBuild item attributes) that we refer to often. 30 | static class Metadata 31 | { 32 | // On output dependency lists. 33 | public static string Source = "Source"; 34 | // On ProtoBuf items. 35 | public static string ProtoRoot = "ProtoRoot"; 36 | public static string OutputDir = "OutputDir"; 37 | public static string RSocketRpcServices = "RSocketRpcServices"; 38 | public static string RSocketRpcOutputDir = "RSocketRpcOutputDir"; 39 | }; 40 | 41 | // A few flags used to control the behavior under various platforms. 42 | internal static class Platform 43 | { 44 | public enum OsKind { Unknown, Windows, Linux, MacOsX }; 45 | public static readonly OsKind Os; 46 | 47 | public enum CpuKind { Unknown, X86, X64 }; 48 | public static readonly CpuKind Cpu; 49 | 50 | // This is not necessarily true, but good enough. BCL lacks a per-FS 51 | // API to determine file case sensitivity. 52 | public static bool IsFsCaseInsensitive => Os == OsKind.Windows; 53 | public static bool IsWindows => Os == OsKind.Windows; 54 | 55 | static Platform() 56 | { 57 | Os = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? OsKind.Windows 58 | : RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? OsKind.Linux 59 | : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? OsKind.MacOsX 60 | : OsKind.Unknown; 61 | 62 | switch (RuntimeInformation.OSArchitecture) 63 | { 64 | case Architecture.X86: Cpu = CpuKind.X86; break; 65 | case Architecture.X64: Cpu = CpuKind.X64; break; 66 | // We do not have build tools for other architectures. 67 | default: Cpu = CpuKind.Unknown; break; 68 | } 69 | } 70 | }; 71 | 72 | // Exception handling helpers. 73 | static class Exceptions 74 | { 75 | // Returns true iff the exception indicates an error from an I/O call. See 76 | // https://github.com/Microsoft/msbuild/blob/v15.4.8.50001/src/Shared/ExceptionHandling.cs#L101 77 | static public bool IsIoRelated(Exception ex) => 78 | ex is IOException || 79 | (ex is ArgumentException && !(ex is ArgumentNullException)) || 80 | ex is SecurityException || 81 | ex is UnauthorizedAccessException || 82 | ex is NotSupportedException; 83 | }; 84 | 85 | // String helpers. 86 | static class Strings 87 | { 88 | // Compare string to argument using OrdinalIgnoreCase comparison. 89 | public static bool EqualNoCase(this string a, string b) => 90 | string.Equals(a, b, StringComparison.OrdinalIgnoreCase); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /RSocket.Rpc.Tools/GeneratorServices.cs: -------------------------------------------------------------------------------- 1 | #region Copyright notice and license 2 | 3 | // Copyright 2018-2019 the original author or authors. 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #endregion 18 | 19 | using System; 20 | using System.IO; 21 | using System.Text; 22 | using Microsoft.Build.Framework; 23 | using Microsoft.Build.Utilities; 24 | 25 | namespace RSocket.Rpc.Tools 26 | { 27 | // Abstract class for language-specific analysis behavior, such 28 | // as guessing the generated files the same way protoc does. 29 | internal abstract class GeneratorServices 30 | { 31 | protected readonly TaskLoggingHelper Log; 32 | protected GeneratorServices(TaskLoggingHelper log) { Log = log; } 33 | 34 | // Obtain a service for the given language (csharp, cpp). 35 | public static GeneratorServices GetForLanguage(string lang, TaskLoggingHelper log) 36 | { 37 | if (lang.EqualNoCase("csharp")) { return new CSharpGeneratorServices(log); } 38 | if (lang.EqualNoCase("cpp")) { return new CppGeneratorServices(log); } 39 | 40 | log.LogError("Invalid value '{0}' for task property 'Generator'. " + 41 | "Supported generator languages: CSharp, Cpp.", lang); 42 | return null; 43 | } 44 | 45 | // Guess whether item's metadata suggests RSocket RPC stub generation. 46 | // When "RSocketRpcServices" is not defined, assume RSocket RPC is not used. 47 | // When defined, C# uses "none" to skip RSocket RPC, C++ uses "false", so 48 | // recognize both. Since the value is tightly coupled to the scripts, 49 | // we do not try to validate the value; scripts take care of that. 50 | // It is safe to assume that RSocket RPC is requested for any other value. 51 | protected bool RSocketRpcOutputPossible(ITaskItem proto) 52 | { 53 | string gsm = proto.GetMetadata(Metadata.RSocketRpcServices); 54 | return !gsm.EqualNoCase("") && !gsm.EqualNoCase("none") 55 | && !gsm.EqualNoCase("false"); 56 | } 57 | 58 | public abstract string[] GetPossibleOutputs(ITaskItem proto); 59 | }; 60 | 61 | // C# generator services. 62 | internal class CSharpGeneratorServices : GeneratorServices 63 | { 64 | public CSharpGeneratorServices(TaskLoggingHelper log) : base(log) { } 65 | 66 | public override string[] GetPossibleOutputs(ITaskItem protoItem) 67 | { 68 | bool doRSocketRpc = RSocketRpcOutputPossible(protoItem); 69 | string filename = LowerUnderscoreToUpperCamel( 70 | Path.GetFileNameWithoutExtension(protoItem.ItemSpec)); 71 | 72 | var outputs = new string[doRSocketRpc ? 2 : 1]; 73 | string outdir = protoItem.GetMetadata(Metadata.OutputDir); 74 | string fileStem = Path.Combine(outdir, filename); 75 | outputs[0] = fileStem + ".cs"; 76 | if (doRSocketRpc) 77 | { 78 | // Override outdir if kRSocketRpcOutputDir present, default to proto output. 79 | outdir = protoItem.GetMetadata(Metadata.RSocketRpcOutputDir); 80 | if (outdir != "") 81 | { 82 | fileStem = Path.Combine(outdir, filename); 83 | } 84 | outputs[1] = fileStem + "RSocketRpc.cs"; 85 | } 86 | return outputs; 87 | } 88 | 89 | string LowerUnderscoreToUpperCamel(string str) 90 | { 91 | // See src/compiler/generator_helpers.h:118 92 | var result = new StringBuilder(str.Length, str.Length); 93 | bool cap = true; 94 | foreach (char c in str) 95 | { 96 | if (c == '_') 97 | { 98 | cap = true; 99 | } 100 | else if (cap) 101 | { 102 | result.Append(char.ToUpperInvariant(c)); 103 | cap = false; 104 | } 105 | else 106 | { 107 | result.Append(c); 108 | } 109 | } 110 | return result.ToString(); 111 | } 112 | }; 113 | 114 | // C++ generator services. 115 | internal class CppGeneratorServices : GeneratorServices 116 | { 117 | public CppGeneratorServices(TaskLoggingHelper log) : base(log) { } 118 | 119 | public override string[] GetPossibleOutputs(ITaskItem protoItem) 120 | { 121 | bool doRSocketRpc = RSocketRpcOutputPossible(protoItem); 122 | string root = protoItem.GetMetadata(Metadata.ProtoRoot); 123 | string proto = protoItem.ItemSpec; 124 | string filename = Path.GetFileNameWithoutExtension(proto); 125 | // E. g., ("foo/", "foo/bar/x.proto") => "bar" 126 | string relative = GetRelativeDir(root, proto); 127 | 128 | var outputs = new string[doRSocketRpc ? 4 : 2]; 129 | string outdir = protoItem.GetMetadata(Metadata.OutputDir); 130 | string fileStem = Path.Combine(outdir, relative, filename); 131 | outputs[0] = fileStem + ".pb.cc"; 132 | outputs[1] = fileStem + ".pb.h"; 133 | if (doRSocketRpc) 134 | { 135 | // Override outdir if kRSocketRpcOutputDir present, default to proto output. 136 | outdir = protoItem.GetMetadata(Metadata.RSocketRpcOutputDir); 137 | if (outdir != "") 138 | { 139 | fileStem = Path.Combine(outdir, relative, filename); 140 | } 141 | outputs[2] = fileStem + "_rsocket_rpc.pb.cc"; 142 | outputs[3] = fileStem + "_rsocket_rpc.pb.h"; 143 | } 144 | return outputs; 145 | } 146 | 147 | // Calculate part of proto path relative to root. Protoc is very picky 148 | // about them matching exactly, so can be we. Expect root be exact prefix 149 | // to proto, minus some slash normalization. 150 | string GetRelativeDir(string root, string proto) 151 | { 152 | string protoDir = Path.GetDirectoryName(proto); 153 | string rootDir = EndWithSlash(Path.GetDirectoryName(EndWithSlash(root))); 154 | if (rootDir == s_dotSlash) 155 | { 156 | // Special case, otherwise we can return "./" instead of "" below! 157 | return protoDir; 158 | } 159 | if (Platform.IsFsCaseInsensitive) 160 | { 161 | protoDir = protoDir.ToLowerInvariant(); 162 | rootDir = rootDir.ToLowerInvariant(); 163 | } 164 | protoDir = EndWithSlash(protoDir); 165 | if (!protoDir.StartsWith(rootDir)) 166 | { 167 | Log.LogWarning("ProtoBuf item '{0}' has the ProtoRoot metadata '{1}' " + 168 | "which is not prefix to its path. Cannot compute relative path.", 169 | proto, root); 170 | return ""; 171 | } 172 | return protoDir.Substring(rootDir.Length); 173 | } 174 | 175 | // './' or '.\', normalized per system. 176 | static string s_dotSlash = "." + Path.DirectorySeparatorChar; 177 | 178 | static string EndWithSlash(string str) 179 | { 180 | if (str == "") 181 | { 182 | return s_dotSlash; 183 | } 184 | else if (str[str.Length - 1] != '\\' && str[str.Length - 1] != '/') 185 | { 186 | return str + Path.DirectorySeparatorChar; 187 | } 188 | else 189 | { 190 | return str; 191 | } 192 | } 193 | }; 194 | } 195 | -------------------------------------------------------------------------------- /RSocket.Rpc.Tools/ProtoCompilerOutputs.cs: -------------------------------------------------------------------------------- 1 | #region Copyright notice and license 2 | 3 | // Copyright 2018-2019 the original author or authors. 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #endregion 18 | 19 | using System.Collections.Generic; 20 | using Microsoft.Build.Framework; 21 | using Microsoft.Build.Utilities; 22 | 23 | namespace RSocket.Rpc.Tools 24 | { 25 | public class ProtoCompilerOutputs : Task 26 | { 27 | /// 28 | /// Code generator. Currently supported are "csharp", "cpp". 29 | /// 30 | [Required] 31 | public string Generator { get; set; } 32 | 33 | /// 34 | /// All Proto files in the project. The task computes possible outputs 35 | /// from these proto files, and returns them in the PossibleOutputs list. 36 | /// Not all of these might be actually produced by protoc; this is dealt 37 | /// with later in the ProtoCompile task which returns the list of 38 | /// files actually produced by the compiler. 39 | /// 40 | [Required] 41 | public ITaskItem[] ProtoBuf { get; set; } 42 | 43 | /// 44 | /// Output items per each potential output. We do not look at existing 45 | /// cached dependency even if they exist, since file may be refactored, 46 | /// affecting whether or not RSocket RPC code file is generated from a given proto. 47 | /// Instead, all potentially possible generated sources are collected. 48 | /// It is a wise idea to generate empty files later for those potentials 49 | /// that are not actually created by protoc, so the dependency checks 50 | /// result in a minimal recompilation. The Protoc task can output the 51 | /// list of files it actually produces, given right combination of its 52 | /// properties. 53 | /// Output items will have the Source metadata set on them: 54 | /// 55 | /// 56 | [Output] 57 | public ITaskItem[] PossibleOutputs { get; private set; } 58 | 59 | public override bool Execute() 60 | { 61 | var generator = GeneratorServices.GetForLanguage(Generator, Log); 62 | if (generator == null) 63 | { 64 | // Error already logged, just return. 65 | return false; 66 | } 67 | 68 | // Get language-specific possible output. The generator expects certain 69 | // metadata be set on the proto item. 70 | var possible = new List(); 71 | foreach (var proto in ProtoBuf) 72 | { 73 | var outputs = generator.GetPossibleOutputs(proto); 74 | foreach (string output in outputs) 75 | { 76 | var ti = new TaskItem(output); 77 | ti.SetMetadata(Metadata.Source, proto.ItemSpec); 78 | possible.Add(ti); 79 | } 80 | } 81 | PossibleOutputs = possible.ToArray(); 82 | 83 | return !Log.HasLoggedErrors; 84 | } 85 | }; 86 | } 87 | -------------------------------------------------------------------------------- /RSocket.Rpc.Tools/ProtoReadDependencies.cs: -------------------------------------------------------------------------------- 1 | #region Copyright notice and license 2 | 3 | // Copyright 2018-2019 the original author or authors. 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #endregion 18 | 19 | using System.Collections.Generic; 20 | using Microsoft.Build.Framework; 21 | using Microsoft.Build.Utilities; 22 | 23 | namespace RSocket.Rpc.Tools 24 | { 25 | public class ProtoReadDependencies : Task 26 | { 27 | /// 28 | /// The collection is used to collect possible additional dependencies 29 | /// of proto files cached under ProtoDepDir. 30 | /// 31 | [Required] 32 | public ITaskItem[] ProtoBuf { get; set; } 33 | 34 | /// 35 | /// Directory where protoc dependency files are cached. 36 | /// 37 | [Required] 38 | public string ProtoDepDir { get; set; } 39 | 40 | /// 41 | /// Additional items that a proto file depends on. This list may include 42 | /// extra dependencies; we do our best to include as few extra positives 43 | /// as reasonable to avoid missing any. The collection item is the 44 | /// dependency, and its Source metadatum is the dependent proto file, like 45 | /// 47 | /// 48 | [Output] 49 | public ITaskItem[] Dependencies { get; private set; } 50 | 51 | public override bool Execute() 52 | { 53 | // Read dependency files, where available. There might be none, 54 | // just use a best effort. 55 | if (ProtoDepDir != null) 56 | { 57 | var dependencies = new List(); 58 | foreach (var proto in ProtoBuf) 59 | { 60 | string[] deps = DepFileUtil.ReadDependencyInputs(ProtoDepDir, proto.ItemSpec, Log); 61 | foreach (string dep in deps) 62 | { 63 | var ti = new TaskItem(dep); 64 | ti.SetMetadata(Metadata.Source, proto.ItemSpec); 65 | dependencies.Add(ti); 66 | } 67 | } 68 | Dependencies = dependencies.ToArray(); 69 | } 70 | else 71 | { 72 | Dependencies = new ITaskItem[0]; 73 | } 74 | 75 | return !Log.HasLoggedErrors; 76 | } 77 | }; 78 | } 79 | -------------------------------------------------------------------------------- /RSocket.Rpc.Tools/ProtoToolsPlatform.cs: -------------------------------------------------------------------------------- 1 | #region Copyright notice and license 2 | 3 | // Copyright 2018-2019 the original author or authors. 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #endregion 18 | 19 | using Microsoft.Build.Framework; 20 | using Microsoft.Build.Utilities; 21 | 22 | namespace RSocket.Rpc.Tools 23 | { 24 | /// 25 | /// A helper task to resolve actual OS type and bitness. 26 | /// 27 | public class ProtoToolsPlatform : Task 28 | { 29 | /// 30 | /// Return one of 'linux', 'macosx' or 'windows'. 31 | /// If the OS is unknown, the property is not set. 32 | /// 33 | [Output] 34 | public string Os { get; set; } 35 | 36 | /// 37 | /// Return one of 'x64' or 'x86'. 38 | /// If the CPU is unknown, the property is not set. 39 | /// 40 | [Output] 41 | public string Cpu { get; set; } 42 | 43 | 44 | public override bool Execute() 45 | { 46 | switch (Platform.Os) 47 | { 48 | case Platform.OsKind.Linux: Os = "linux"; break; 49 | case Platform.OsKind.MacOsX: Os = "macosx"; break; 50 | case Platform.OsKind.Windows: Os = "windows"; break; 51 | default: Os = ""; break; 52 | } 53 | 54 | switch (Platform.Cpu) 55 | { 56 | case Platform.CpuKind.X86: Cpu = "x86"; break; 57 | case Platform.CpuKind.X64: Cpu = "x64"; break; 58 | default: Cpu = ""; break; 59 | } 60 | return true; 61 | } 62 | }; 63 | } 64 | -------------------------------------------------------------------------------- /RSocket.Rpc.Tools/RSocket.Rpc.Tools.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0 5 | build\_protobuf\ 6 | Protobuf.MSBuild 7 | true 8 | true 9 | RSocket RPC and Protocol Buffer compiler for managed C# and native C++ projects. 10 | 11 | Add this package to a project that contains .proto files to be compiled to code. 12 | It contains the compilers, include files and project system integration for RSocket RPC 13 | and Protocol buffer service description files necessary to build them on Windows, 14 | Linux and MacOS. Managed runtime is supplied separately in the RSocket.Rpc.Core package. 15 | Copyright 2018-2019 the original author or authors. 16 | RSocket RPC authors. 17 | RSocket.Rpc.Tools 18 | https://github.com/rsocket/rsocket-rpc-net 19 | Apache-2.0 20 | 21 | 22 | 23 | ../RSocket.Rpc.Protobuf/proto/ 24 | ../protoc_plugins/ 25 | 26 | 27 | 28 | 29 | 30 | 31 | <_Asset PackagePath="build/native/include/google/protobuf" Include="$(Assets_ProtoInclude)/google/protobuf/any.proto" /> 32 | <_Asset PackagePath="build/native/include/google/protobuf" Include="$(Assets_ProtoInclude)/google/protobuf/api.proto" /> 33 | <_Asset PackagePath="build/native/include/google/protobuf" Include="$(Assets_ProtoInclude)/google/protobuf/descriptor.proto" /> 34 | <_Asset PackagePath="build/native/include/google/protobuf" Include="$(Assets_ProtoInclude)/google/protobuf/duration.proto" /> 35 | <_Asset PackagePath="build/native/include/google/protobuf" Include="$(Assets_ProtoInclude)/google/protobuf/empty.proto" /> 36 | <_Asset PackagePath="build/native/include/google/protobuf" Include="$(Assets_ProtoInclude)/google/protobuf/field_mask.proto" /> 37 | <_Asset PackagePath="build/native/include/google/protobuf" Include="$(Assets_ProtoInclude)/google/protobuf/source_context.proto" /> 38 | <_Asset PackagePath="build/native/include/google/protobuf" Include="$(Assets_ProtoInclude)/google/protobuf/struct.proto" /> 39 | <_Asset PackagePath="build/native/include/google/protobuf" Include="$(Assets_ProtoInclude)/google/protobuf/timestamp.proto" /> 40 | <_Asset PackagePath="build/native/include/google/protobuf" Include="$(Assets_ProtoInclude)/google/protobuf/type.proto" /> 41 | <_Asset PackagePath="build/native/include/google/protobuf" Include="$(Assets_ProtoInclude)/google/protobuf/wrappers.proto" /> 42 | <_Asset PackagePath="build/native/include/rsocket/" Include="$(Assets_ProtoInclude)/rsocket/options.proto" /> 43 | <_Asset PackagePath="tools/windows_x64/" Include="$(Assets_ProtoCompiler)windows_x64/protoc.exe" /> 44 | <_Asset PackagePath="tools/linux_x64/" Include="$(Assets_ProtoCompiler)linux_x64/protoc" /> 45 | <_Asset PackagePath="tools/macosx_x64/" Include="$(Assets_ProtoCompiler)macosx_x64/protoc" /> 46 | 47 | 48 | <_Asset PackagePath="tools/windows_x64/" Include="$(Assets_ProtoCompiler)windows_x64/rsocket_rpc_csharp_plugin.exe" /> 49 | <_Asset PackagePath="tools/linux_x64/" Include="$(Assets_ProtoCompiler)linux_x64/rsocket_rpc_csharp_plugin" /> 50 | <_Asset PackagePath="tools/macosx_x64/" Include="$(Assets_ProtoCompiler)macosx_x64/rsocket_rpc_csharp_plugin" /> 51 | 52 | 53 | 54 | 55 | 56 | 57 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /RSocket.Rpc.Tools/build/RSocket.Rpc.Tools.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /RSocket.Rpc.Tools/build/RSocket.Rpc.Tools.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /RSocket.Rpc.Tools/build/_protobuf/Google.Protobuf.Tools.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 5 | 6 | 7 | 1 8 | 9 | 10 | 11 | $( [System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)../../tools) ) 12 | $( [System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)../native/include) ) 13 | 14 | 15 | 20 | 21 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /RSocket.Rpc.Tools/build/_protobuf/Protobuf.CSharp.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | 11 | 12 | 17 | 18 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 31 | 32 | 33 | 34 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 48 | 49 | 50 | 55 | 56 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 81 | 82 | 83 | 84 | 86 | 87 | 88 | 89 | 92 | 93 | 95 | 96 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /RSocket.Rpc.Tools/build/_protobuf/README: -------------------------------------------------------------------------------- 1 | TODO(kkm): These file will go into Google.Protobuf.Tools/build after package split. 2 | -------------------------------------------------------------------------------- /RSocket.Rpc.Tools/build/_rsocket/README: -------------------------------------------------------------------------------- 1 | TODO(kkm): These file will go into RSocket.Rpc.Tools/build after package split. 2 | Remove leading underscores from file names; they are hiding the 3 | files from some NuGet versions which pull them into project. 4 | -------------------------------------------------------------------------------- /RSocket.Rpc.Tools/build/_rsocket/RSocket.Rpc.CSharp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /RSocket.Rpc.Tools/build/_rsocket/_RSocket.Rpc.Tools.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 5 | 6 | 7 | -------------------------------------------------------------------------------- /RSocket.Rpc.Tools/build/_rsocket/_RSocket.Rpc.Tools.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 5 | rsocket_rpc_csharp_plugin 6 | 7 | 8 | 9 | 10 | 11 | File;BrowseObject 12 | 13 | 14 | 15 | 16 | 17 | Both 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | $(Protobuf_PackagedToolsPath)\$(Protobuf_ToolsOs)_$(Protobuf_ToolsCpu)\$(RSocketRpc_PluginFileName).exe 27 | $(Protobuf_PackagedToolsPath)/$(Protobuf_ToolsOs)_$(Protobuf_ToolsCpu)/$(RSocketRpc_PluginFileName) 29 | 30 | 31 | 32 | 33 | 34 | 35 | $(RSocketRpc_PluginFullPath) 36 | %(Protobuf_Compile.OutputDir) 37 | <_RSocketRpcOutputOptions Condition=" '%(Protobuf_Compile.Access)' == 'Internal' ">%(Protobuf_Compile._RSocketRpcOutputOptions);internal_access 38 | 39 | 40 | <_RSocketRpcOutputOptions>%(Protobuf_Compile._RSocketRpcOutputOptions);no_server 41 | 42 | 43 | <_RSocketRpcOutputOptions>%(Protobuf_Compile._RSocketRpcOutputOptions);no_client 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /RSocket.Rpc.Tools/build/native/RSocket.Rpc.Tools.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 5 | 6 | 7 | 1 8 | 9 | 10 | 11 | 12 | $(MSBuildThisFileDirectory)..\..\tools\windows_x86\protoc.exe 13 | $(MSBuildThisFileDirectory)include\ 14 | rsocket_rpc_cpp_plugin 15 | $(MSBuildThisFileDirectory)..\..\tools\windows_x86\rsocket_rpc_cpp_plugin.exe 16 | 17 | 18 | -------------------------------------------------------------------------------- /RSocket.Rpc.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | RSocket.Rpc 5 | RSocket RPC C# 6 | C# implementation of RSocket RPC - an RPC library and framework 7 | C# implementation of RSocket RPC - an RPC library and framework. See project site for more info. 8 | $version$ 9 | Netifi Inc. 10 | netifi 11 | Copyright 2019, Netifi Inc. 12 | RSocket RPC Protocol 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /RSocket.Rpc.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26430.4 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RSocket.Rpc.Core", "RSocket.Rpc.Core\RSocket.Rpc.Core.csproj", "{BD878CB3-BDB4-46AB-84EF-C3B4729F56BC}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RSocket.Rpc.Tools", "RSocket.Rpc.Tools\RSocket.Rpc.Tools.csproj", "{8A643A1B-B85C-4E3D-BFD3-719FE04D7E91}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RSocket.Rpc.Tools.Tests", "RSocket.Rpc.Tools.Tests\RSocket.Rpc.Tools.Tests.csproj", "{AEBE9BD8-E433-45B7-8B3D-D458EDBBCFC4}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RSocket.Rpc.Sample", "RSocket.Rpc.Sample\RSocket.Rpc.Sample.csproj", "{DDF007E0-E9E7-49AB-A4A9-FEFC8080E3A8}" 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|Any CPU = Debug|Any CPU 17 | Release|Any CPU = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {BD878CB3-BDB4-46AB-84EF-C3B4729F56BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {BD878CB3-BDB4-46AB-84EF-C3B4729F56BC}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {BD878CB3-BDB4-46AB-84EF-C3B4729F56BC}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {BD878CB3-BDB4-46AB-84EF-C3B4729F56BC}.Release|Any CPU.Build.0 = Release|Any CPU 24 | {8A643A1B-B85C-4E3D-BFD3-719FE04D7E91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {8A643A1B-B85C-4E3D-BFD3-719FE04D7E91}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {8A643A1B-B85C-4E3D-BFD3-719FE04D7E91}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {8A643A1B-B85C-4E3D-BFD3-719FE04D7E91}.Release|Any CPU.Build.0 = Release|Any CPU 28 | {AEBE9BD8-E433-45B7-8B3D-D458EDBBCFC4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {AEBE9BD8-E433-45B7-8B3D-D458EDBBCFC4}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {AEBE9BD8-E433-45B7-8B3D-D458EDBBCFC4}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {AEBE9BD8-E433-45B7-8B3D-D458EDBBCFC4}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {DDF007E0-E9E7-49AB-A4A9-FEFC8080E3A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {DDF007E0-E9E7-49AB-A4A9-FEFC8080E3A8}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {DDF007E0-E9E7-49AB-A4A9-FEFC8080E3A8}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {DDF007E0-E9E7-49AB-A4A9-FEFC8080E3A8}.Release|Any CPU.Build.0 = Release|Any CPU 36 | EndGlobalSection 37 | GlobalSection(SolutionProperties) = preSolution 38 | HideSolutionNode = FALSE 39 | EndGlobalSection 40 | GlobalSection(ExtensibilityGlobals) = postSolution 41 | SolutionGuid = {97AE1B72-072B-45E5-81EC-283FDF30B752} 42 | EndGlobalSection 43 | EndGlobal 44 | -------------------------------------------------------------------------------- /tests.json: -------------------------------------------------------------------------------- 1 | { 2 | "RSocket.Rpc.Tools.Tests": [ 3 | "RSocket.Rpc.Tools.Tests.CppGeneratorTest", 4 | "RSocket.Rpc.Tools.Tests.CSharpGeneratorTest", 5 | "RSocket.Rpc.Tools.Tests.DepFileUtilTest", 6 | "RSocket.Rpc.Tools.Tests.GeneratorTest", 7 | "RSocket.Rpc.Tools.Tests.ProtoCompileBasicTest", 8 | "RSocket.Rpc.Tools.Tests.ProtoCompileCommandLineGeneratorTest", 9 | "RSocket.Rpc.Tools.Tests.ProtoCompileCommandLinePrinterTest", 10 | "RSocket.Rpc.Tools.Tests.ProtoToolsPlatformTaskTest" 11 | ] 12 | } 13 | --------------------------------------------------------------------------------