Added Rubocop harness to enforce Ruby code style
diff --git a/.github/workflows/sca.yml b/.github/workflows/sca.yml
index 9fa2a16..ae41f86 100644
--- a/.github/workflows/sca.yml
+++ b/.github/workflows/sca.yml
@@ -62,6 +62,13 @@
         run: |
           python -m pip install --upgrade pip setuptools wheel flake8
 
+      - name: Set up Ruby
+        uses: ruby/setup-ruby@v1
+        with:
+          ruby-version: "2.7"
+          bundler-cache: true
+          working-directory: "lib/rb"
+
       # Generate thrift files so the static code analysis includes an analysis
       # of the files the thrift compiler spits out.
       - name: Build compiler
@@ -155,6 +162,13 @@
           composer install --quiet
           ./vendor/bin/phpcs
 
+      - name: Run rubocop
+        id: rubocop
+        continue-on-error: true
+        working-directory: "lib/rb"
+        run: |
+          bundle exec rubocop --config .rubocop.yml --format progress --format github . ../../test/rb ../../tutorial/rb
+
       - name: Print statistics
         if: ${{ always() }}
         run: |
@@ -176,6 +190,7 @@
           CPPCHECK_OUTCOME: ${{ steps.cppcheck.outcome }}
           FLAKE8_OUTCOME: ${{ steps.flake8.outcome }}
           PHPCS_OUTCOME: ${{ steps.phpcs.outcome }}
+          RUBOCOP_OUTCOME: ${{ steps.rubocop.outcome }}
         run: |
           failed=0
 
@@ -191,5 +206,9 @@
             echo "::error::Step 'phpcs' failed (outcome: $PHPCS_OUTCOME)"
             failed=1
           fi
+          if [ "$RUBOCOP_OUTCOME" != "success" ]; then
+            echo "::error::Step 'rubocop' failed (outcome: $RUBOCOP_OUTCOME)"
+            failed=1
+          fi
 
           exit $failed
diff --git a/lib/rb/.rubocop.yml b/lib/rb/.rubocop.yml
new file mode 100644
index 0000000..926edcb
--- /dev/null
+++ b/lib/rb/.rubocop.yml
@@ -0,0 +1,13 @@
+plugins:
+  - rubocop-performance
+  - rubocop-rspec
+
+AllCops:
+  DisabledByDefault: true
+  SuggestExtensions: false
+  TargetRubyVersion: 2.7
+  Exclude:
+    - "**/vendor/**/*"
+
+Layout/IndentationConsistency:
+  Enabled: true
diff --git a/lib/rb/Gemfile b/lib/rb/Gemfile
index 83ff867..f3da0a3 100644
--- a/lib/rb/Gemfile
+++ b/lib/rb/Gemfile
@@ -5,3 +5,5 @@
 # Only required for tests with Rack 2.x on Ruby 4.0+
 gem 'cgi'
 gem 'ostruct'
+
+eval_gemfile File.expand_path("Gemfile.linters", __dir__)
diff --git a/lib/rb/Gemfile.linters b/lib/rb/Gemfile.linters
new file mode 100644
index 0000000..00d4d22
--- /dev/null
+++ b/lib/rb/Gemfile.linters
@@ -0,0 +1,5 @@
+source "https://rubygems.org"
+
+gem 'rubocop', '~> 1.82.0'
+gem 'rubocop-performance', '~> 1.26.1'
+gem 'rubocop-rspec', '~> 3.8.0'
diff --git a/lib/rb/Gemfile.lock b/lib/rb/Gemfile.lock
index ea47938..5030d2d 100644
--- a/lib/rb/Gemfile.lock
+++ b/lib/rb/Gemfile.lock
@@ -7,6 +7,7 @@
 GEM
   remote: https://rubygems.org/
   specs:
+    ast (2.4.3)
     binding_of_caller (1.0.1)
       debug_inspector (>= 1.2.0)
     byebug (11.1.3)
@@ -16,9 +17,17 @@
     debug_inspector (1.2.0)
     diff-lcs (1.6.2)
     eventmachine (1.2.7)
