require 'benchmark'
require 'orig/hex_struct'
require 'hexstruct2'

class A < HexStruct
  STRUCT = [
    [:MsgCode, 2],
    [:from_add, 3],
    [:to_add, 3],
    [:data, 5],
  ]
end

class AA < HexStruct
  STRUCT = [
    [:MsgCode, 2],
    [:from_add, 3],
    [:to_add, 3],
    [:data, -1],
  ]
end

class DataPart < HexStruct
  STRUCT = [
    [:DataType, 2],
    [:Len, 1],
    [:data, -1],
  ]
end


B = HexStruct2.define {
  fixed_size_field :MsgCode, 2
  fixed_size_field :from_add, 3
  fixed_size_field :to_add, 3
  fixed_size_field :data, 5
}
BB = HexStruct2.define {
  fixed_size_field :MsgCode, 2
  fixed_size_field :from_add, 3
  fixed_size_field :to_add, 3
  struct_field(:data) {
    fixed_size_field :DataType, 2
    fixed_size_field :Len, 1
    variable_size_field :data
  }
}


str = [
  "0023",       # MsgCode
  "000110",     # from_add
  "000203",     # to_add
  "0102030405", # data(5byte)
].join

nested_str = [
  "0023",       # MsgCode
  "000110",     # from_add
  "000203",     # to_add
  "001103AABBCC", # data
].join

n = ARGV[0] ? ARGV[0].to_i : 1
frame = nil

Benchmark.bm(16) {|x|
  x.report('original/parse') {
    n.times do
      A.new(str)
    end
  }
  x.report('original/parse2') {
    n.times do
      frame = AA.new(nested_str)
      frame.data = DataPart.new(frame.data)
    end
  }
  x.report('original/access') {
    frame = A.new(str)
    n.times do
      frame.MsgCode
      frame.from_add
      frame.data
    end
  }
  x.report('original/p+a') {
    n.times do
      frame = A.new(str)
      frame.MsgCode
      frame.from_add
      frame.data
    end
  }

  x.report('aamine  /parse') {
    n.times do
      B.parse(str)
    end
  }
  x.report('aamine  /parse2') {
    n.times do
      BB.parse(nested_str)
    end
  }
  x.report('aamine  /access') {
    frame = B.parse(str)
    n.times do
      frame.MsgCode
      frame.from_add
      frame.data
    end
  }
  x.report('aamine  /p+a') {
    n.times do
      frame = B.parse(str)
      frame.MsgCode
      frame.from_add
      frame.data
    end
  }
}
