require 'yaml'

module BinaryIO

# Failed to write binary data.
class BinaryWriteError < IOError
end

# Based on BinaryReader class by Michael Neumann
# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/23048
class BinaryWriter

  # Config file containing info about the types of data to be written.
  CONFIG = 'BinaryIO.yaml'
  
	File.open("#{File.dirname(__FILE__)}/#{CONFIG}") do |file|
		YAML::load(file).each_pair do |meth, data|
			eval %{
				def write_#{meth}(value)
					_write(value, #{data[:size]}, '#{data[:format]}')
				end
			}
		end
	end

  # handle:: stream to write to.
	def initialize(handle)
		@handle = handle
	end

  # value:: Value or values to write [Number or Array of Number].
  # size:: Size of each data item in bytes.
  # format:: Format string for each data item (See Array#pack).
	protected
	def _write(value, size, format)
    # If not an array, make it into a single-element array so we can pack it.
		value = [value] unless value.is_a? Array

		num_bytes = value.size * size
		arr = value.pack(format * value.size)

    begin
      num_bytes_written = @handle.write(arr)
    rescue IOError => exception
      raise BinaryWriteError, exception.message
    end

    unless num_bytes_written == num_bytes
      raise BinaryWriteError, "Wrote #{num_bytes_written} bytes when expecting #{num_bytes} bytes"
    end
	end
end

end