Tuesday, 26 May 2015

Rust: print the program arguments

A simple example using Cargo in Rust 1.0 on Linux.

Install Rust if you haven't. Create a project:

$ cargo new hello --bin

This will create the files:

hello/Cargo.toml
hello/src/main.rs

Replace the contents of main.rs with:

use std::env;

fn main() {
  for argument in env::args() {
    println!("Hello, {}!", argument);
  }
}

From the hello directory run:

$ cargo run World Kitty "to my little friend, Al Pacino"
     Running `target/debug/hello World Kitty to my little friend, Al Pacino`
Hello, target/debug/hello!
Hello, World!
Hello, Kitty!
Hello, to my little friend, Al Pacino!

Rust provides the executable as the zeroth argument target/debug/hello. The arguments passed to the application start at index 1.

Monday, 25 May 2015

Blog: Google Code shutting down; code moved to GitHub

Many previous posts link to https://code.google.com/p/illegalargumentexception/ but this resource is going away:

Hello,

Earlier today, Google announced we will be turning down Google Code Project Hosting. The service started in 2006 with the goal of providing a scalable and reliable way of hosting open source projects. Since that time, millions of people have contributed to open source projects hosted on the site.

But a lot has changed since 2006. In the past nine years, many other options for hosting open source projects have popped up, along with vibrant communities of developers. It’s time to recognize that Google Code’s mission to provide open source projects a home has been accomplished by others, such as GitHub and Bitbucket.

We will be shutting down Google Code over the coming months. Starting today, the site will no longer accept new projects, but will remain functionally unchanged until August 2015. After that, project data will be read-only. Early next year, the site will shut down, but project data will be available for download in an archive format.

etc...

The contents of the old SVN repository have been moved to https://github.com/mcdiae/iae.

Links have not been changed at this time.

Friday, 15 May 2015

Rust: is ready to roll (1.0.0 released)

$ sudo ./install.sh 
install: creating uninstall script at /usr/local/lib/rustlib/uninstall.sh
install: installing component 'rustc'
install: installing component 'cargo'
install: installing component 'rust-docs'

    Rust is ready to roll.

$ rustc --version
rustc 1.0.0 (a59de37e9 2015-05-13) (built 2015-05-14)

Rust has been released. The sample 1.0.0-beta.4 code in previous posts still passes cargo clean and cargo test.

Wednesday, 13 May 2015

Rust: send and receive on localhost with UDP

UDP it is the simple cousin of TCP. You send a message off into the ether, you might listen a period of time for a response, and the payloads are small enough to fit in a packet.

This post looks at sending and receiving packets in Rust.

Rust: start thread & return value on finish

Rust threads are relatively easy to spawn and pass results back from.

use std::thread;

pub fn add_in_future(i1: i32, i2: i32) -> i32 {
  let handle = thread::spawn(move || {
    i1 + i2
  });
  handle.join().unwrap()
}

#[cfg(test)]
mod test {
  use super::*;

  #[test]
  fn test_future() {
    let expected = 3;
    let actual = add_in_future(1, 2);
    assert_eq!(expected, actual);
  }
}

The add_in_future function sums two numbers in a separate thread. Then the originating thread consumes the result. The move keyword moves ownership of variables to the new thread.

This post is just a code snippet written by someone getting started. No promises are made about code quality. Version: rustc 1.0.0-beta.4 (850151a75 2015-04-30) (built 2015-04-30)

Rust: serializing structs to bytes

Back when I wrote C code for platform-dependent binary formats it was fairly common to perform stream I/O with structs and unions. This post looks at similar functionality in Rust.

use std::mem;

#[allow(dead_code)]
pub struct Ser {
  prop: u32
}

pub fn to_bytes(ser: Ser) -> [u8; 4] {
  unsafe { mem::transmute_copy::<Ser, [u8; 4]>(&ser) }
}

#[cfg(test)]
mod test {
  use super::*;

  #[test]
  fn test_to_bytes() {
    let instance = Ser { prop: 0x0A0B0C0D };
    let bigend = Ser { prop: instance.prop.to_be() };
    let actual = to_bytes(bigend);
    let expected: [u8; 4] = [0xA, 0xB, 0xC, 0xD];
    assert_eq!(expected, actual);
  }
}

Rust: the size of a struct

This code determines the size of a data structure in byte terms.

use std::mem;

#[allow(dead_code)]
pub struct AStruct {
  prop: u32
}

pub fn size_of_a_struct() -> usize {
  mem::size_of::<AStruct>()
}

#[cfg(test)]
mod test {
  use super::*;

  #[test]
  fn test_size() {
    let expected = 4 as usize;
    assert_eq!(expected, size_of_a_struct());
  }
}

