j-law-ruby 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +9 -0
  3. data/README.md +109 -0
  4. data/Rakefile +87 -0
  5. data/ext/j_law_ruby/extconf.rb +34 -0
  6. data/lib/j_law_ruby/build_support.rb +129 -0
  7. data/lib/j_law_ruby/c_ffi.rb +662 -0
  8. data/lib/j_law_ruby.rb +532 -0
  9. data/rake_support/vendor_rust.rb +51 -0
  10. data/test/test_c_ffi_adapter.rb +46 -0
  11. data/test/test_consumption_tax.rb +66 -0
  12. data/test/test_gemspec.rb +82 -0
  13. data/test/test_income_tax.rb +77 -0
  14. data/test/test_income_tax_deductions.rb +82 -0
  15. data/test/test_real_estate.rb +98 -0
  16. data/test/test_stamp_tax.rb +68 -0
  17. data/test/test_withholding_tax.rb +65 -0
  18. data/vendor/rust/Cargo.lock +235 -0
  19. data/vendor/rust/Cargo.toml +12 -0
  20. data/vendor/rust/crates/j-law-c-ffi/Cargo.toml +20 -0
  21. data/vendor/rust/crates/j-law-c-ffi/j_law_c_ffi.h +493 -0
  22. data/vendor/rust/crates/j-law-c-ffi/src/lib.rs +1553 -0
  23. data/vendor/rust/crates/j-law-core/Cargo.toml +18 -0
  24. data/vendor/rust/crates/j-law-core/src/domains/consumption_tax/calculator.rs +216 -0
  25. data/vendor/rust/crates/j-law-core/src/domains/consumption_tax/context.rs +29 -0
  26. data/vendor/rust/crates/j-law-core/src/domains/consumption_tax/mod.rs +9 -0
  27. data/vendor/rust/crates/j-law-core/src/domains/consumption_tax/params.rs +24 -0
  28. data/vendor/rust/crates/j-law-core/src/domains/consumption_tax/policy.rs +34 -0
  29. data/vendor/rust/crates/j-law-core/src/domains/income_tax/assessment.rs +76 -0
  30. data/vendor/rust/crates/j-law-core/src/domains/income_tax/calculator.rs +222 -0
  31. data/vendor/rust/crates/j-law-core/src/domains/income_tax/context.rs +79 -0
  32. data/vendor/rust/crates/j-law-core/src/domains/income_tax/deduction/calculator.rs +167 -0
  33. data/vendor/rust/crates/j-law-core/src/domains/income_tax/deduction/context.rs +172 -0
  34. data/vendor/rust/crates/j-law-core/src/domains/income_tax/deduction/expense.rs +465 -0
  35. data/vendor/rust/crates/j-law-core/src/domains/income_tax/deduction/mod.rs +20 -0
  36. data/vendor/rust/crates/j-law-core/src/domains/income_tax/deduction/params.rs +205 -0
  37. data/vendor/rust/crates/j-law-core/src/domains/income_tax/deduction/personal.rs +324 -0
  38. data/vendor/rust/crates/j-law-core/src/domains/income_tax/deduction/types.rs +61 -0
  39. data/vendor/rust/crates/j-law-core/src/domains/income_tax/mod.rs +24 -0
  40. data/vendor/rust/crates/j-law-core/src/domains/income_tax/params.rs +109 -0
  41. data/vendor/rust/crates/j-law-core/src/domains/income_tax/policy.rs +103 -0
  42. data/vendor/rust/crates/j-law-core/src/domains/mod.rs +5 -0
  43. data/vendor/rust/crates/j-law-core/src/domains/real_estate/calculator.rs +197 -0
  44. data/vendor/rust/crates/j-law-core/src/domains/real_estate/context.rs +48 -0
  45. data/vendor/rust/crates/j-law-core/src/domains/real_estate/mod.rs +9 -0
  46. data/vendor/rust/crates/j-law-core/src/domains/real_estate/params.rs +43 -0
  47. data/vendor/rust/crates/j-law-core/src/domains/real_estate/policy.rs +40 -0
  48. data/vendor/rust/crates/j-law-core/src/domains/stamp_tax/calculator.rs +321 -0
  49. data/vendor/rust/crates/j-law-core/src/domains/stamp_tax/context.rs +408 -0
  50. data/vendor/rust/crates/j-law-core/src/domains/stamp_tax/mod.rs +12 -0
  51. data/vendor/rust/crates/j-law-core/src/domains/stamp_tax/params.rs +190 -0
  52. data/vendor/rust/crates/j-law-core/src/domains/stamp_tax/policy.rs +105 -0
  53. data/vendor/rust/crates/j-law-core/src/domains/withholding_tax/calculator.rs +247 -0
  54. data/vendor/rust/crates/j-law-core/src/domains/withholding_tax/context.rs +167 -0
  55. data/vendor/rust/crates/j-law-core/src/domains/withholding_tax/mod.rs +9 -0
  56. data/vendor/rust/crates/j-law-core/src/domains/withholding_tax/params.rs +80 -0
  57. data/vendor/rust/crates/j-law-core/src/domains/withholding_tax/policy.rs +49 -0
  58. data/vendor/rust/crates/j-law-core/src/error.rs +171 -0
  59. data/vendor/rust/crates/j-law-core/src/lib.rs +9 -0
  60. data/vendor/rust/crates/j-law-core/src/types/amount.rs +232 -0
  61. data/vendor/rust/crates/j-law-core/src/types/citation.rs +82 -0
  62. data/vendor/rust/crates/j-law-core/src/types/date.rs +280 -0
  63. data/vendor/rust/crates/j-law-core/src/types/mod.rs +11 -0
  64. data/vendor/rust/crates/j-law-core/src/types/rate.rs +219 -0
  65. data/vendor/rust/crates/j-law-core/src/types/rounding.rs +81 -0
  66. data/vendor/rust/crates/j-law-registry/Cargo.toml +15 -0
  67. data/vendor/rust/crates/j-law-registry/data/consumption_tax/consumption_tax.json +70 -0
  68. data/vendor/rust/crates/j-law-registry/data/income_tax/deductions.json +327 -0
  69. data/vendor/rust/crates/j-law-registry/data/income_tax/income_tax.json +352 -0
  70. data/vendor/rust/crates/j-law-registry/data/real_estate/brokerage_fee.json +125 -0
  71. data/vendor/rust/crates/j-law-registry/data/stamp_tax/stamp_tax.json +674 -0
  72. data/vendor/rust/crates/j-law-registry/data/withholding_tax/withholding_tax.json +70 -0
  73. data/vendor/rust/crates/j-law-registry/src/consumption_tax_loader.rs +325 -0
  74. data/vendor/rust/crates/j-law-registry/src/consumption_tax_schema.rs +49 -0
  75. data/vendor/rust/crates/j-law-registry/src/income_tax_deduction_loader.rs +636 -0
  76. data/vendor/rust/crates/j-law-registry/src/income_tax_deduction_schema.rs +111 -0
  77. data/vendor/rust/crates/j-law-registry/src/income_tax_loader.rs +445 -0
  78. data/vendor/rust/crates/j-law-registry/src/income_tax_schema.rs +44 -0
  79. data/vendor/rust/crates/j-law-registry/src/lib.rs +20 -0
  80. data/vendor/rust/crates/j-law-registry/src/loader.rs +221 -0
  81. data/vendor/rust/crates/j-law-registry/src/schema.rs +73 -0
  82. data/vendor/rust/crates/j-law-registry/src/stamp_tax_loader.rs +374 -0
  83. data/vendor/rust/crates/j-law-registry/src/stamp_tax_schema.rs +72 -0
  84. data/vendor/rust/crates/j-law-registry/src/validator.rs +204 -0
  85. data/vendor/rust/crates/j-law-registry/src/withholding_tax_loader.rs +310 -0
  86. data/vendor/rust/crates/j-law-registry/src/withholding_tax_schema.rs +61 -0
  87. metadata +148 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a2e37cfa4515c19a9ab8330f6cf37dec2e9e4a202383542c779c90ac525b3953
