taurus 0.1.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.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +8 -0
  4. data/CHANGELOG.md +518 -0
  5. data/CLAUDE.md +104 -0
  6. data/LICENSE.md +33 -0
  7. data/README.adoc +1529 -0
  8. data/Rakefile +7 -0
  9. data/TODO.impl/01-architecture.md +217 -0
  10. data/TODO.impl/02-ffi-declarations.md +236 -0
  11. data/TODO.impl/03-document-node-element-nodeset.md +382 -0
  12. data/TODO.impl/04-sax-parser.md +203 -0
  13. data/TODO.impl/05-serialize-c14n-memory-specs-css.md +276 -0
  14. data/benchmark/README.md +168 -0
  15. data/benchmark/taurus_vs_nokogiri.rb +105 -0
  16. data/docs/ARCHITECTURE.adoc +559 -0
  17. data/docs/BUILD.md +395 -0
  18. data/docs/ERROR_MESSAGES.md +458 -0
  19. data/docs/FFI_ARCHITECTURE.md +439 -0
  20. data/docs/FUTURE_VISION.md +303 -0
  21. data/docs/GITHUB_ACTIONS.md +293 -0
  22. data/docs/OPTIMIZATIONS_IMPLEMENTED.adoc +459 -0
  23. data/docs/PERFORMANCE.adoc +668 -0
  24. data/docs/PERFORMANCE.md +448 -0
  25. data/docs/RELEASE_NOTES_v1.0.0.md +515 -0
  26. data/docs/XPATH_SPEC_COMPLIANCE.md +298 -0
  27. data/docs/completion/taurus.bash +86 -0
  28. data/docs/completion/taurus.zsh +74 -0
  29. data/docs/man/taurus-format.1 +227 -0
  30. data/docs/man/taurus-parse.1 +178 -0
  31. data/docs/man/taurus-xpath.1 +312 -0
  32. data/docs/man/taurus.1 +160 -0
  33. data/docs/v0.9.0_PERFORMANCE_IMPROVEMENTS.md +217 -0
  34. data/docs/v0.9.0_RELEASE_SUMMARY.md +281 -0
  35. data/docs/v1.0.0_CONTINUATION_PLAN.md +172 -0
  36. data/docs/v1.0.0_CONTINUATION_PROMPT.md +382 -0
  37. data/docs/v1.0.0_SESSION_6_CONTINUATION.md +434 -0
  38. data/docs/v1.0.0_SESSION_6_PROMPT.md +231 -0
  39. data/docs/v1.0.0_STATUS_TRACKER.md +224 -0
  40. data/docs/v1.1.0_CONTINUATION_PLAN.md +299 -0
  41. data/docs/v1.1.0_FINAL_CONTINUATION_PLAN.md +201 -0
  42. data/docs/v1.1.0_SESSION_3_PROMPT.md +223 -0
  43. data/docs/v1.1.0_STATUS_TRACKER.md +355 -0
  44. data/docs/xml-performance.adoc +115 -0
  45. data/docs/xpath-performance.adoc +379 -0
  46. data/lib/taurus/version.rb +5 -0
  47. data/lib/taurus/xml/attr.rb +43 -0
  48. data/lib/taurus/xml/c14n.rb +23 -0
  49. data/lib/taurus/xml/cdata.rb +16 -0
  50. data/lib/taurus/xml/comment.rb +16 -0
  51. data/lib/taurus/xml/css_to_xpath.rb +177 -0
  52. data/lib/taurus/xml/doc_type.rb +54 -0
  53. data/lib/taurus/xml/document.rb +202 -0
  54. data/lib/taurus/xml/document_fragment.rb +42 -0
  55. data/lib/taurus/xml/element.rb +278 -0
  56. data/lib/taurus/xml/ffi.rb +420 -0
  57. data/lib/taurus/xml/namespace.rb +43 -0
  58. data/lib/taurus/xml/node.rb +221 -0
  59. data/lib/taurus/xml/node_set.rb +143 -0
  60. data/lib/taurus/xml/parse_options.rb +19 -0
  61. data/lib/taurus/xml/processing_instruction.rb +26 -0
  62. data/lib/taurus/xml/sax/document.rb +45 -0
  63. data/lib/taurus/xml/sax/parser.rb +148 -0
  64. data/lib/taurus/xml/sax.rb +12 -0
  65. data/lib/taurus/xml/searchable.rb +93 -0
  66. data/lib/taurus/xml/text.rb +16 -0
  67. data/lib/taurus/xml.rb +29 -0
  68. data/lib/taurus.rb +7 -0
  69. data/taurus.gemspec +42 -0
  70. metadata +157 -0