Rust provides the size_of function to determine the size of a type.

This post is just a code snippet written by someone getting started. No promises are made about code quality. Version: rustc 1.0.0-beta.4 (850151a75 2015-04-30) (built 2015-04-30)

Rust: byte array to hex String

This code allows you to express arbitrary octet sequences as hex.

pub fn to_hex_string(bytes: Vec<u8>) -> String {
  let strs: Vec<String> = bytes.iter()
                               .map(|b| format!("{:02X}", b))
                               .collect();
  strs.connect(" ")
}

#[cfg(test)]
mod test {
  use super::*;

  #[test]
  fn test_to_hex_string() {
    let bytes: Vec<u8> = vec![0xFF, 0, 0xAA];
    let actual = to_hex_string(bytes);
    assert_eq!("FF 00 AA", actual);
  }
}

This function turns a byte vector into a space-delimited hex string using an iterator to map the values.

This post is just a code snippet written by someone getting started. No promises are made about code quality. Version: rustc 1.0.0-beta.4 (850151a75 2015-04-30) (built 2015-04-30)

Rust: network byte order

Languages on different architectures might serialize the 32-bit unsigned int 15 as the byte sequences 00 00 00 0F (big-endian) or 0F 00 00 00 (little-endian) but network protocols generally prefer the former.

pub fn to_network_byte_order(n: u32) -> u32 {
  n.to_be()
}

pub fn from_network_byte_order(n: u32) -> u32 {
  u32::from_be(n)
}

#[cfg(test)]
mod test {
  use super::*;

  #[test]
  fn test_to_network_byte_order() {
    let expected: u32 = 0xFFAABBCC;
    let nbo = to_network_byte_order(expected);
    if cfg!(target_endian = "big") {
      assert_eq!(expected, nbo);
    } else {
      assert_eq!(expected.swap_bytes(), nbo);
    }
    let actual = from_network_byte_order(nbo);
    assert_eq!(expected, actual);
  }
}

u32 is a 32-bit unsigned integer; i32 is the signed version.

This post is just a code snippet written by someone getting started. No promises are made about code quality. Version: rustc 1.0.0-beta.4 (850151a75 2015-04-30) (built 2015-04-30)

Rust: UTF-8 byte array to String

Rust has a string type that mandates UTF-8 for strings but at some point you need to turn raw octets into structures you can treat as character data.

pub fn utf8_to_string(bytes: &[u8]) -> String {
  let vector: Vec<u8> = Vec::from(bytes);
  String::from_utf8(vector).unwrap()
}

#[cfg(test)]
mod test {
  use super::*;

  #[test]
  fn test_to_string() {
    let bytes: [u8; 7] = [0x55, 0x54, 0x46, 0x38, 0, 0, 0];
    let len: usize = 4;
    let actual = utf8_to_string(&bytes[0..len]);
    assert_eq!("UTF8", actual);
  }
}

The utf8_to_string function turns some octets into a String. Note the lack of semicolon on the last line - this indicates that the line returns a value. The ampersands indicate that the function is borrowing the variable. Rust has strong opinions on ownership - expect compile errors if you do not understand this concept.

Rust comes packages with the Cargo build system. I've in-lined my unit tests to exercise the functions I write. assert_eq! is a macro. Note that I've tried out a slice in my test to truncate the trailing zeroes.

This post is just a code snippet written by someone getting started. No promises are made about code quality. Version: rustc 1.0.0-beta.4 (850151a75 2015-04-30) (built 2015-04-30)

Sunday, 10 May 2015

Rust: first look

Rust is approaching its 1.0 release.

Rust is a systems programming language that runs blazingly fast, prevents almost all crashes*, and eliminates data races.

* In theory. Rust is a work-in-progress and may do anything it likes up to and including eating your laundry.

Rust has been under public development for a number of years. Many search engine results will lead to obsolete code. That might include this post. I have tried to stick to APIs marked stable but verify against the official documentation. The documentation on www.rust-lang.org is currently incomplete but it is the best starting point.

Version info:

$ rustc --version
rustc 1.0.0-beta.4 (850151a75 2015-04-30) (built 2015-04-30)

How I approached getting started with Rust:

  • Decide on an application to write (a simple UDP test client)
  • Decompose it into a list of parts
  • Figure out how to do each one in turn

A laundry list of disjointed code samples follow in subsequent posts.

2015-05-13: post has been split up into multiple posts for easier reference; use the rust-lang tag to filter.

Wednesday, 6 May 2015

UML: authoring simple sequence diagrams

I had specific criteria for a UML sequence diagram generator:

  • Text-sourced
  • Simple
  • Off-line
  • Linux

seqdiag fits the bill. There is an interactive shell if you want to try it out before installing.