README: update with extra disclaimer
[raindrops.git] / lib / raindrops / struct.rb
blob7233ce827ea214bc9a7838bd320b6d70306cbe06
1 # -*- encoding: binary -*-
2 # frozen_string_literal: false
4 # This is a wrapper around Raindrops objects much like the core Ruby
5 # \Struct can be seen as a wrapper around the core \Array class.
6 # It's usage is similar to the core \Struct class, except its fields
7 # may only be used to house unsigned long integers.
9 #   class Foo < Raindrops::Struct.new(:readers, :writers)
10 #   end
12 #   foo = Foo.new 0, 0
14 #   foo.incr_writers    -> 1
15 #   foo.incr_readers    -> 1
17 class Raindrops::Struct
19   # returns a new class derived from Raindrops::Struct and supporting
20   # the given +members+ as fields, just like \Struct.new in core Ruby.
21   def self.new(*members)
22     members = members.map { |x| x.to_sym }.freeze
23     str = <<EOS
24 def initialize(*values)
25   (MEMBERS.size >= values.size) or raise ArgumentError, "too many arguments"
26   @raindrops = Raindrops.new(MEMBERS.size)
27   values.each_with_index { |val,i| @raindrops[i] = values[i] }
28 end
30 def initialize_copy(src)
31   @raindrops = src.instance_variable_get(:@raindrops).dup
32 end
34 def []=(index, value)
35   @raindrops[index] = value
36 end
38 def [](index)
39   @raindrops[index]
40 end
42 def to_hash
43   ary = @raindrops.to_ary
44   rv = {}
45   MEMBERS.each_with_index { |member, i| rv[member] = ary[i] }
46   rv
47 end
48 EOS
50     members.each_with_index do |member, i|
51       str << "def incr_#{member}; @raindrops.incr(#{i}); end; " \
52              "def decr_#{member}; @raindrops.decr(#{i}); end; " \
53              "def #{member}; @raindrops[#{i}]; end; " \
54              "def #{member}=(val); @raindrops[#{i}] = val; end; "
55     end
57     klass = Class.new
58     klass.const_set(:MEMBERS, members)
59     klass.class_eval(str)
60     klass
61   end
63 end