yara-ffi 3.1.0 → 4.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.
@@ -0,0 +1,224 @@
1
+ module Yara
2
+ # Public: Collection of ScanResult objects from YARA scanning operations.
3
+ #
4
+ # ScanResults acts as an enumerable container for individual rule matches,
5
+ # providing convenient methods for accessing and querying scan results. It
6
+ # supports standard collection operations and offers specialized methods for
7
+ # common YARA use cases like checking for any matches or extracting rule names.
8
+ #
9
+ # This class is typically returned by Scanner#scan when no block is provided,
10
+ # containing all rules that matched during the scanning operation.
11
+ #
12
+ # Examples
13
+ #
14
+ # results = scanner.scan(data)
15
+ #
16
+ # if results.matched?
17
+ # puts "Found #{results.size} matches"
18
+ # results.each { |match| puts match.rule_name }
19
+ # end
20
+ #
21
+ # rule_names = results.matching_rules
22
+ # first_match = results.first
23
+ class ScanResults
24
+ include Enumerable
25
+
26
+ # Public: Initialize a new ScanResults collection.
27
+ #
28
+ # Creates an empty results collection that can be populated with ScanResult
29
+ # objects. This is typically called internally by Scanner during scanning
30
+ # operations.
31
+ #
32
+ # results - An optional Array of ScanResult objects (default: empty array)
33
+ #
34
+ # Examples
35
+ #
36
+ # # Typically created internally by Scanner
37
+ # results = ScanResults.new
38
+ # results << scan_result
39
+ def initialize(results = [])
40
+ @results = results
41
+ end
42
+
43
+ # Public: Enumerate over all scan results.
44
+ #
45
+ # Implements the Enumerable interface, allowing standard collection methods
46
+ # like map, select, reject, etc. to be used on the results collection.
47
+ #
48
+ # block - Block that receives each ScanResult object
49
+ #
50
+ # Examples
51
+ #
52
+ # results.each { |result| puts result.rule_name }
53
+ # matched_names = results.map(&:rule_name)
54
+ # malware_results = results.select { |r| r.rule_meta[:category] == 'malware' }
55
+ #
56
+ # Returns an Enumerator when no block given, otherwise returns self.
57
+ def each(&block)
58
+ @results.each(&block)
59
+ end
60
+
61
+ # Public: Add a ScanResult to this collection.
62
+ #
63
+ # This method is used internally during scanning to accumulate matching
64
+ # rules. It appends the result to the internal results array.
65
+ #
66
+ # result - A ScanResult object to add to the collection
67
+ #
68
+ # Examples
69
+ #
70
+ # results = ScanResults.new
71
+ # results << ScanResult.new("MyRule", rule_ptr)
72
+ #
73
+ # Returns self for method chaining.
74
+ def <<(result)
75
+ @results << result
76
+ end
77
+
78
+ # Public: Get all scan results as an array.
79
+ #
80
+ # Returns the internal array of ScanResult objects. This method is provided
81
+ # for compatibility and direct access to the underlying collection.
82
+ #
83
+ # Examples
84
+ #
85
+ # all_results = results.matches
86
+ # puts "Found #{all_results.length} matches"
87
+ #
88
+ # Returns an Array of ScanResult objects.
89
+ def matches
90
+ @results
91
+ end
92
+
93
+ # Public: Extract the names of all matching rules.
94
+ #
95
+ # This convenience method returns just the rule names from all results,
96
+ # which is commonly needed for logging, reporting, or further processing
97
+ # of scan results.
98
+ #
99
+ # Examples
100
+ #
101
+ # rule_names = results.matching_rules
102
+ # puts "Matched: #{rule_names.join(', ')}"
103
+ #
104
+ # Returns an Array of String rule names.
105
+ def matching_rules
106
+ @results.map(&:rule_name)
107
+ end
108
+
109
+ # Public: Check if any rules matched during scanning.
110
+ #
111
+ # This is a convenience method to test whether the scan found any matches
112
+ # without needing to check the size or examine individual results.
113
+ #
114
+ # Examples
115
+ #
116
+ # if results.matched?
117
+ # puts "Scan found matches!"
118
+ # else
119
+ # puts "No matches found"
120
+ # end
121
+ #
122
+ # Returns true if there are any results, false otherwise.
123
+ def matched?
124
+ !@results.empty?
125
+ end
126
+
127
+ # Public: Alias for matched? method.
128
+ #
129
+ # Provides an alternative method name that may be more natural in some
130
+ # contexts, particularly when used in conditional expressions.
131
+ #
132
+ # Examples
133
+ #
134
+ # puts "Clean file" unless results.match?
135
+ #
136
+ # Returns true if there are any results, false otherwise.
137
+ alias_method :match?, :matched?
138
+
139
+ # Public: Get the number of matching rules.
140
+ #
141
+ # Returns the count of ScanResult objects in this collection, indicating
142
+ # how many rules matched during the scan operation.
143
+ #
144
+ # Examples
145
+ #
146
+ # puts "#{results.size} rules matched"
147
+ # alert_count = results.size
148
+ #
149
+ # Returns an Integer count of results.
150
+ def size
151
+ @results.size
152
+ end
153
+
154
+ # Public: Aliases for size method.
155
+ #
156
+ # These provide alternative method names for getting the collection size,
157
+ # maintaining compatibility with standard Ruby collection interfaces.
158
+ alias_method :length, :size
159
+ alias_method :count, :size
160
+
161
+ # Public: Get the first scan result.
162
+ #
163
+ # Returns the first ScanResult object in the collection, or nil if the
164
+ # collection is empty. Useful when you expect only one match or want to
165
+ # examine the first match found.
166
+ #
167
+ # Examples
168
+ #
169
+ # first_match = results.first
170
+ # puts first_match.rule_name if first_match
171
+ #
172
+ # Returns a ScanResult object or nil if collection is empty.
173
+ def first
174
+ @results.first
175
+ end
176
+
177
+ # Public: Get the last scan result.
178
+ #
179
+ # Returns the last ScanResult object in the collection, or nil if the
180
+ # collection is empty. The order depends on the sequence in which rules
181
+ # matched during scanning.
182
+ #
183
+ # Examples
184
+ #
185
+ # last_match = results.last
186
+ # puts "Final match: #{last_match.rule_name}" if last_match
187
+ #
188
+ # Returns a ScanResult object or nil if collection is empty.
189
+ def last
190
+ @results.last
191
+ end
192
+
193
+ # Public: Check if the results collection is empty.
194
+ #
195
+ # Returns true if no rules matched during scanning, false otherwise.
196
+ # This is the inverse of matched? and can be useful for control flow.
197
+ #
198
+ # Examples
199
+ #
200
+ # puts "No threats detected" if results.empty?
201
+ # process_results unless results.empty?
202
+ #
203
+ # Returns true if no results exist, false otherwise.
204
+ def empty?
205
+ @results.empty?
206
+ end
207
+
208
+ # Public: Convert results to a plain array.
209
+ #
210
+ # Returns a duplicate of the internal results array, allowing manipulation
211
+ # without affecting the original ScanResults object. This is useful when
212
+ # you need to work with the results as a standard Ruby array.
213
+ #
214
+ # Examples
215
+ #
216
+ # array_copy = results.to_a
217
+ # sorted_results = results.to_a.sort_by(&:rule_name)
218
+ #
219
+ # Returns a new Array containing all ScanResult objects.
220
+ def to_a
221
+ @results.dup
222
+ end
223
+ end
224
+ end