Module: AbideDevUtils::XCCDF::Parser::Objects::DigestObject
- Included in:
- ElementBase
- Defined in:
- lib/abide_dev_utils/xccdf/parser/objects/digest_object.rb
Overview
Methods for providing and comparing hash digests of objects
Instance Method Summary collapse
-
#digest ⇒ Object
Returns a SHA256 digest of the object, including the digests of all children.
-
#digest_equal?(other) ⇒ Boolean
Checks SHA256 digest equality.
-
#digest_similarity(other, only_labels: [], label_weights: {}) ⇒ Object
Compares two objects by their SHA256 digests and returns the degree to which they are similar as a percentage.
-
#digestable_instance_variables ⇒ Object
Returns a string of all instance variable values that are not nil, empty, or excluded.
-
#exclude_from_digest(exclude) ⇒ Object
Excludes instance variables that are not used in the digest.
-
#labeled_self_digest ⇒ Object
Returns a labeled digest of the current object.
-
#non_compatible?(digest_part, other_digest_part) ⇒ Boolean
If one of the digest parts is nil and the other is not, we can't compare.
-
#normalize_exclusion(exclude) ⇒ Object
Exclusions are instance variable symbols and must be prefixed with “@”.
- #sorted_digest_parts(dgst) ⇒ Object
-
#split_labeled_digest(digest_part) ⇒ Object
Splits a digest into a label and digest.
Instance Method Details
#digest ⇒ Object
Returns a SHA256 digest of the object, including the digests of all children
40 41 42 43 44 45 46 47 |
# File 'lib/abide_dev_utils/xccdf/parser/objects/digest_object.rb', line 40 def digest return @digest if defined?(@digest) parts = [labeled_self_digest] children.each { |child| parts << child.digest } unless children.empty? @digest = parts.join('|') @digest end |
#digest_equal?(other) ⇒ Boolean
Checks SHA256 digest equality
34 35 36 |
# File 'lib/abide_dev_utils/xccdf/parser/objects/digest_object.rb', line 34 def digest_equal?(other) digest == other.digest end |
#digest_similarity(other, only_labels: [], label_weights: {}) ⇒ Object
Compares two objects by their SHA256 digests and returns the degree to which they are similar as a percentage.
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/abide_dev_utils/xccdf/parser/objects/digest_object.rb', line 71 def digest_similarity(other, only_labels: [], label_weights: {}) digest_parts = sorted_digest_parts(digest) number_compared = 0 cumulative_similarity = 0.0 digest_parts.each do |digest_part| label, self_digest = split_labeled_digest(digest_part) next unless only_labels.empty? || only_labels.include?(label) label_weight = label_weights.key?(label) ? label_weights[label] : 1.0 sorted_digest_parts(other.digest).each do |other_digest_part| other_label, other_digest = split_labeled_digest(other_digest_part) next unless (label == other_label) && (self_digest == other_digest) number_compared += 1 cumulative_similarity += 1.0 * label_weight break # break when found end end cumulative_similarity / (number_compared.zero? ? 1.0 : number_compared) end |
#digestable_instance_variables ⇒ Object
Returns a string of all instance variable values that are not nil, empty, or excluded
57 58 59 60 61 62 63 64 65 66 |
# File 'lib/abide_dev_utils/xccdf/parser/objects/digest_object.rb', line 57 def digestable_instance_variables instance_vars = instance_variables.reject { |iv| @exclude_from_digest.include?(iv) }.sort_by!(&:to_s) return 'empty' if instance_vars.empty? var_vals = instance_vars.map { |iv| instance_variable_get(iv) } var_vals.reject! { |v| v.nil? || v.empty? } return 'empty' if var_vals.empty? var_vals.join end |
#exclude_from_digest(exclude) ⇒ Object
Excludes instance variables that are not used in the digest
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/abide_dev_utils/xccdf/parser/objects/digest_object.rb', line 10 def exclude_from_digest(exclude) unless exclude.is_a?(Array) || exclude.is_a?(Symbol) raise ArgumentError, 'exclude must be an Array or Symbol' end @exclude_from_digest ||= [] if exclude.is_a?(Array) exclude.map! do |e| normalize_exclusion(e) end @exclude_from_digest += exclude else @exclude_from_digest << normalize_exclusion(exclude) end @exclude_from_digest.uniq! end |
#labeled_self_digest ⇒ Object
Returns a labeled digest of the current object
50 51 52 53 54 |
# File 'lib/abide_dev_utils/xccdf/parser/objects/digest_object.rb', line 50 def labeled_self_digest return "#{label}:#{Digest::SHA256.hexdigest(digestable_instance_variables)}" if respond_to?(:label) "none:#{Digest::SHA256.hexdigest(digestable_instance_variables)}" end |
#non_compatible?(digest_part, other_digest_part) ⇒ Boolean
If one of the digest parts is nil and the other is not, we can't compare
102 103 104 |
# File 'lib/abide_dev_utils/xccdf/parser/objects/digest_object.rb', line 102 def non_compatible?(digest_part, other_digest_part) (digest_part.nil? || other_digest_part.nil?) && digest_part != other_digest_part end |
#normalize_exclusion(exclude) ⇒ Object
Exclusions are instance variable symbols and must be prefixed with “@”
28 29 30 31 |
# File 'lib/abide_dev_utils/xccdf/parser/objects/digest_object.rb', line 28 def normalize_exclusion(exclude) exclude = "@#{exclude}" unless exclude.to_s.start_with?('@') exclude.to_sym end |
#sorted_digest_parts(dgst) ⇒ Object
92 93 94 95 96 97 98 99 |
# File 'lib/abide_dev_utils/xccdf/parser/objects/digest_object.rb', line 92 def sorted_digest_parts(dgst) @sorted_digest_parts_cache = {} unless defined?(@sorted_digest_parts_cache) return @sorted_digest_parts_cache[dgst] if @sorted_digest_parts_cache.key?(dgst) @sorted_digest_parts_cache ||= {} @sorted_digest_parts_cache[dgst] = dgst.split('|').sort_by { |part| split_labeled_digest(part).first } @sorted_digest_parts_cache[dgst] end |
#split_labeled_digest(digest_part) ⇒ Object
Splits a digest into a label and digest
107 108 109 110 111 112 113 |
# File 'lib/abide_dev_utils/xccdf/parser/objects/digest_object.rb', line 107 def split_labeled_digest(digest_part) @labeled_digest_part_cache = {} unless defined?(@labeled_digest_part_cache) return @labeled_digest_part_cache[digest_part] if @labeled_digest_part_cache.key?(digest_part) @labeled_digest_part_cache[digest_part] = digest_part.split(':') @labeled_digest_part_cache[digest_part] end |