+    json (2.18.1)
+    language_server-protocol (3.17.0.5)
+    lint_roller (1.1.0)
     logger (1.7.0)
     method_source (0.9.2)
     ostruct (0.6.3)
+    parallel (1.27.0)
+    parser (3.3.10.1)
+      ast (~> 2.4.1)
+      racc
+    prism (1.9.0)
     pry (0.11.3)
       coderay (~> 1.1.0)
       method_source (~> 0.9.0)
@@ -28,10 +37,13 @@
     pry-stack_explorer (0.4.9.3)
       binding_of_caller (>= 0.7)
       pry (>= 0.9.11)
+    racc (1.8.1)
     rack (2.2.22)
     rack-test (0.8.3)
       rack (>= 1.0, < 3)
+    rainbow (3.1.1)
     rake (13.3.1)
+    regexp_parser (2.11.3)
     rspec (3.13.2)
       rspec-core (~> 3.13.0)
       rspec-expectations (~> 3.13.0)
@@ -45,12 +57,37 @@
       diff-lcs (>= 1.2.0, < 2.0)
       rspec-support (~> 3.13.0)
     rspec-support (3.13.6)
+    rubocop (1.82.1)
+      json (~> 2.3)
+      language_server-protocol (~> 3.17.0.2)
+      lint_roller (~> 1.1.0)
+      parallel (~> 1.10)
+      parser (>= 3.3.0.2)
+      rainbow (>= 2.2.2, < 4.0)
+      regexp_parser (>= 2.9.3, < 3.0)
+      rubocop-ast (>= 1.48.0, < 2.0)
+      ruby-progressbar (~> 1.7)
+      unicode-display_width (>= 2.4.0, < 4.0)
+    rubocop-ast (1.49.0)
+      parser (>= 3.3.7.2)
+      prism (~> 1.7)
+    rubocop-performance (1.26.1)
+      lint_roller (~> 1.1)
+      rubocop (>= 1.75.0, < 2.0)
+      rubocop-ast (>= 1.47.1, < 2.0)
+    rubocop-rspec (3.8.0)
+      lint_roller (~> 1.1)
+      rubocop (~> 1.81)
+    ruby-progressbar (1.13.0)
     srv (1.0.0)
       rack (>= 1.3.0)
     thin (1.8.2)
       daemons (~> 1.0, >= 1.0.9)
       eventmachine (~> 1.0, >= 1.0.4)
       rack (>= 1, < 3)
+    unicode-display_width (3.2.0)
+      unicode-emoji (~> 4.1)
+    unicode-emoji (4.2.0)
 
 PLATFORMS
   arm64-darwin
@@ -70,6 +107,9 @@
   rack-test (~> 0.8.3)
   rake (~> 13.3)
   rspec (~> 3.7)
+  rubocop (~> 1.82.0)
+  rubocop-performance (~> 1.26.1)
+  rubocop-rspec (~> 3.8.0)
   srv (~> 1.0)
   thin (~> 1.7)
   thrift!
diff --git a/lib/rb/Rakefile b/lib/rb/Rakefile
index b33d773..7b51145 100644
--- a/lib/rb/Rakefile
+++ b/lib/rb/Rakefile
@@ -81,7 +81,7 @@
    Dir::chdir(File::dirname('ext/extconf.rb')) do
       unless sh "ruby #{File::basename('ext/extconf.rb')}"
         $stderr.puts "Failed to run extconf"
-          break
+        break
       end
       unless sh "make"
         $stderr.puts "make failed"
@@ -103,6 +103,13 @@
   ruby 'benchmark/benchmark.rb'
 end
 
+begin
+  require "rubocop/rake_task"
+  RuboCop::RakeTask.new
+rescue LoadError
+  task(:rubocop) { abort "Install the rubocop gem to run a static analysis" }
+end
+
 desc 'Builds the thrift gem'
 task :gem => [:spec, :build_ext] do
   unless sh 'gem', 'build', 'thrift.gemspec'
