Skip to content

ricardohsd/ex_marshal

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

47 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ExMarshal Build Status

ExMarshal encodes and decodes Elixir terms according to Ruby Marshal format.

Currently supported Ruby types are nil, false, true, Fixnum, Bignum, BigDecimal, Float, Symbol, String, Array, Hash.

Why?

Once you decide to integrate small Elixir tool into big-old-legacy Ruby system, chances are that you need to interact with Memcached. As soon as Ruby code writes something into Memcached, most likely Ruby uses dalli gem. And Dalli uses Ruby Marshal by default.

Another use case is to decode Rails session encoded using Ruby Marshal. You can read more about it here.

Installation

Add ExMarshal as a dependency to your mix.exs file:

def deps do
  [{:ex_marshal, "0.0.4"}]
end

Usage

iex(1)> ExMarshal.decode(<<4, 8, 91, 8, 105, 6, 105, 7, 105, 8>>)
[1, 2, 3]
iex(2)> ExMarshal.encode([1, 2, 3])
<<4, 8, 91, 8, 105, 6, 105, 7, 105, 8>>
iex(3)>

ExMarshal with Memcache.Client

Of course it's possible to use ExMarshal on its own, but the main reason why ExMarshal was created is to work with Memcached. Here is how ExMarshal can be used with Memcache.Client:

defmodule Memcache.Client.Transcoder.Ruby do
  @behaviour Memcache.Client.Transcoder

  @ruby_type_flag 0x0001

  def encode_value(value) do
    {ExMarshal.encode(value), @ruby_type_flag}
  end

  def decode_value(value, @ruby_type_flag) do
    ExMarshal.decode(value)
  end

  def decode_value(_value, data_type) do
    {:error, {:invalid_data_type, data_type}}
  end
end

Then tell Memcache.Client to use this transcoder:

config :memcache_client,
  transcoder: Memcache.Client.Transcoder.Ruby

Examples

Read

Ruby side

:1 > dc = Dalli::Client.new('localhost:11211')
:2 > dc.set("str", "hello elixir")
 => true

Elixir side

iex(1)> Memcache.Client.get("str")
%Memcache.Client.Response{cas: 184, data_type: 1, extras: <<0, 0, 0, 1>>,
 key: "", status: :ok, value: "hello elixir"}

Write

Elixir side

iex(1)> Memcache.Client.set("str", "hello ruby")
%Memcache.Client.Response{cas: 185, data_type: nil, extras: "", key: "",
 status: :ok, value: ""}

Ruby side

:1 > dc = Dalli::Client.new('localhost:11211')
:2 > dc.get("str")
 => "hello ruby"

Kudos

Thanks to @tsharju for ability to use custom transcoders in Memcache.Client

Thanks to @shepmaster for series of posts about Ruby Marshal format.

Special thanks to @lexmag for help in writing this tool and for guiding me through Elixir world.

License

This software is licensed under the ISC license.

About

Ruby Marshal format implemented in Elixir

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Elixir 100.0%