title: Using Elixir to talk to Rust via Ports, what am I getting wrong?
body: <p>I'm in the process of writing a tutorial, because I couldn't find a simple example anywhere, of communicating between Elixir and Rust via a Port.</p>
  
  <p>I can get Rustler to work, but that is a NIF, not a Port.</p>
  
  <p>I'm missing something fundamental in my code. I'm not sure if I'm missing something basic in stdio or if it's something else, but I've tried a lot of different things.</p>
  
  <p>I <em>can</em> get port communication to work with a very basic program in Rust:</p>
  
  <pre class="lang-rust prettyprint-override"><code>use std::env;
  
  fn main() {
      println!("hello world!");
  }
  </code></pre>
  
  <p>I can get this to get pulled into my iex -S mix by running this port:</p>
  
  <pre><code>defmodule PortExample do
  
    def test() do
      port = Port.open({:spawn_executable, "_build/dev/rustler_crates/portexample/debug/portexample"}, [:binary])
      Port.info(port)
      port
  end
  </code></pre>
  
  <p>Here's what the iex for that looks like: </p>
  
  <pre class="lang-none prettyprint-override"><code>Interactive Elixir (1.4.2) - press Ctrl+C to exit (type h() ENTER for help)
  iex(1)&gt; PortExample.test()
  #Port&lt;0.9420&gt;
  iex(2)&gt; flush()
  {#Port&lt;0.9420&gt;, {:data, "hello world!\n"}}
  :ok
  iex(3)&gt; 
  </code></pre>
  
  <p>I can do the same using a porcelain library call:</p>
  
  <pre><code>  alias Porcelain.Result
    def porcelain() do
      result = Porcelain.exec("_build/dev/rustler_crates/portexample/debug/portexample",["hello", "world"])
      IO.inspect result.out
    end
  </code></pre>
  
  <p>corresponding iex:</p>
  
  <pre class="lang-none prettyprint-override"><code>iex(3)&gt; PortExample.porcelain()
  "hello world!\n"
  "hello world!\n"
  iex(4)&gt; 
  </code></pre>
  
  <p>However, as soon as I start using a Rust library with some form of input/output, things start falling over.</p>
  
  <p>For example, Rust code:</p>
  
  <pre class="lang-rust prettyprint-override"><code>use std::io::{self, Write, Read};
  
  fn main() {
      let mut input = String::new();
      let mut output = String::new();
      for i in 0..2 {
          match io::stdin().read_line(&amp;mut input) {
              Ok(n) =&gt; {
                  println!("input: {}", input.trim());
                  io::stdout().flush();
              }
              Err(error) =&gt; println!("error: {}", error),
          }
      }
  }
  </code></pre>
  
  <p>I can get it to compile and run in the command line:</p>
  
  <pre class="lang-none prettyprint-override"><code>hello
  input: hello
  world
  input: hello
  world
  </code></pre>
  
  <p>However, when I call it from an Elixir port:</p>
  
  <pre class="lang-none prettyprint-override"><code>iex(12)&gt; port = PortExample.test()
  #Port&lt;0.8779&gt;
  iex(13)&gt; Port.command(port, "hello")
  true
  iex(14)&gt; Port.command(port, "world")
  true
  iex(15)&gt; Port.command(port, "!")    
  true
  iex(16)&gt; Port.command(port, "more")
  true
  iex(17)&gt; flush()
  :ok
  iex(18)&gt; Port.info(port)
  [name: '_build/dev/rustler_crates/portexample/debug/portexample',
   links: [#PID&lt;0.271.0&gt;], id: 4697, connected: #PID&lt;0.271.0&gt;, input: 0,
   output: 15, os_pid: 21523]
  </code></pre>
  
  <p>I get no data from it at all! However, the <code>Port.info(port)</code> call shows that its received 15 bytes. It just hasn't posted returned anything at all to the port. I've been trying to read other code and I thought I was doing things similar enough that it should work, but it doesn't.</p>
  
  <p>I thought: maybe the buffer isn't flushed? so I flush the buffer in Rust.
  I thought: maybe the loop is hanging, so I limited it to only a few passes.
  When I try to run this same code through the porcelain call, it hangs. </p>