@@ -0,0 +1,458 @@
1
+ # Taurus Error Message Catalog
2
+
3
+ This document provides a comprehensive reference for all error types, codes, causes, and solutions in Taurus.
4
+
5
+ ## Error Types Overview
6
+
7
+ Taurus provides three main error types:
8
+
9
+ | Error Type | Purpose | Common Codes |
10
+ |------------|---------|--------------|
11
+ | `Taurus::ParseError` | XML parsing failures | `:parse_failed`, `:unclosed_tag`, `:empty_input` |
12
+ | `Taurus::XPathError` | XPath syntax and evaluation errors | `:xpath_syntax`, `:xpath_function` |
13
+ | `Taurus::EvaluationError` | Runtime evaluation issues | `:xpath_evaluation`, `:xpath_type_error` |
14
+
15
+ All errors inherit from `StandardError` and provide comprehensive diagnostic information.
16
+
17
+ ## Parse Errors
18
+
19
+ ### EMPTY_INPUT
20
+
21
+ **Code**: `:empty_input`
22
+
23
+ **Cause**: Empty string passed to `Taurus.parse()`
24
+
25
+ **Example**:
26
+ ```ruby
27
+ Taurus.parse('')
28
+ # => Taurus::ParseError: Empty input provided
29
+ # code: :empty_input
30
+ ```
31
+
32
+ **Solution**: Provide valid XML content. Check your data source before parsing.
33
+
34
+ **Common Scenarios**:
35
+ - Reading from empty file
36
+ - Network request returned empty body
37
+ - User input was blank
38
+
39
+ ---
40
+
41
+ ### NULL_INPUT
42
+
43
+ **Code**: `:null_input`
44
+
45
+ **Cause**: NULL (nil) value passed to parser
46
+
47
+ **Example**:
48
+ ```ruby
49
+ Taurus.parse(nil)
50
+ # => Taurus::ParseError: NULL input provided
51
+ # code: :null_input
52
+ ```
53
+
54
+ **Solution**: Ensure input is a valid string. Add nil checks before parsing.
55
+
56
+ ```ruby
57
+ # Good practice
58
+ xml = fetch_xml_data()
59
+ doc = Taurus.parse(xml) if xml && !xml.empty?
60
+ ```
61
+
62
+ ---
63
+
64
+ ### PARSE_FAILED
65
+
66
+ **Code**: `:parse_failed`
67
+
68
+ **Cause**: Malformed XML structure
69
+
70
+ **Examples**:
71
+ ```ruby
72
+ # Missing closing bracket
73
+ Taurus.parse('<root')
74
+ # => ParseError: Expected '>' at line 1, column 6
75
+
76
+ # Invalid tag name
77
+ Taurus.parse('<123invalid>')
78
+ # => ParseError: Invalid tag name at line 1, column 2
79
+
80
+ # Malformed attribute
81
+ Taurus.parse('<root attr=value>')
82
+ # => ParseError: Expected quoted attribute value
83
+ ```
84
+
85
+ **Solution**: Validate XML syntax. Use XML schema validation if available.
86
+
87
+ **Common Issues**:
88
+ - Missing `>` or `<` characters
89
+ - Invalid characters in tag names
90
+ - Unquoted attribute values
91
+ - Incorrectly nested elements
92
+
93
+ **Related Documentation**: [XML 1.0 Specification](https://www.w3.org/TR/xml/)
94
+
95
+ ---
96
+
97
+ ### UNCLOSED_TAG
98
+
99
+ **Code**: `:unclosed_tag`
100
+
101
+ **Cause**: XML element not properly closed
102
+
103
+ **Examples**:
104
+ ```ruby
105
+ # Missing closing tag
106
+ Taurus.parse('<root><item></root>')
107
+ # => ParseError: Unclosed tag 'item' at line 1, column 7
108
+ # Context:
109
+ # <root><item></root>
110
+ # ^
111
+
112
+ # Mismatched tags
113
+ Taurus.parse('<root><item></items></root>')
114
+ # => ParseError: Mismatched closing tag at line 1, column 13
115
+ ```
116
+
117
+ **Solution**: Ensure all opening tags have matching closing tags.
118
+
119
+ **Best Practices**:
120
+ - Use self-closing tags where appropriate: `<item/>`
121
+ - Maintain proper nesting hierarchy
122
+ - Use XML validators during development
123
+
124
+ ---
125
+
126
+ ## XPath Errors
127
+
128
+ ### XPATH_SYNTAX
129
+
130
+ **Code**: `:xpath_syntax`
131
+
132
+ **Cause**: Invalid XPath expression syntax
133
+
134
+ **Examples**:
135
+
136
+ **Unclosed Predicate**:
137
+ ```ruby
138
+ doc.xpath('//item[')
139
+ # => XPathError: Unexpected token in primary expression: EOF
140
+ # Line: 1, Column: 8
141
+ # Context:
142
+ # //item[
143
+ # ^
144
+ ```
145
+
146
+ **Missing Attribute Name**:
147
+ ```ruby
148
+ doc.xpath('//item/@')
149
+ # => XPathError: Expected attribute name after '@'
150
+ # Line: 1, Column: 9
151
+ ```
152
+
153
+ **Invalid Function Syntax**:
154
+ ```ruby
155
+ doc.xpath('count(//item')
156
+ # => XPathError: Unclosed function call
157
+ # Line: 1, Column: 14
158
+ ```
159
+
160
+ **Solution**: Check XPath syntax against XPath 1.0 specification.
161
+
162
+ **Common Mistakes**:
163
+ - Forgetting to close brackets `[...]`
164
+ - Missing parentheses in function calls
165
+ - Invalid operator usage
166
+ - Incomplete attribute references
167
+
168
+ **Related Documentation**: [XPath 1.0 Specification](https://www.w3.org/TR/xpath/)
169
+
170
+ ---
171
+
172
+ ### XPATH_FUNCTION
173
+
174
+ **Code**: `:xpath_function`
175
+
176
+ **Cause**: Unknown function name or invalid function arguments
177
+
178
+ **Examples**:
179
+
180
+ **Unknown Function**:
181
+ ```ruby
182
+ doc.xpath('unknown_func()')
183
+ # => XPathError: Unknown function 'unknown_func' at line 1, column 1
184
+ # Suggestion: Did you mean count(), concat(), or contains()?
185
+ ```
186
+
187
+ **Wrong Number of Arguments**:
188
+ ```ruby
189
+ doc.xpath('concat("a")')
190
+ # => XPathError: Function 'concat' requires at least 2 arguments, got 1
191
+ # Line: 1, Column: 1
192
+
193
+ doc.xpath('ceiling(1, 2)')
194
+ # => XPathError: Function 'ceiling' accepts 1 argument, got 2
195
+ ```
196
+
197
+ **Solution**: Use only XPath 1.0 standard functions with correct arguments.
198
+
199
+ **XPath 1.0 Functions** (all 27 supported):
200
+
201
+ **String Functions**:
202
+ - `string(object?)` - Convert to string
203
+ - `concat(string, string, ...)` - Concatenate (2+ args)
204
+ - `starts-with(string, string)` - Prefix test
205
+ - `contains(string, string)` - Substring test
206
+ - `substring(string, number, number?)` - Extract substring
207
+ - `string-length(string?)` - String length
208
+ - `normalize-space(string?)` - Normalize whitespace
209
+ - `translate(string, string, string)` - Character translation
210
+ - `substring-before(string, string)` - Before delimiter
211
+ - `substring-after(string, string)` - After delimiter
212
+
213
+ **Boolean Functions**:
214
+ - `boolean(object)` - Convert to boolean
215
+ - `not(boolean)` - Logical NOT
216
+ - `true()` - Boolean true
217
+ - `false()` - Boolean false
218
+ - `lang(string)` - Language matching
219
+
220
+ **Number Functions**:
221
+ - `number(object?)` - Convert to number
222
+ - `sum(node-set)` - Sum node values
223
+ - `floor(number)` - Round down
224
+ - `ceiling(number)` - Round up
225
+ - `round(number)` - Round to nearest
226
+
227
+ **Node-set Functions**:
228
+ - `count(node-set)` - Count nodes
229
+ - `id(object)` - Select by ID
230
+ - `last()` - Context size
231
+ - `position()` - Context position (1-based)
232
+ - `local-name(node-set?)` - Local name
233
+ - `namespace-uri(node-set?)` - Namespace URI
234
+ - `name(node-set?)` - Qualified name
235
+
236
+ ---
237
+
238
+ ### XPATH_EVALUATION
239
+
240
+ **Code**: `:xpath_evaluation`
241
+
242
+ **Cause**: Runtime evaluation error (not a syntax error)
243
+
244
+ **Examples**:
245
+
246
+ **Type Conversion Error**:
247
+ ```ruby
248
+ doc.xpath('count("not-a-nodeset")')
249
+ # => XPathError: Function 'count' requires node-set argument
250
+ ```
251
+
252
+ **Division by Zero**:
253
+ ```ruby
254
+ doc.xpath('1 div 0')
255
+ # => XPathError: Division by zero in arithmetic expression
256
+ ```
257
+
258
+ **Solution**: Ensure operands are correct types and operations are valid.
259
+
260
+ **Common Runtime Errors**:
261
+ - Type mismatches in function arguments
262
+ - Invalid arithmetic operations
263
+ - NULL reference errors
264
+ - Out-of-range numeric operations
265
+
266
+ ---
267
+
268
+ ## Error Attributes Reference
269
+
270
+ All error objects provide these attributes:
271
+
272
+ ### message
273
+ **Type**: String
274
+ **Description**: Human-readable error description
275
+
276
+ Example:
277
+ ```ruby
278
+ rescue Taurus::ParseError => e
279
+ puts e.message
280
+ # => "Failed to parse root element at line 1, column 1"
281
+ end
282
+ ```
283
+
284
+ ### code
285
+ **Type**: Symbol
286
+ **Description**: Machine-readable error code
287
+
288
+ Example:
289
+ ```ruby
290
+ rescue Taurus::XPathError => e
291
+ case e.code
292
+ when :xpath_syntax
293
+ # Handle syntax errors
294
+ when :xpath_function
295
+ # Handle function errors
296
+ end
297
+ end
298
+ ```
299
+
300
+ ### line
301
+ **Type**: Integer (1-based)
302
+ **Description**: Line number where error occurred
303
+
304
+ ### column
305
+ **Type**: Integer (1-based)
306
+ **Description**: Column number where error occurred
307
+
308
+ ### byte_offset
309
+ **Type**: Integer (0-based)
310
+ **Description**: Byte offset in input string
311
+
312
+ ### context
313
+ **Type**: String
314
+ **Description**: Code snippet showing error location with `^` marker
315
+
316
+ Example:
317
+ ```ruby
318
+ rescue Taurus::XPathError => e
319
+ puts e.context
320
+ # => //book[@id = invalid]
321
+ # ^
322
+ end
323
+ ```
324
+
325
+ ## Error Handling Patterns
326
+
327
+ ### Pattern 1: Defensive Parsing
328
+
329
+ ```ruby
330
+ def safe_parse(xml)
331
+ return nil if xml.nil? || xml.empty?
332
+
333
+ Taurus.parse(xml)
334
+ rescue Taurus::ParseError => e
335
+ logger.error("XML parse failed: #{e.message}")
336
+ logger.debug("Error code: #{e.code}")
337
+ logger.debug("Location: #{e.line}:#{e.column}")
338
+ nil
339
+ end
340
+ ```
341
+
342
+ ### Pattern 2: XPath Validation
343
+
344
+ ```ruby
345
+ def validate_xpath(expression)
346
+ # Try to parse (without document context)
347
+ Taurus::XPath.parse(expression)
348
+ true
349
+ rescue Taurus::XPathError => e
350
+ warn "Invalid XPath: #{e.message}"
351
+ warn "At: #{e.line}:#{e.column}"
352
+ false
353
+ end
354
+ ```
355
+
356
+ ### Pattern 3: User-Friendly Error Messages
357
+
358
+ ```ruby
359
+ def execute_query(doc, xpath)
360
+ doc.xpath(xpath)
361
+ rescue Taurus::XPathError => e
362
+ case e.code
363
+ when :xpath_syntax
364
+ "XPath syntax error at position #{e.column}: #{e.message}"
365
+ when :xpath_function
366
+ "Unknown or invalid function: #{e.message}"
367
+ else
368
+ "XPath error: #{e.message}"
369
+ end
370
+ end
371
+ ```
372
+
373
+ ### Pattern 4: Comprehensive Logging
374
+
375
+ ```ruby
376
+ def parse_with_logging(xml, source_name)
377
+ logger.info("Parsing XML from: #{source_name}")
378
+ Taurus.parse(xml)
379
+ rescue Taurus::ParseError => e
380
+ logger.error("Parse failed for #{source_name}")
381
+ logger.error(" Message: #{e.message}")
382
+ logger.error(" Code: #{e.code}")
383
+ logger.error(" Location: line #{e.line}, column #{e.column}")
384
+ logger.error(" Byte offset: #{e.byte_offset}")
385
+ logger.debug(" Context:\n#{e.context}")
386
+ raise
387
+ end
388
+ ```
389
+
390
+ ## Troubleshooting Guide
391
+
392
+ ### "Empty input provided"
393
+
394
+ **Problem**: Trying to parse empty XML
395
+ **Check**:
396
+ - Is your XML source returning data?
397
+ - Are you reading from the correct file/URL?
398
+ - Is the network request succeeding?
399
+
400
+ ### "Unclosed tag"
401
+
402
+ **Problem**: Missing closing tag in XML
403
+ **Check**:
404
+ - Count opening vs closing tags
405
+ - Look for self-closing tags that should be regular tags
406
+ - Check nesting hierarchy
407
+
408
+ ### "Unknown function"
409
+
410
+ **Problem**: Using non-XPath 1.0 function
411
+ **Check**:
412
+ - Is the function name spelled correctly?
413
+ - Is this an XPath 2.0/3.0 function? (not supported yet)
414
+ - See list of 27 supported functions above
415
+
416
+ ### "Unexpected token"
417
+
418
+ **Problem**: Syntax error in XPath
419
+ **Check**:
420
+ - Are all brackets balanced? `[...]`, `(...)`, `{...}`
421
+ - Are strings properly quoted? `'...'` or `"..."`
422
+ - Are operators used correctly? `=`, `!=`, `<`, `>`, etc.
423
+
424
+ ## Performance Considerations
425
+
426
+ ### Error Context Generation
427
+
428
+ Error context generation is optimized but has minimal overhead:
429
+
430
+ **Cost**: ~1-2µs per error (only when error occurs)
431
+ **Impact**: Zero impact on success path
432
+ **Memory**: Temporary allocation, immediately freed
433
+
434
+ ### Best Practices
435
+
436
+ 1. **Validate early**: Check input before processing
437
+ 2. **Cache expressions**: Parse XPath once, reuse
438
+ 3. **Handle at boundaries**: Catch errors at API boundaries
439
+ 4. **Log strategically**: Full details to logs, user-friendly to UI
440
+
441
+ ## Related Documentation
442
+
443
+ - [XPath 1.0 Specification](https://www.w3.org/TR/xpath/)
444
+ - [XML 1.0 Specification](https://www.w3.org/TR/xml/)
445
+ - [Taurus README](../README.adoc) - Main documentation
446
+ - [XPath Spec Compliance](XPATH_SPEC_COMPLIANCE.md) - Feature matrix
447
+
448
+ ## Version History
449
+
450
+ **v1.0.0** (2024-12-07):
451
+ - Initial comprehensive error handling
452
+ - All error codes documented
453
+ - Context snippets with position markers
454
+ - "Did you mean?" suggestions for functions
455
+
456
+ ---
457
+
458
+ *For implementation details, see `lib/src/error.c` and `lib/taurus/ffi/errors.rb`*