/usr/lib/ruby/vendor_ruby/moneta/transformer.rb is in ruby-moneta 0.7.20-2.2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 | module Moneta
# Transforms keys and values (Marshal, YAML, JSON, Base64, MD5, ...).
# You can bypass the transformer (e.g. serialization) by using the `:raw` option.
#
# @example Add `Moneta::Transformer` to proxy stack
# Moneta.build do
# transformer :key => [:marshal, :escape], :value => [:marshal]
# adapter :File, :dir => 'data'
# end
#
# @example Bypass serialization
# store.store('key', 'value', :raw => true)
# store['key'] # raises an Exception
# store.load('key', :raw => true) # returns 'value'
#
# store['key'] = 'value'
# store.load('key', :raw => true) # returns "\x04\bI\"\nvalue\x06:\x06ET"
#
# @api public
class Transformer < Proxy
class << self
alias_method :original_new, :new
# @param [Moneta store] adapter The underlying store
# @param [Hash] options
# @return [Transformer] new Moneta transformer
# @option options [Array] :key List of key transformers in the order in which they should be applied
# @option options [Array] :value List of value transformers in the order in which they should be applied
# @option options [String] :prefix Prefix string for key namespacing (Used by the :prefix key transformer)
# @option options [String] :secret HMAC secret to verify values (Used by the :hmac value transformer)
# @option options [Integer] :maxlen Maximum key length (Used by the :truncate key transformer)
def new(adapter, options = {})
keys = [options[:key]].flatten.compact
values = [options[:value]].flatten.compact
raise ArgumentError, 'Option :key or :value is required' if keys.empty? && values.empty?
options[:prefix] ||= '' if keys.include?(:prefix)
name = class_name(keys, values)
const_set(name, compile(keys, values)) unless const_defined?(name)
const_get(name).original_new(adapter, options)
end
private
def compile(keys, values)
@key_validator ||= compile_validator(KEY_TRANSFORMER)
@value_validator ||= compile_validator(VALUE_TRANSFORMER)
raise ArgumentError, 'Invalid key transformer chain' if @key_validator !~ keys.map(&:inspect).join
raise ArgumentError, 'Invalid value transformer chain' if @value_validator !~ values.map(&:inspect).join
klass = Class.new(self)
klass.class_eval <<-end_eval, __FILE__, __LINE__
def initialize(adapter, options = {})
super
#{compile_initializer('key', keys)}
#{compile_initializer('value', values)}
end
end_eval
key, key_opts = compile_transformer(keys, 'key')
dump, dump_opts = compile_transformer(values, 'value')
load, load_opts = compile_transformer(values.reverse, 'value', 1)
if values.empty?
compile_key_transformer(klass, key, key_opts)
elsif keys.empty?
compile_value_transformer(klass, load, load_opts, dump, dump_opts)
else
compile_key_value_transformer(klass, key, key_opts, load, load_opts, dump, dump_opts)
end
klass
end
def without(*options)
options = options.flatten.uniq
options.empty? ? 'options' : "Utils.without(options, #{options.map(&:to_sym).map(&:inspect).join(', ')})"
end
def compile_key_transformer(klass, key, key_opts)
klass.class_eval <<-end_eval, __FILE__, __LINE__
def key?(key, options = {})
@adapter.key?(#{key}, #{without key_opts})
end
def increment(key, amount = 1, options = {})
@adapter.increment(#{key}, amount, #{without key_opts})
end
def load(key, options = {})
@adapter.load(#{key}, #{without :raw, key_opts})
end
def store(key, value, options = {})
@adapter.store(#{key}, value, #{without :raw, key_opts})
end
def delete(key, options = {})
@adapter.delete(#{key}, #{without :raw, key_opts})
end
def create(key, value, options = {})
@adapter.create(#{key}, value, #{without :raw, key_opts})
end
end_eval
end
def compile_value_transformer(klass, load, load_opts, dump, dump_opts)
klass.class_eval <<-end_eval, __FILE__, __LINE__
def load(key, options = {})
value = @adapter.load(key, #{without :raw, load_opts})
value && !options[:raw] ? #{load} : value
end
def store(key, value, options = {})
@adapter.store(key, options[:raw] ? value : #{dump}, #{without :raw, dump_opts})
value
end
def delete(key, options = {})
value = @adapter.delete(key, #{without :raw, load_opts})
value && !options[:raw] ? #{load} : value
end
def create(key, value, options = {})
@adapter.create(key, options[:raw] ? value : #{dump}, #{without :raw, dump_opts})
end
end_eval
end
def compile_key_value_transformer(klass, key, key_opts, load, load_opts, dump, dump_opts)
klass.class_eval <<-end_eval, __FILE__, __LINE__
def key?(key, options = {})
@adapter.key?(#{key}, #{without key_opts})
end
def increment(key, amount = 1, options = {})
@adapter.increment(#{key}, amount, #{without key_opts})
end
def load(key, options = {})
value = @adapter.load(#{key}, #{without :raw, key_opts, load_opts})
value && !options[:raw] ? #{load} : value
end
def store(key, value, options = {})
@adapter.store(#{key}, options[:raw] ? value : #{dump}, #{without :raw, key_opts, dump_opts})
value
end
def delete(key, options = {})
value = @adapter.delete(#{key}, #{without :raw, key_opts, load_opts})
value && !options[:raw] ? #{load} : value
end
def create(key, value, options = {})
@adapter.create(#{key}, options[:raw] ? value : #{dump}, #{without :raw, key_opts, dump_opts})
end
end_eval
end
# Compile option initializer
def compile_initializer(type, transformers)
transformers.map do |name|
t = TRANSFORMER[name]
(t[1].to_s + t[2].to_s).scan(/@\w+/).uniq.map do |opt|
"raise ArgumentError, \"Option #{opt[1..-1]} is required for #{name} #{type} transformer\" unless #{opt} = options[:#{opt[1..-1]}]\n"
end
end.join("\n")
end
def compile_validator(s)
Regexp.new('\A' + s.gsub(/\w+/) do
'(' + TRANSFORMER.select {|k,v| v.first.to_s == $& }.map {|v| ":#{v.first}" }.join('|') + ')'
end.gsub(/\s+/, '') + '\Z')
end
# Returned compiled transformer code string
def compile_transformer(transformer, var, i = 2)
value, options = var, []
transformer.each do |name|
raise ArgumentError, "Unknown transformer #{name}" unless t = TRANSFORMER[name]
require t[3] if t[3]
code = t[i]
options += code.scan(/options\[:(\w+)\]/).flatten
value =
if t[0] == :serialize && var == 'key'
"(tmp = #{value}; String === tmp ? tmp : #{code % 'tmp'})"
else
code % value
end
end
return value, options
end
def class_name(keys, values)
(keys.empty? ? '' : keys.map(&:to_s).map(&:capitalize).join + 'Key') +
(values.empty? ? '' : values.map(&:to_s).map(&:capitalize).join + 'Value')
end
end
end
end
require 'moneta/transformer/helper'
require 'moneta/transformer/config'
|