module Bootsnap::CompileCache::YAML
def init!
def init! require('yaml') require('msgpack') # MessagePack serializes symbols as strings by default. # We want them to roundtrip cleanly, so we use a custom factory. # see: https://github.com/msgpack/msgpack-ruby/pull/122 factory = MessagePack::Factory.new factory.register_type(0x00, Symbol) self.msgpack_factory = factory self.supported_options = [] params = ::YAML.method(:load).parameters if params.include?([:key, :symbolize_names]) self.supported_options << :symbolize_names end if params.include?([:key, :freeze]) if factory.load(factory.dump('yaml'), freeze: true).frozen? self.supported_options << :freeze end end self.supported_options.freeze end
def input_to_output(data, kwargs)
def input_to_output(data, kwargs) ::YAML.load(data, **(kwargs || {})) end
def input_to_storage(contents, _, kwargs)
def input_to_storage(contents, _, kwargs) raise(Uncompilable) if contents.index("!ruby/object") obj = ::YAML.load(contents, **(kwargs || {})) msgpack_factory.dump(obj) rescue NoMethodError, RangeError # if the object included things that we can't serialize, fall back to # Marshal. It's a bit slower, but can encode anything yaml can. # NoMethodError is unexpected types; RangeError is Bignums Marshal.dump(obj) end
def install!(cache_dir)
def install!(cache_dir) self.cache_dir = cache_dir init! ::YAML.singleton_class.prepend(Patch) end
def storage_to_output(data, kwargs)
def storage_to_output(data, kwargs) # This could have a meaning in messagepack, and we're being a little lazy # about it. -- but a leading 0x04 would indicate the contents of the YAML # is a positive integer, which is rare, to say the least. if data[0] == 0x04.chr && data[1] == 0x08.chr Marshal.load(data) else msgpack_factory.load(data, **(kwargs || {})) end end