diff --git a/lib/rb/coding_standards.md b/lib/rb/coding_standards.md
index fa0390b..641265b 100644
--- a/lib/rb/coding_standards.md
+++ b/lib/rb/coding_standards.md
@@ -1 +1,9 @@
-Please follow [General Coding Standards](/doc/coding_standards.md)
+## Ruby Coding Standards
+
+Please follow:
+* [Thrift General Coding Standards](/doc/coding_standards.md)
+* Code Style for Ruby code enforced by RuboCop
+
+To check you code for compliance, run:
+
+    bundle exec rake rubocop
diff --git a/test/rb/.rubocop.yml b/test/rb/.rubocop.yml
new file mode 120000
index 0000000..e7754d9
--- /dev/null
+++ b/test/rb/.rubocop.yml
@@ -0,0 +1 @@
+../../lib/rb/.rubocop.yml
\ No newline at end of file
diff --git a/test/rb/Gemfile b/test/rb/Gemfile
index 2d0f8f1..71ea8ea 100644
--- a/test/rb/Gemfile
+++ b/test/rb/Gemfile
@@ -6,3 +6,5 @@
 gem 'rack', '~> 2.2'
 gem 'thin', '~> 1.7', '>= 1.7.2'
 gem 'test-unit', '~> 3.2', '>= 3.2.7'
+
+eval_gemfile File.expand_path("../../lib/rb/Gemfile.linters", __dir__)
diff --git a/test/rb/Gemfile.lock b/test/rb/Gemfile.lock
index 41b17b9..45bb8bb 100644
--- a/test/rb/Gemfile.lock
+++ b/test/rb/Gemfile.lock
@@ -7,17 +7,54 @@
 GEM
   remote: https://rubygems.org/
   specs:
+    ast (2.4.3)
     daemons (1.4.1)
     eventmachine (1.2.7)
+    json (2.18.1)
+    language_server-protocol (3.17.0.5)
+    lint_roller (1.1.0)
     logger (1.7.0)
+    parallel (1.27.0)
+    parser (3.3.10.1)
+      ast (~> 2.4.1)
+      racc
     power_assert (3.0.1)
+    prism (1.9.0)
+    racc (1.8.1)
     rack (2.2.22)
+    rainbow (3.1.1)
+    regexp_parser (2.11.3)
+    rubocop (1.82.1)
+      json (~> 2.3)
+      language_server-protocol (~> 3.17.0.2)
+      lint_roller (~> 1.1.0)
+      parallel (~> 1.10)
+      parser (>= 3.3.0.2)
+      rainbow (>= 2.2.2, < 4.0)
+      regexp_parser (>= 2.9.3, < 3.0)
+      rubocop-ast (>= 1.48.0, < 2.0)
+      ruby-progressbar (~> 1.7)
+      unicode-display_width (>= 2.4.0, < 4.0)
+    rubocop-ast (1.49.0)
+      parser (>= 3.3.7.2)
+      prism (~> 1.7)
+    rubocop-performance (1.26.1)
+      lint_roller (~> 1.1)
+      rubocop (>= 1.75.0, < 2.0)
+      rubocop-ast (>= 1.47.1, < 2.0)
+    rubocop-rspec (3.8.0)
+      lint_roller (~> 1.1)
+      rubocop (~> 1.81)
+    ruby-progressbar (1.13.0)
     test-unit (3.7.3)
       power_assert
     thin (1.8.2)
       daemons (~> 1.0, >= 1.0.9)
       eventmachine (~> 1.0, >= 1.0.4)
       rack (>= 1, < 3)
+    unicode-display_width (3.2.0)
+      unicode-emoji (~> 4.1)
+    unicode-emoji (4.2.0)
 
 PLATFORMS
   arm64-darwin
@@ -28,6 +65,9 @@
 
 DEPENDENCIES
   rack (~> 2.2)
+  rubocop (~> 1.82.0)
+  rubocop-performance (~> 1.26.1)
+  rubocop-rspec (~> 3.8.0)
   test-unit (~> 3.2, >= 3.2.7)
   thin (~> 1.7, >= 1.7.2)
   thrift!