sashite-sin 2.1.0 → 3.0.0

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.
data/README.md CHANGED
@@ -1,17 +1,15 @@
1
- # Sin.rb
1
+ # sin.rb
2
2
 
3
3
  [![Version](https://img.shields.io/github/v/tag/sashite/sin.rb?label=Version&logo=github)](https://github.com/sashite/sin.rb/tags)
4
4
  [![Yard documentation](https://img.shields.io/badge/Yard-documentation-blue.svg?logo=github)](https://rubydoc.info/github/sashite/sin.rb/main)
5
- ![Ruby](https://github.com/sashite/sin.rb/actions/workflows/main.yml/badge.svg?branch=main)
6
- [![License](https://img.shields.io/github/license/sashite/sin.rb?label=License&logo=github)](https://github.com/sashite/sin.rb/raw/main/LICENSE.md)
5
+ [![CI](https://github.com/sashite/sin.rb/actions/workflows/main.yml/badge.svg?branch=main)](https://github.com/sashite/sin.rb/actions)
6
+ [![License](https://img.shields.io/github/license/sashite/sin.rb?label=License&logo=github)](https://github.com/sashite/sin.rb/raw/main/LICENSE)
7
7
 
8
- > **SIN** (Style Identifier Notation) implementation for the Ruby language.
8
+ > **SIN** (Style Identifier Notation) implementation for Ruby.
9
9
 
10
- ## What is SIN?
10
+ ## Overview
11
11
 
12
- SIN (Style Identifier Notation) provides a compact, ASCII-based format for identifying **styles** in abstract strategy board games. SIN uses single-character identifiers with case encoding to represent both style identity and player assignment simultaneously.
13
-
14
- This gem implements the [SIN Specification v1.0.0](https://sashite.dev/specs/sin/1.0.0/) exactly, providing a rule-agnostic notation system for style identification in board games.
12
+ This library implements the [SIN Specification v1.0.0](https://sashite.dev/specs/sin/1.0.0/).
15
13
 
16
14
  ## Installation
17
15
 
@@ -28,321 +26,205 @@ gem install sashite-sin
28
26
 
29
27
  ## Usage
30
28
 
31
- ### Basic Operations
29
+ ### Parsing (String → Identifier)
30
+
31
+ Convert a SIN string into an `Identifier` object.
32
32
 
33
33
  ```ruby
34
34
  require "sashite/sin"
35
35
 
36
- # Parse SIN strings into identifier objects
37
- identifier = Sashite::Sin.parse("C") # Family=:C, Side=:first
38
- identifier.to_s # => "C"
39
- identifier.family # => :C
40
- identifier.side # => :first
41
- identifier.letter # => "C" (combined representation)
42
-
43
- # Create identifiers directly
44
- identifier = Sashite::Sin.identifier(:C, :first) # Family=:C, Side=:first
45
- identifier = Sashite::Sin::Identifier.new(:C, :second) # Family=:C, Side=:second
46
-
47
- # Validate SIN strings
48
- Sashite::Sin.valid?("C") # => true
49
- Sashite::Sin.valid?("c") # => true
50
- Sashite::Sin.valid?("1") # => false (not a letter)
51
- Sashite::Sin.valid?("CC") # => false (not single character)
52
- ```
36
+ # Standard parsing (raises on error)
37
+ sin = Sashite::Sin.parse("C")
38
+ sin.style # => :C
39
+ sin.side # => :first
53
40
 
54
- ### Identifier Transformations
41
+ # Lowercase indicates second player
42
+ sin = Sashite::Sin.parse("c")
43
+ sin.style # => :C
44
+ sin.side # => :second
55
45
 
56
- ```ruby
57
- # All transformations return new immutable instances
58
- identifier = Sashite::Sin.parse("C")
46
+ # Invalid input raises ArgumentError
47
+ Sashite::Sin.parse("") # => raises ArgumentError
48
+ Sashite::Sin.parse("CC") # => raises ArgumentError
49
+ ```
59
50
 
60
- # Flip player assignment
61
- flipped = identifier.flip # Family=:C, Side=:second
62
- flipped.to_s # => "c"
51
+ ### Formatting (Identifier → String)
63
52
 
64
- # Change family
65
- changed = identifier.with_family(:S) # Family=:S, Side=:first
66
- changed.to_s # => "S"
53
+ Convert an `Identifier` back to a SIN string.
67
54
 
68
- # Change side
69
- other_side = identifier.with_side(:second) # Family=:C, Side=:second
70
- other_side.to_s # => "c"
55
+ ```ruby
56
+ # From Identifier object
57
+ sin = Sashite::Sin::Identifier.new(:C, :first)
58
+ sin.to_s # => "C"
71
59
 
72
- # Chain transformations
73
- result = identifier.flip.with_family(:M) # Family=:M, Side=:second
74
- result.to_s # => "m"
60
+ sin = Sashite::Sin::Identifier.new(:C, :second)
61
+ sin.to_s # => "c"
75
62
  ```
76
63
 
77
- ### Player and Style Queries
64
+ ### Validation
78
65
 
79
66
  ```ruby
80
- identifier = Sashite::Sin.parse("C")
81
- opposite = Sashite::Sin.parse("s")
82
-
83
- # Player identification
84
- identifier.first_player? # => true
85
- identifier.second_player? # => false
86
- opposite.first_player? # => false
87
- opposite.second_player? # => true
88
-
89
- # Family and side comparison
90
- chess1 = Sashite::Sin.parse("C")
91
- chess2 = Sashite::Sin.parse("c")
92
- shogi = Sashite::Sin.parse("S")
93
-
94
- chess1.same_family?(chess2) # => true (both Chess family)
95
- chess1.same_side?(shogi) # => true (both first player)
96
- chess1.same_family?(shogi) # => false (different families)
67
+ # Boolean check
68
+ Sashite::Sin.valid?("C") # => true
69
+ Sashite::Sin.valid?("c") # => true
70
+ Sashite::Sin.valid?("") # => false
71
+ Sashite::Sin.valid?("CC") # => false
72
+ Sashite::Sin.valid?("1") # => false
97
73
  ```
98
74
 
99
- ### Identifier Collections
75
+ ### Accessing Identifier Data
100
76
 
101
77
  ```ruby
102
- # Working with multiple identifiers
103
- identifiers = %w[C c S s M m].map { |sin| Sashite::Sin.parse(sin) }
104
-
105
- # Filter by player
106
- first_player_identifiers = identifiers.select(&:first_player?)
107
- first_player_identifiers.map(&:to_s) # => ["C", "S", "M"]
78
+ sin = Sashite::Sin.parse("C")
108
79
 
109
- # Group by family
110
- by_family = identifiers.group_by(&:family)
111
- by_family[:C].size # => 2 (both C and c)
80
+ # Get attributes
81
+ sin.style # => :C
82
+ sin.side # => :first
112
83
 
113
- # Find specific families
114
- chess_identifiers = identifiers.select { |i| i.family == :C }
115
- chess_identifiers.map(&:to_s) # => ["C", "c"]
84
+ # Get string component
85
+ sin.letter # => "C"
116
86
  ```
117
87
 
118
- ## Format Specification
88
+ ### Transformations
119
89
 
120
- ### Structure
121
- ```
122
- <style-letter>
123
- ```
124
-
125
- ### Grammar (BNF)
126
- ```bnf
127
- <sin> ::= <uppercase-letter> | <lowercase-letter>
90
+ All transformations return new immutable `Identifier` objects.
128
91
 
129
- <uppercase-letter> ::= "A" | "B" | "C" | ... | "Z"
130
- <lowercase-letter> ::= "a" | "b" | "c" | ... | "z"
131
- ```
132
-
133
- ### Regular Expression
134
92
  ```ruby
135
- /\A[A-Za-z]\z/
136
- ```
93
+ sin = Sashite::Sin.parse("C")
137
94
 
138
- ### Style Attribute Mapping
95
+ # Side transformation
96
+ sin.flip.to_s # => "c"
139
97
 
140
- SIN encodes style attributes using the following correspondence:
141
-
142
- | Style Attribute | SIN Encoding | Examples |
143
- |-----------------|--------------|----------|
144
- | **Family** | Style family symbol | `:C`, `:S`, `:X` |
145
- | **Side** | Player assignment | `:first`, `:second` |
146
- | **Letter** | Combined representation | `"C"`, `"c"`, `"S"`, `"s"` |
147
-
148
- #### Dual-Purpose Encoding
149
-
150
- The **Letter** combines two distinct semantic components:
151
- - **Style Family**: The underlying family symbol (:A-:Z), representing the game tradition or rule system
152
- - **Player Assignment**: The side (:first or :second), encoded as case in the letter representation
153
-
154
- **Examples**:
155
- - Family `:C` + Side `:first` → Letter `"C"` (Chess, First player)
156
- - Family `:C` + Side `:second` → Letter `"c"` (Chess, Second player)
157
- - Family `:S` + Side `:first` → Letter `"S"` (Shōgi, First player)
158
- - Family `:S` + Side `:second` → Letter `"s"` (Shōgi, Second player)
159
-
160
- ## Traditional Game Style Examples
98
+ # Attribute changes
99
+ sin.with_style(:S).to_s # => "S"
100
+ sin.with_side(:second).to_s # => "c"
101
+ ```
161
102
 
162
- The SIN specification is rule-agnostic and does not define specific letter assignments. However, here are common usage patterns following [SIN Examples](https://sashite.dev/specs/sin/1.0.0/examples/):
103
+ ### Queries
163
104
 
164
105
  ```ruby
165
- # Chess (8×8 board)
166
- chess_white = Sashite::Sin.parse("C") # First player (White pieces)
167
- chess_black = Sashite::Sin.parse("c") # Second player (Black pieces)
168
-
169
- # Shōgi (9×9 board)
170
- shogi_sente = Sashite::Sin.parse("S") # First player (Sente 先手)
171
- shogi_gote = Sashite::Sin.parse("s") # Second player (Gote 後手)
106
+ sin = Sashite::Sin.parse("C")
172
107
 
173
- # Xiangqi (9×10 board)
174
- xiangqi_red = Sashite::Sin.parse("X") # First player (Red pieces)
175
- xiangqi_black = Sashite::Sin.parse("x") # Second player (Black pieces)
108
+ # Side queries
109
+ sin.first_player? # => true
110
+ sin.second_player? # => false
176
111
 
177
- # Makruk (8×8 board)
178
- makruk_white = Sashite::Sin.parse("M") # First player (White pieces)
179
- makruk_black = Sashite::Sin.parse("m") # Second player (Black pieces)
180
-
181
- # Janggi (9×10 board)
182
- janggi_cho = Sashite::Sin.parse("J") # First player (Cho 초)
183
- janggi_han = Sashite::Sin.parse("j") # Second player (Han 한)
112
+ # Comparison queries
113
+ other = Sashite::Sin.parse("c")
114
+ sin.same_style?(other) # => true
115
+ sin.same_side?(other) # => false
184
116
  ```
185
117
 
186
- ## Cross-Style Scenarios
118
+ ## API Reference
119
+
120
+ ### Types
187
121
 
188
122
  ```ruby
189
- # Chess vs. Ōgi Match (both 8×8 compatible)
190
- chess_white = Sashite::Sin.parse("C") # Chess style, first player
191
- ogi_black = Sashite::Sin.parse("o") # Ōgi style, second player
192
-
193
- # Cross-Style Match Setup
194
- def create_hybrid_match
195
- [
196
- Sashite::Sin.parse("C"), # First player uses Chess family
197
- Sashite::Sin.parse("s") # Second player uses Shōgi family
198
- ]
123
+ # Identifier represents a parsed SIN identifier with style and side.
124
+ class Sashite::Sin::Identifier
125
+ # Creates an Identifier from style and side.
126
+ # Raises ArgumentError if attributes are invalid.
127
+ #
128
+ # @param style [Symbol] Style abbreviation (:A through :Z)
129
+ # @param side [Symbol] Player side (:first or :second)
130
+ # @return [Identifier]
131
+ def initialize(style, side)
132
+
133
+ # Returns the style as an uppercase symbol.
134
+ #
135
+ # @return [Symbol]
136
+ def style
137
+
138
+ # Returns the player side.
139
+ #
140
+ # @return [Symbol] :first or :second
141
+ def side
142
+
143
+ # Returns the SIN string representation.
144
+ #
145
+ # @return [String]
146
+ def to_s
199
147
  end
200
-
201
- identifiers = create_hybrid_match
202
- identifiers[0].same_side?(identifiers[1]) # => false (different players)
203
- identifiers[0].same_family?(identifiers[1]) # => false (different families)
204
148
  ```
205
149
 
206
- ## System Constraints
207
-
208
- ### Character Limitation
209
- SIN provides **26 possible identifiers** per player using ASCII letters (A-Z, a-z).
210
-
211
- ### Player Limitation
212
- SIN supports exactly **two players** through case distinction:
213
- - **First player**: Uppercase letters (A-Z) → `:first`
214
- - **Second player**: Lowercase letters (a-z) → `:second`
215
-
216
- ### Context Dependency
217
- The specific SIN assignment for a style may vary between different game contexts based on collision avoidance, historical precedence, and community conventions.
218
-
219
- ## API Reference
220
-
221
- ### Main Module Methods
222
-
223
- - `Sashite::Sin.valid?(sin_string)` - Check if string is valid SIN notation
224
- - `Sashite::Sin.parse(sin_string)` - Parse SIN string into Identifier object
225
- - `Sashite::Sin.identifier(family, side)` - Create identifier instance directly
226
-
227
- ### Identifier Class
228
-
229
- #### Creation and Parsing
230
- - `Sashite::Sin::Identifier.new(family, side)` - Create identifier instance
231
- - `Sashite::Sin::Identifier.parse(sin_string)` - Parse SIN string
232
-
233
- #### Attribute Access
234
- - `#family` - Get style family (symbol :A through :Z)
235
- - `#side` - Get player side (:first or :second)
236
- - `#letter` - Get combined letter representation (string)
237
- - `#to_s` - Convert to SIN string representation
238
-
239
- #### Player Queries
240
- - `#first_player?` - Check if first player identifier
241
- - `#second_player?` - Check if second player identifier
242
-
243
- #### Transformations (immutable - return new instances)
244
- - `#flip` - Switch player assignment
245
- - `#with_family(new_family)` - Create identifier with different family
246
- - `#with_side(new_side)` - Create identifier with different side
247
-
248
- #### Comparison Methods
249
- - `#same_family?(other)` - Check if same style family
250
- - `#same_side?(other)` - Check if same player side
251
- - `#==(other)` - Full equality comparison
252
- - `#same_letter?(other)` - Alias for `same_family?` (deprecated)
253
-
254
150
  ### Constants
255
151
 
256
- - `Sashite::Sin::Identifier::FIRST_PLAYER` - Symbol for first player (`:first`)
257
- - `Sashite::Sin::Identifier::SECOND_PLAYER` - Symbol for second player (`:second`)
258
- - `Sashite::Sin::Identifier::VALID_FAMILIES` - Array of valid families (`:A` to `:Z`)
259
- - `Sashite::Sin::Identifier::VALID_SIDES` - Array of valid sides
260
- - `Sashite::Sin::Identifier::SIN_PATTERN` - Regular expression for SIN validation
261
-
262
- ## Advanced Usage
152
+ ```ruby
153
+ Sashite::Sin::Identifier::VALID_STYLES # => [:A, :B, ..., :Z]
154
+ Sashite::Sin::Identifier::VALID_SIDES # => [:first, :second]
155
+ ```
263
156
 
264
- ### Family and Side Separation
157
+ ### Parsing
265
158
 
266
159
  ```ruby
267
- # Clear separation of concerns
268
- identifier = Sashite::Sin.parse("C")
269
- identifier.family # => :C (Style Family - invariant)
270
- identifier.side # => :first (Player Assignment)
271
- identifier.letter # => "C" (Combined representation)
272
-
273
- # Transformations are explicit
274
- chess_white = Sashite::Sin.identifier(:C, :first)
275
- shogi_white = chess_white.with_family(:S) # Change family, keep side
276
- chess_black = chess_white.with_side(:second) # Change side, keep family
160
+ # Parses a SIN string into an Identifier.
161
+ # Raises ArgumentError if the string is not valid.
162
+ #
163
+ # @param string [String] SIN string
164
+ # @return [Identifier]
165
+ # @raise [ArgumentError] if invalid
166
+ def Sashite::Sin.parse(string)
277
167
  ```
278
168
 
279
- ### Immutable Transformations
169
+ ### Validation
280
170
 
281
171
  ```ruby
282
- # All transformations return new instances
283
- original = Sashite::Sin.identifier(:C, :first)
284
- flipped = original.flip
285
- changed_family = original.with_family(:S)
286
-
287
- # Original identifier is never modified
288
- original.to_s # => "C" (unchanged)
289
- flipped.to_s # => "c"
290
- changed_family.to_s # => "S"
291
-
292
- # Transformations can be chained
293
- result = original.flip.with_family(:M).flip
294
- result.to_s # => "M"
172
+ # Reports whether string is a valid SIN identifier.
173
+ #
174
+ # @param string [String] SIN string
175
+ # @return [Boolean]
176
+ def Sashite::Sin.valid?(string)
295
177
  ```
296
178
 
297
- ## Design Properties
179
+ ### Transformations
298
180
 
299
- Following the SIN v1.0.0 specification, this implementation provides:
181
+ All transformations return new `Sashite::Sin::Identifier` objects:
300
182
 
301
- - **ASCII compatibility**: Maximum portability across systems
302
- - **Rule-agnostic**: Independent of specific game mechanics
303
- - **Minimal overhead**: Single character per style-player combination
304
- - **Flexible collision resolution**: Systematic approaches for identifier conflicts
305
- - **Semantic clarity**: Distinct concepts for Family, Side, and Letter
306
- - **SNN coordination**: Works harmoniously with formal style naming
307
- - **Context-aware**: Adapts to avoid conflicts within specific game scenarios
308
- - **Canonical representation**: Each style-player combination has exactly one SIN identifier
309
- - **Immutable**: All identifier instances are frozen and transformations return new objects
310
- - **Functional**: Pure functions with no side effects
183
+ ```ruby
184
+ # Side transformation
185
+ def flip # => Identifier
311
186
 
312
- ## Related Specifications
187
+ # Attribute changes
188
+ def with_style(style) # => Identifier
189
+ def with_side(side) # => Identifier
190
+ ```
313
191
 
314
- - [SIN Specification v1.0.0](https://sashite.dev/specs/sin/1.0.0/) - Complete technical specification
315
- - [SIN Examples](https://sashite.dev/specs/sin/1.0.0/examples/) - Practical implementation examples
316
- - [Style Name Notation (SNN)](https://sashite.dev/specs/snn/) - Formal naming for game styles
317
- - [Sashité Protocol](https://sashite.dev/protocol/) - Conceptual foundation for abstract strategy board games
192
+ ### Queries
318
193
 
319
- ## Documentation
194
+ ```ruby
195
+ # Side queries
196
+ def first_player? # => Boolean
197
+ def second_player? # => Boolean
320
198
 
321
- - [Official SIN Specification v1.0.0](https://sashite.dev/specs/sin/1.0.0/)
322
- - [SIN Examples Documentation](https://sashite.dev/specs/sin/1.0.0/examples/)
323
- - [API Documentation](https://rubydoc.info/github/sashite/sin.rb/main)
199
+ # Comparison queries
200
+ def same_style?(other) # => Boolean
201
+ def same_side?(other) # => Boolean
202
+ ```
324
203
 
325
- ## Development
204
+ ### Errors
326
205
 
327
- ```sh
328
- # Clone the repository
329
- git clone https://github.com/sashite/sin.rb.git
330
- cd sin.rb
206
+ All parsing and validation errors raise `ArgumentError` with descriptive messages:
331
207
 
332
- # Install dependencies
333
- bundle install
208
+ | Message | Cause |
209
+ |---------|-------|
210
+ | `"empty input"` | String length is 0 |
211
+ | `"input exceeds 1 character"` | String too long |
212
+ | `"must be a letter"` | Character is not A-Z or a-z |
334
213
 
335
- # Run tests
336
- ruby test.rb
214
+ ## Design Principles
337
215
 
338
- # Generate documentation
339
- yard doc
340
- ```
216
+ - **Bounded values**: Explicit validation of styles and sides
217
+ - **Object-oriented**: `Identifier` class enables methods and encapsulation
218
+ - **Ruby idioms**: `valid?` predicate, `to_s` conversion, `ArgumentError` for invalid input
219
+ - **Immutable identifiers**: All transformations return new objects
220
+ - **No dependencies**: Pure Ruby standard library only
341
221
 
342
- ## License
222
+ ## Related Specifications
343
223
 
344
- Available as open source under the [MIT License](https://opensource.org/licenses/MIT).
224
+ - [Game Protocol](https://sashite.dev/game-protocol/) — Conceptual foundation
225
+ - [SIN Specification](https://sashite.dev/specs/sin/1.0.0/) — Official specification
226
+ - [SIN Examples](https://sashite.dev/specs/sin/1.0.0/examples/) — Usage examples
345
227
 
346
- ## About
228
+ ## License
347
229
 
348
- Maintained by [Sashité](https://sashite.com/) — promoting chess variants and sharing the beauty of board game cultures.
230
+ Available as open source under the [Apache License 2.0](https://opensource.org/licenses/Apache-2.0).
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sashite
4
+ module Sin
5
+ # Constants for the SIN (Style Identifier Notation) specification.
6
+ #
7
+ # Defines valid values for styles and sides, as well as formatting constants.
8
+ #
9
+ # @example Accessing valid styles
10
+ # Constants::VALID_STYLES # => [:A, :B, ..., :Z]
11
+ #
12
+ # @example Accessing valid sides
13
+ # Constants::VALID_SIDES # => [:first, :second]
14
+ #
15
+ # @see https://sashite.dev/specs/sin/1.0.0/
16
+ module Constants
17
+ # Valid style symbols (A-Z as uppercase symbols).
18
+ #
19
+ # @return [Array<Symbol>] Array of 26 valid style symbols
20
+ VALID_STYLES = %i[A B C D E F G H I J K L M N O P Q R S T U V W X Y Z].freeze
21
+
22
+ # Valid side symbols.
23
+ #
24
+ # @return [Array<Symbol>] Array of valid side symbols
25
+ VALID_SIDES = %i[first second].freeze
26
+
27
+ # Maximum length of a valid SIN string.
28
+ #
29
+ # @return [Integer] Maximum string length (1)
30
+ MAX_STRING_LENGTH = 1
31
+
32
+ # Empty string constant for internal use.
33
+ #
34
+ # @return [String] Empty string
35
+ EMPTY_STRING = ""
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sashite
4
+ module Sin
5
+ module Errors
6
+ class Argument < ::ArgumentError
7
+ # Error messages for SIN parsing and validation.
8
+ #
9
+ # Provides centralized, immutable error message constants for consistent
10
+ # error reporting across the library.
11
+ #
12
+ # @example Using an error message
13
+ # raise ArgumentError, Messages::EMPTY_INPUT
14
+ #
15
+ # @see https://sashite.dev/specs/sin/1.0.0/
16
+ module Messages
17
+ # Error message for empty input string.
18
+ #
19
+ # @return [String] Error message
20
+ EMPTY_INPUT = "empty input"
21
+
22
+ # Error message for input exceeding maximum length.
23
+ #
24
+ # @return [String] Error message
25
+ INPUT_TOO_LONG = "input exceeds 1 character"
26
+
27
+ # Error message for invalid character (not a letter).
28
+ #
29
+ # @return [String] Error message
30
+ MUST_BE_LETTER = "must be a letter"
31
+
32
+ # Error message for invalid style value.
33
+ #
34
+ # @return [String] Error message
35
+ INVALID_STYLE = "invalid style"
36
+
37
+ # Error message for invalid side value.
38
+ #
39
+ # @return [String] Error message
40
+ INVALID_SIDE = "invalid side"
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "argument/messages"
4
+
5
+ module Sashite
6
+ module Sin
7
+ module Errors
8
+ # Namespace for ArgumentError-related constants and messages.
9
+ #
10
+ # Provides structured access to error messages used when raising
11
+ # ArgumentError exceptions throughout the library.
12
+ #
13
+ # @example Raising an error with a message
14
+ # raise ArgumentError, Argument::Messages::EMPTY_INPUT
15
+ #
16
+ # @see Argument::Messages
17
+ class Argument < ::ArgumentError
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "errors/argument"
4
+
5
+ module Sashite
6
+ module Sin
7
+ # Namespace for error-related constants and messages.
8
+ #
9
+ # Provides structured access to error messages used throughout the library.
10
+ #
11
+ # @example Accessing error messages
12
+ # Errors::Argument::Messages::EMPTY_INPUT # => "empty input"
13
+ #
14
+ # @see Errors::Argument
15
+ # @see Errors::Argument::Messages
16
+ module Errors
17
+ end
18
+ end
19
+ end