Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/lib/rex/transformer.rb
Views: 11766
# -*- coding: binary -*-1module Rex23###4#5# Transformer - more than meets the eye!6#7# This class, aside from having a kickass name, is responsible for translating8# object instances of one or more types into a single list instance of one or9# more types. This is useful for translating object instances that be can10# either strings or an array of strings into an array of strings, for11# instance. It lets you make things take a uniform structure in an abstract12# manner.13#14###15class Transformer1617#18# Translates the object instance supplied in src_instance to an instance of19# dst_class. The dst_class parameter's instance must support the <<20# operator. An example call to this method looks something like:21#22# Transformer.transform(string, Array, [ String ], target)23#24def Transformer.transform(src_instance, dst_class, supported_classes,25target = nil)26dst_instance = dst_class.new2728if (src_instance.kind_of?(Array))29src_instance.each { |src_inst|30Transformer.transform_single(src_inst, dst_instance,31supported_classes, target)32}33elsif (!src_instance.kind_of?(NilClass))34Transformer.transform_single(src_instance, dst_instance,35supported_classes, target)36end3738return dst_instance39end4041protected4243#44# Transform a single source instance.45#46def Transformer.transform_single(src_instance, dst_instance,47supported_classes, target)48# If the src instance's class is supported, just add it to the dst49# instance50if (supported_classes.include?(src_instance.class))51dst_instance << src_instance52# If the src instance's class is an array, then we should check to see53# if any of the supporting classes support from_a.54elsif (src_instance.kind_of?(Array))55new_src_instance = nil5657# Walk each supported class calling from_a if exported58supported_classes.each { |sup_class|59next if (sup_class.respond_to?('from_a') == false)6061new_src_instance = sup_class.from_a(src_instance)6263if (new_src_instance != nil)64dst_instance << new_src_instance65break66end67}6869# If we don't have a valid new src instance, then we suck70if (new_src_instance == nil)71bomb_translation(src_instance, target)72end7374# If the source instance is a string, query each of the supported75# classes to see if they can serialize it to their particular data76# type.77elsif (src_instance.kind_of?(String))78new_src_instance = nil7980# Walk each supported class calling from_s if exported81supported_classes.each { |sup_class|82next if (sup_class.respond_to?('from_s') == false)8384new_src_instance = sup_class.from_s(src_instance)8586if (new_src_instance != nil)87dst_instance << new_src_instance88break89end90}9192# If we don't have a valid new src instance, then we suck93if (new_src_instance == nil)94bomb_translation(src_instance, target)95end96# Otherwise, bomb translation97else98bomb_translation(src_instance, target)99end100end101102def Transformer.bomb_translation(src_instance, target) # :nodoc:103error = "Invalid source class (#{src_instance.class})"104105if (target != nil)106error += " for #{target}"107end108109raise ArgumentError, error, caller110end111112end113114end115116117118