Current section
Files
Jump to
Current section
Files
lib/memcache/serialization.ex
defmodule Memcache.Serialization do
alias Memcache.Serialization.Opcode
defmodule Header do
defstruct(
magic: 0,
opcode: 0,
key_length: 0,
extras_length: 0,
status: 0,
total_body_length: 0,
cas: 0
)
def length, do: 24
end
def encode_request(header, key, body \\ "", extras \\ "") do
%Header{opcode: opcode, cas: cas} = header
opcode = Opcode.to_byte(opcode)
key_length = byte_size(key)
extras_length = byte_size(extras)
total_body = <<extras::binary, key::binary, body::binary>>
total_body_length = byte_size(total_body)
<<0x80::size(8), opcode::size(8), key_length::size(16), extras_length::size(8), 0::size(8),
0::size(16), total_body_length::size(32), 0::size(32), cas::size(64), total_body::binary>>
end
def decode_response_header(
<<0x81::size(8), opcode::size(8), key_length::size(16), extras_length::size(8),
_data_type::size(8), status::size(16), total_body_length::size(32), _opaque::size(32),
cas::size(64)>>
) do
{:ok,
%Header{
magic: 0x81,
opcode: Opcode.to_atom(opcode),
key_length: key_length,
extras_length: extras_length,
status: status_atom(status),
total_body_length: total_body_length,
cas: cas
}}
end
def decode_response_header(_bytes), do: {:error, :invalid_header}
def decode_response_body(header, total_body) do
key_length = header.key_length
extras_length = header.extras_length
body_length = header.total_body_length - (key_length + extras_length)
<<extras::binary-size(extras_length), key::binary-size(key_length),
body::binary-size(body_length)>> = total_body
{:ok, key, body, extras}
end
# status
defp status_atom(0x00), do: :ok
defp status_atom(0x01), do: :key_not_found
defp status_atom(0x02), do: :key_exists
defp status_atom(0x03), do: :value_too_large
defp status_atom(0x04), do: :invalid_arguments
defp status_atom(0x05), do: :item_not_stored
defp status_atom(0x06), do: :incr_or_decr_on_non_numeric_value
defp status_atom(0x20), do: :auth_failure
defp status_atom(0x21), do: :auth_continue
defp status_atom(_), do: :unknown_status
end
defmodule Memcache.Serialization.Opcode do
def quiet?(opcode) do
opcode in [
:getq,
:getkq,
:setq,
:addq,
:replaceq,
:deleteq,
:incrementq,
:decrementq,
:quitq,
:flushq,
:appendq,
:prependq
]
end
def get?(opcode) do
opcode in [:get, :getq, :getk, :getkq]
end
def set?(opcode) do
opcode in [:set, :setq]
end
def to_quiet(:get), do: :getq
def to_quiet(:getk), do: :getkq
def to_quiet(:set), do: :setq
def to_quiet(:add), do: :addq
def to_quiet(:replace), do: :replaceq
def to_quiet(:delete), do: :deleteq
def to_quiet(:increment), do: :incrementq
def to_quiet(:decrement), do: :decrementq
def to_quiet(:quit), do: :quitq
def to_quiet(:flush), do: :flushq
def to_quiet(:append), do: :appendq
def to_quiet(:prepend), do: :prependq
def to_quiet(_), do: {:error, :not_quiet}
def to_byte(:get), do: 0x00
def to_byte(:set), do: 0x01
def to_byte(:add), do: 0x02
def to_byte(:replace), do: 0x03
def to_byte(:delete), do: 0x04
def to_byte(:increment), do: 0x05
def to_byte(:decrement), do: 0x06
def to_byte(:quit), do: 0x07
def to_byte(:flush), do: 0x08
def to_byte(:getq), do: 0x09
def to_byte(:noop), do: 0x0A
def to_byte(:version), do: 0x0B
def to_byte(:getk), do: 0x0C
def to_byte(:getkq), do: 0x0D
def to_byte(:append), do: 0x0E
def to_byte(:prepend), do: 0x0F
def to_byte(:stat), do: 0x10
def to_byte(:setq), do: 0x11
def to_byte(:addq), do: 0x12
def to_byte(:replaceq), do: 0x13
def to_byte(:deleteq), do: 0x14
def to_byte(:incrementq), do: 0x15
def to_byte(:decrementq), do: 0x16
def to_byte(:quitq), do: 0x17
def to_byte(:flushq), do: 0x18
def to_byte(:appendq), do: 0x19
def to_byte(:prependq), do: 0x1A
# SASL auth
def to_byte(:sasl_list_mechanisms), do: 0x20
def to_byte(:sasl_authenticate), do: 0x21
def to_byte(:sasl_step), do: 0x22
def to_atom(0x00), do: :get
def to_atom(0x01), do: :set
def to_atom(0x02), do: :add
def to_atom(0x03), do: :replace
def to_atom(0x04), do: :delete
def to_atom(0x05), do: :increment
def to_atom(0x06), do: :decrement
def to_atom(0x07), do: :quit
def to_atom(0x08), do: :flush
def to_atom(0x09), do: :getq
def to_atom(0x0A), do: :noop
def to_atom(0x0B), do: :version
def to_atom(0x0C), do: :getk
def to_atom(0x0D), do: :getkq
def to_atom(0x0E), do: :append
def to_atom(0x0F), do: :prepend
def to_atom(0x10), do: :stat
def to_atom(0x11), do: :setq
def to_atom(0x12), do: :addq
def to_atom(0x13), do: :replaceq
def to_atom(0x14), do: :deleteq
def to_atom(0x15), do: :incrementq
def to_atom(0x16), do: :decrementq
def to_atom(0x17), do: :quitq
def to_atom(0x18), do: :flushq
def to_atom(0x19), do: :appendq
def to_atom(0x1A), do: :prependq
# SASL auth
def to_atom(0x20), do: :sasl_list_mechanisms
def to_atom(0x21), do: :sasl_authenticate
def to_atom(0x22), do: :sasl_step
end