Módulo:Cache

Fonte: Dota 2 Wiki
Ir para: navegação, pesquisa

A documentação para este módulo pode ser criada na página Módulo:Cache/doc

--------------------------------------------------------------------------------
-- Imports
--------------------------------------------------------------------------------

local libraryUtil = require( 'libraryUtil' )
local var = require( 'Module:Variables' ).var
local vardefine = require( 'Module:Variables' ).vardefine

--------------------------------------------------------------------------------
-- Strings
--------------------------------------------------------------------------------

local i18n = {
  error = {
    unsupported_type = 'Unsupported data type'
  },
  log = {
    caching = 'No cached version found. Storing.'
  }
}

--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------

local h = {}

--- Generate a variable unique key.
-- @param args (table): The template/module arguments.
-- @param prefix (string): A unique prefix for the cached template/module.
-- @return (string): A unique key.
function h.make_key( args, prefix )
  prefix = ( prefix or 'cache' )
  local key = { prefix }
  for _,arg in pairs( args ) do
    key[#key+1] = tostring( arg )
  end
  local key = table.concat( key, '_' )
  return mw.hash.hashValue( 'md5', key )
end

--- Convert a value into a string for caching.
-- @param value (string/number/bool/table/nil): The value to be converted
-- @return (string): The converted value.
-- @return (string): The original type.
function h.preprocess( value )
  local value_type = type( value )
  
  if value_type == 'number' or value_type == 'boolean' then
    value = tostring( value )
  elseif value_type == 'table' then
    -- Check the table for a metatable to detect mw.html and similar objects.
    local mt = getmetatable( value )
    if mt and mt.__tostring then
      value = tostring( value )
      value_type = 'string'
    else
      value = mw.text.jsonEncode( value )
    end
  elseif value_type ~= 'string' then
    error( i18n.error.unsupported_type )
  end

  return value, value_type
end

--- Convert a string value back to its original type.
-- @param value (string): The string value.
-- @param value_type (string): The original type.
-- @return (string/number/bool/table/nil): The value in its original type.
function h.process( value, value_type )
  if value_type == 'string' then
    return value
  elseif value_type == 'number' then
    return tonumber( value )
  elseif value_type == 'boolean' then
    return ( value == 'true' )
  elseif value_type == 'table' then
    return mw.text.jsonDecode( value )
  elseif not value_type then
    return
  else
    error( i18n.error.unsupported_type )
  end
end

--- Write a value to the cache.
-- @param key (string): The key under which the value will be stored.
-- @param value (string/number/bool/table/nil): The value to store.
-- @return (string/number/bool/table/nil): The value.
function h.write( key, value )
  local processed_value, value_type = h.preprocess( value )
  vardefine( key, processed_value )
  vardefine( key .. '__type', value_type )
  return value
end

--- Read a value from the cache.
-- @param key (string): The key from which to retrieve the value.
-- @return (string/number/bool/table/nil): The original value.
function h.read( key )
  local value = var( key )
  local value_type = var( key .. '__type' )

  return h.process( value, value_type )
end

--------------------------------------------------------------------------------
-- Functions
--------------------------------------------------------------------------------

local p = {}

function p.auto( func, args, prefix )
  libraryUtil.checkType( 'auto', 1, func, 'function' )
  libraryUtil.checkType( 'auto', 2, args, 'table' )
  libraryUtil.checkType( 'auto', 3, prefix, 'string', true )

  local key = h.make_key( args, prefix )
  local cached = h.read( key )
  if cached then
    return cached
  else
    mw.log( i18n.log.caching )
    return h.write( key, func( args ) )
  end
end

function p.set( args, value, prefix )
  libraryUtil.checkType( 'set', 1, args, 'table' )
  libraryUtil.checkTypeMulti( 'set', 2, value, { 'boolean', 'string', 'number', 'table' } )
  libraryUtil.checkType( 'set', 3, prefix, 'string', true )

  local key = h.make_key( args, prefix )

  return h.write( key, value )
end

function p.get( args, prefix )
  libraryUtil.checkType( 'get', 2, args, 'table' )
  libraryUtil.checkType( 'get', 3, prefix, 'string', true )

  local key = h.make_key( args, prefix )

  return h.read( key )
end

function p.key( args, prefix )
  return h.make_key( args, prefix )
end

--------------------------------------------------------------------------------
-- Return
--------------------------------------------------------------------------------

return p