class Readthis::Entity

An instance of the Entity class is used to handle `load` and `dump` operations on cached values.

Constants

COMPRESSED_FLAG

A hexidecimal compression flag. When it is present within the magic bit of an entity that entity is considered compressed.

DEFAULT_OPTIONS

Unless they are overridden, these are the options used to load and unload every value.

Public Class Methods

new(options = {}) click to toggle source

Creates a Readthis::Entity with default options. Each option can be overridden later when entities are being dumped.

Options are sticky, meaning that whatever is used when dumping will automatically be used again when loading, regardless of how current options are set.

@option [Boolean] :compress (false) Enable or disable automatic

compression

@option [Module] :marshal (Marshal) Any module that responds to `dump`

and `load`

@option [Number] :threshold (8k) The size a string must be for

compression
# File lib/readthis/entity.rb, line 35
def initialize(options = {})
  @options = DEFAULT_OPTIONS.merge(options)
end

Public Instance Methods

compose(value, marshal, compress) click to toggle source

Composes a single byte comprised of the chosen serializer and compression options. The byte is formatted as:

| 0000 | 0 | 000 |

Where there are four unused bits, 1 compression bit, and 3 bits for the serializer. This allows up to 8 different serializers for marshaling.

@param [String] value String to prefix with flags @param [Module] marshal The marshal module to be used @param [Boolean] compress Flag determining whether the value is compressed @return [String] The original string with a single byte prefixed

@example Compose an option embedded string

entity.compose(string, Marshal, false) => 0x1  + string
entity.compose(string, JSON, true) => 0x10 + string
# File lib/readthis/entity.rb, line 104
def compose(value, marshal, compress)
  flags = serializers.assoc(marshal)
  flags |= COMPRESSED_FLAG if compress

  value.prepend([flags].pack('C'))
end
decompose(string) click to toggle source

Decompose an option embedded string into marshal, compression and value.

@param [String] string Option embedded string to @return [Array<Module, Boolean, String>] An array comprised of the

marshal, compression flag, and the base string.
# File lib/readthis/entity.rb, line 117
def decompose(string)
  flags = string[0].unpack('C').first

  if flags < 16
    marshal = serializers.rassoc(flags)
    compress = (flags & COMPRESSED_FLAG) != 0

    [marshal, compress, string[1..-1]]
  else
    [@options[:marshal], @options[:compress], string]
  end
end
dump(value, options = {}) click to toggle source

Output a value prepared for cache storage. Passed options will override whatever has been specified for the instance.

@param [String] value String to dump @option options [Boolean] :compress Enable or disable automatic

compression

@option options [Module] :marshal Any module that responds to `dump` and

`load`

@option options [Number] :threshold The size a string must be for

compression

@return [String] The prepared, possibly compressed, string

@example Dumping a value using defaults

entity.dump(string)

@example Dumping a value with overrides

entity.dump(string, compress: false, marshal: JSON)
# File lib/readthis/entity.rb, line 59
def dump(value, options = {})
  compress = with_fallback(options, :compress)
  marshal = with_fallback(options, :marshal)
  threshold = with_fallback(options, :threshold)

  dumped = deflate(marshal.dump(value), compress, threshold)

  compose(dumped, marshal, compress)
end
load(string) click to toggle source

Parse a dumped value using the embedded options.

@param [String] string Option embedded string to load @return [String] The original dumped string, restored

@example

entity.load(dumped)
# File lib/readthis/entity.rb, line 78
def load(string)
  marshal, compress, value = decompose(string)

  marshal.load(inflate(value, compress))
rescue TypeError, NoMethodError
  string
end

Private Instance Methods

deflate(value, compress, threshold) click to toggle source
# File lib/readthis/entity.rb, line 132
def deflate(value, compress, threshold)
  if compress && value.bytesize >= threshold
    Zlib::Deflate.deflate(value)
  else
    value
  end
end
inflate(value, decompress) click to toggle source
# File lib/readthis/entity.rb, line 140
def inflate(value, decompress)
  if decompress
    Zlib::Inflate.inflate(value)
  else
    value
  end
rescue Zlib::Error
  value
end
serializers() click to toggle source
# File lib/readthis/entity.rb, line 150
def serializers
  Readthis.serializers
end
with_fallback(options, key) click to toggle source
# File lib/readthis/entity.rb, line 154
def with_fallback(options, key)
  options.key?(key) ? options[key] : @options[key]
end