4
+ data.tar.gz: b3e3500018a5ecc1795d5e24b47079f8a254625997ca3cf380bdf2a3a92d7f2e
5
+ SHA512:
6
+ metadata.gz: ad62d52287bef5395b8b5c29527d3fbe16d8bce8789eb2f3c18d1e0fb3cf9400dfe7eda7bc3a3b1c1eeb9e3a0012b3cfbf986ad2d12715ff06d56173182ba285
7
+ data.tar.gz: 9e9dabffff57a7b307b446dfd20a4e7a79d90edfc3af90e1ad599dc22f080b281c2b04f0de13960ca87608e4b9a499ac4cb1a039dd6fa5b0dbd3ee48f425b063
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gemspec
6
+
7
+ gem "rake"
8
+ gem "ffi"
9
+ gem "minitest"
data/README.md ADDED
@@ -0,0 +1,109 @@
1
+ # j_law_ruby
2
+
3
+ 日本法令計算の PoC を Ruby から試すためのバインディングです。
4
+
5
+ 内部では `j-law-c-ffi` の C ABI を `ffi` gem 経由で呼び出し、Rust コアの整数演算ロジックを Ruby から利用します。
6
+
7
+ > [!WARNING]
8
+ > **PoC / アルファ版に関する注意事項**
9
+ >
10
+ > - 本ライブラリは現在 **`v0.0.1` のアルファ版**です。API と配布形態は予告なく変更される場合があります。
11
+ > - この binding が返す計算結果について、法的正確性、完全性、最新性、個別事案への適合性は保証しません。
12
+ > - コードの一部には **AI 生成 / AI 補助**による実装が含まれ、人手による全面レビューは完了していません。
13
+ > - 税務申告や契約実務の唯一の根拠として使用せず、一次資料と専門家で検証してください。
14
+ > - 詳細は [プロジェクトステータスと免責](../../docs/project-status.md) を参照してください。
15
+
16
+ ## 対応機能
17
+
18
+ - `JLawRuby::ConsumptionTax.calc_consumption_tax`
19
+ - `JLawRuby::RealEstate.calc_brokerage_fee`
20
+ - `JLawRuby::IncomeTax.calc_income_tax`
21
+ - `JLawRuby::IncomeTax.calc_income_deductions`
22
+ - `JLawRuby::IncomeTax.calc_income_tax_assessment`
23
+ - `JLawRuby::StampTax.calc_stamp_tax`
24
+ - `JLawRuby::WithholdingTax.calc_withholding_tax`
25
+
26
+ ## インストール
27
+
28
+ CI と publish workflow で検証している Ruby の範囲は `3.1` から `4.0` です。
29
+ RubyGems では `linux/x86_64` `linux/aarch64` `macos/x86_64` `macos/arm64` `windows/amd64`
30
+ 向けの build 済み platform gem を配布します。これらの環境では Rust toolchain は不要です。
31
+ その他の環境では source gem にフォールバックし、`gem install` 時に Rust `1.94.0`
32
+ toolchain を使って `j-law-c-ffi` をビルドします。
33
+
34
+ ```sh
35
+ gem install j_law_ruby
36
+ ```
37
+
38
+ source gem を明示的に使う場合は次を実行します。
39
+
40
+ ```sh
41
+ gem install j_law_ruby --platform ruby
42
+ ```
43
+
44
+ 開発環境では次を実行します。
45
+
46
+ ```sh
47
+ cd crates/j-law-ruby
48
+ bundle install
49
+ bundle exec rake compile
50
+ bundle exec rake test
51
+ ```
52
+
53
+ ## クイックスタート
54
+
55
+ ```ruby
56
+ require "date"
57
+ require "j_law_ruby"
58
+
59
+ date = Date.new(2024, 8, 1)
60
+
61
+ puts JLawRuby::ConsumptionTax.calc_consumption_tax(100_000, Date.new(2024, 1, 1), false).tax_amount
62
+ puts JLawRuby::RealEstate.calc_brokerage_fee(5_000_000, date, false, false).total_with_tax
63
+
64
+ assessment = JLawRuby::IncomeTax.calc_income_tax_assessment(
65
+ 8_000_000,
66
+ Date.new(2024, 1, 1),
67
+ social_insurance_premium_paid: 600_000
68
+ )
69
+ puts assessment.tax.total_tax
70
+
71
+ puts JLawRuby::StampTax.calc_stamp_tax(:article1_real_estate_transfer, 5_000_000, date).tax_amount
72
+
73
+ puts JLawRuby::WithholdingTax.calc_withholding_tax(
74
+ 1_500_000,
75
+ Date.new(2026, 1, 1),
76
+ :professional_fee
77
+ ).tax_amount
78
+ ```
79
+
80
+ ## API メモ
81
+
82
+ - すべての金額は整数円です。
83
+ - すべての API は `Date` / `DateTime` を受け取り、型不一致は `TypeError` を送出します。
84
+ - 法令適用外日付や入力不正は `RuntimeError` を送出します。
85
+ - `calc_stamp_tax()` の `document_code` / `flags` は `Symbol` または `String` を受け取ります。
86
+ - `calc_withholding_tax()` の `category` は `:manuscript_and_lecture` / `:professional_fee` / `:exclusive_contract_fee` などを指定します。
87
+
88
+ ## Gem ビルド
89
+
90
+ ```sh
91
+ cd crates/j-law-ruby
92
+ bundle install
93
+ bundle exec rake build_source_gem
94
+ bundle exec rake build_binary_gem
95
+ ```
96
+
97
+ `rake build` は `build_source_gem` のエイリアスです。
98
+ `build_source_gem` は source gem 用に必要な Rust ソースを `vendor/rust/` へ同期してから gem を生成します。
99
+ `build_binary_gem` は共有ライブラリを事前にビルドして、platform gem に同梱します。
100
+
101
+ ## 関連ドキュメント
102
+
103
+ - [プロジェクトステータスと免責](../../docs/project-status.md)
104
+ - [リポジトリ README](../../README.md)
105
+ - [利用ガイド](../../docs/usage.md)
106
+
107
+ ## ライセンス
108
+
109
+ [MIT License](../../LICENSE)
data/Rakefile ADDED
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rake/testtask"
4
+ require_relative "lib/j_law_ruby/build_support"
5
+ require_relative "rake_support/vendor_rust"
6
+
7
+ def with_unbundled_env
8
+ if defined?(Bundler)
9
+ Bundler.with_unbundled_env { yield }
10
+ else
11
+ yield
12
+ end
13
+ end
14
+
15
+ def gem_root
16
+ File.expand_path(__dir__)
17
+ end
18
+
19
+ def prepare_vendor_rust
20
+ JLawRuby::VendorRust.prepare!(gem_root)
21
+ end
22
+
23
+ def clean_native_library
24
+ rm_rf "lib/j_law_ruby/native"
25
+ end
26
+
27
+ def compile_native_library
28
+ prepare_vendor_rust
29
+
30
+ Dir.chdir("ext/j_law_ruby") do
31
+ ruby "extconf.rb"
32
+ sh JLawRuby::BuildSupport.make_command
33
+ end
34
+ end
35
+
36
+ task :vendor_rust do
37
+ prepare_vendor_rust
38
+ end
39
+
40
+ task :clean_native do
41
+ clean_native_library
42
+ end
43
+
44
+ task :compile do
45
+ compile_native_library
46
+ end
47
+
48
+ task :build_source_gem do
49
+ prepare_vendor_rust
50
+ clean_native_library
51
+
52
+ with_unbundled_env do
53
+ sh "gem", "build", "j_law_ruby.gemspec"
54
+ end
55
+ end
56
+
57
+ task :build_binary_gem do
58
+ compile_native_library
59
+
60
+ with_unbundled_env do
61
+ sh(
62
+ { JLawRuby::BuildSupport::BINARY_GEM_ENV => "1" },
63
+ "gem", "build", "j_law_ruby.gemspec"
64
+ )
65
+ end
66
+ end
67
+
68
+ task :clean do
69
+ rm_rf "vendor/rust"
70
+ rm_rf "lib/j_law_ruby/native"
71
+ rm_f FileList["*.gem"]
72
+
73
+ next unless File.exist?("ext/j_law_ruby/Makefile")
74
+
75
+ Dir.chdir("ext/j_law_ruby") do
76
+ sh JLawRuby::BuildSupport.make_command, "clean"
77
+ end
78
+ end
79
+
80
+ Rake::TestTask.new(:test) do |t|
81
+ t.libs << "lib"
82
+ t.test_files = FileList["test/test_*.rb"]
83
+ end
84
+
85
+ task build: :build_source_gem
86
+ task test: :compile
87
+ task default: :test
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "fileutils"
4
+ require "mkmf"
5
+ require_relative "../../lib/j_law_ruby/build_support"
6
+
7
+ gem_root = File.expand_path("../..", __dir__)
8
+ packaged_library = JLawRuby::BuildSupport.packaged_shared_library_path(gem_root)
9
+
10
+ unless JLawRuby::BuildSupport.should_build_shared_library?(gem_root)
11
+ puts "Using packaged j-law-c-ffi shared library at #{packaged_library}"
12
+ JLawRuby::BuildSupport.write_stub_makefile("Makefile")
13
+ exit 0
14
+ end
15
+
16
+ manifest_path = JLawRuby::BuildSupport.manifest_path(gem_root)
17
+
18
+ abort "Cargo workspace for j-law-c-ffi was not found." if manifest_path.nil?
19
+
20
+ profile = JLawRuby::BuildSupport.cargo_profile
21
+ cargo_command = ["cargo", "build", "-p", "j-law-c-ffi", "--manifest-path", manifest_path]
22
+ cargo_command << "--release" if profile == "release"
23
+
24
+ puts "Building j-law-c-ffi (#{profile}) via #{manifest_path}"
25
+ abort "cargo build failed" unless system(*cargo_command)
26
+
27
+ built_library = JLawRuby::BuildSupport.built_shared_library_path(manifest_path, profile)
28
+ abort "built shared library was not found: #{built_library}" unless File.file?(built_library)
29
+
30
+ native_dir = JLawRuby::BuildSupport.native_dir(gem_root)
31
+ FileUtils.mkdir_p(native_dir)
32
+ FileUtils.cp(built_library, packaged_library)
33
+
34
+ JLawRuby::BuildSupport.write_stub_makefile("Makefile")
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rbconfig"
4
+
5
+ module JLawRuby
6
+ module BuildSupport
7
+ module_function
8
+
9
+ BINARY_GEM_ENV = "JLAW_RUBY_BINARY_GEM"
10
+ FORCE_CARGO_BUILD_ENV = "JLAW_RUBY_FORCE_CARGO_BUILD"
11
+
12
+ def cargo_profile
13
+ ENV.fetch("JLAW_RUBY_CARGO_PROFILE", "release")
14
+ end
15
+
16
+ def binary_gem_build?
17
+ ENV[BINARY_GEM_ENV] == "1"
18
+ end
19
+
20
+ def force_cargo_build?
21
+ ENV[FORCE_CARGO_BUILD_ENV] == "1"
22
+ end
23
+
24
+ def gem_platform
25
+ require "rubygems/platform"
26
+
27
+ Gem::Platform.local
28
+ end
29
+
30
+ def make_command
31
+ RbConfig::CONFIG.fetch("MAKE", "make")
32
+ end
33
+
34
+ def shared_library_filename
35
+ case RbConfig::CONFIG["host_os"]
36
+ when /mswin|mingw|cygwin/
37
+ "j_law_c_ffi.dll"
38
+ when /darwin/
39
+ "libj_law_c_ffi.dylib"
40
+ else
41
+ "libj_law_c_ffi.so"
42
+ end
43
+ end
44
+
45
+ def native_dir(gem_root)
46
+ File.join(gem_root, "lib", "j_law_ruby", "native")
47
+ end
48
+
49
+ def packaged_shared_library_path(gem_root)
50
+ File.join(native_dir(gem_root), shared_library_filename)
51
+ end
52
+
53
+ def packaged_shared_library?(gem_root)
54
+ File.file?(packaged_shared_library_path(gem_root))
55
+ end
56
+
57
+ def vendored_workspace_root(gem_root)
58
+ File.join(gem_root, "vendor", "rust")
59
+ end
60
+
61
+ def vendored_manifest_path(gem_root)
62
+ File.join(vendored_workspace_root(gem_root), "Cargo.toml")
63
+ end
64
+
65
+ def repo_workspace_root(gem_root)
66
+ File.expand_path("../..", gem_root)
67
+ end
68
+
69
+ def repo_manifest_path(gem_root)
70
+ File.join(repo_workspace_root(gem_root), "Cargo.toml")
71
+ end
72
+
73
+ def manifest_path(gem_root)
74
+ vendored_manifest = vendored_manifest_path(gem_root)
75
+ return vendored_manifest if File.file?(vendored_manifest)
76
+
77
+ repo_manifest = repo_manifest_path(gem_root)
78
+ return repo_manifest if File.file?(repo_manifest)
79
+
80
+ nil
81
+ end
82
+
83
+ def built_shared_library_path(manifest_path, profile)
84
+ File.join(File.dirname(manifest_path), "target", profile, shared_library_filename)
85
+ end
86
+
87
+ def shared_library_candidates(gem_root)
88
+ candidates = []
89
+ env_path = ENV["JLAW_RUBY_C_FFI_LIB"]
90
+ candidates << env_path unless env_path.nil? || env_path.empty?
91
+ candidates << packaged_shared_library_path(gem_root)
92
+
93
+ [vendored_manifest_path(gem_root), repo_manifest_path(gem_root)].each do |manifest|
94
+ next unless File.file?(manifest)
95
+
96
+ candidates << built_shared_library_path(manifest, "release")
97
+ candidates << built_shared_library_path(manifest, "debug")
98
+ end
99
+
100
+ candidates.uniq
101
+ end
102
+
103
+ def resolve_shared_library_path(gem_root)
104
+ shared_library_candidates(gem_root).find { |path| File.file?(path) }
105
+ end
106
+
107
+ def should_build_shared_library?(gem_root)
108
+ return true if force_cargo_build?
109
+
110
+ !packaged_shared_library?(gem_root)
111
+ end
112
+
113
+ def write_stub_makefile(path = "Makefile")
114
+ File.write(
115
+ path,
116
+ <<~MAKEFILE
117
+ all:
118
+ \t@true
119
+
120
+ install:
121
+ \t@true
122
+
123
+ clean:
124
+ \t@true
125
+ MAKEFILE
126
+ )
127
+ end
128
+ end
129
+ end