@@ -21,50 +21,88 @@ class << self
2121 def new ( opts = Options . new , **properties )
2222 properties . each_key do |prop |
2323 if method_defined? ( prop )
24- $stdout . puts OVERRIDING_NATIVE_METHOD_MSG % [ prop . inspect , caller ( 3 ) . first ]
24+ warn OVERRIDING_NATIVE_METHOD_MSG % [ prop . inspect , caller ( 3 ) . first ]
2525 end
2626 end
2727
28- super ( * properties . keys , keyword_init : true ) . tap do | klass |
29- klass . class . instance_eval do
30- include TypeChecking
31- attr_reader :options
32- end
28+ klass = if opts [ :class_name ]
29+ super ( opts [ :class_name ] , * properties . keys , keyword_init : opts [ :keyword_init ] )
30+ else
31+ super ( * properties . keys , keyword_init : opts [ :keyword_init ] )
32+ end
3333
34- klass . instance_eval do
35- @options = { types : properties , options : opts }
34+ klass . class . instance_eval do
35+ include TypeChecking
36+ attr_reader :options
37+ end
3638
37- define_method :[]= do |key , val |
38- prop = properties [ key ]
39- unless val_is_type? val , prop
40- raise "Unexpected type #{ val . class } for #{ key . inspect } (expected #{ prop } )"
41- end
39+ klass . instance_eval do
40+ @options = { types : properties , options : opts }
4241
43- super key , val
42+ define_method :[]= do |key , val |
43+ if key . is_a? ( Integer )
44+ if key . negative?
45+ raise IndexError , "offset #{ key } too small for struct(size:#{ members . size } )"
46+ elsif key >= members . size
47+ raise IndexError , "offset #{ key } too large for struct(size:#{ members . size } )"
48+ end
49+ key = self . members [ key ]
50+ end
51+ unless properties . key? ( key )
52+ raise NameError , "no member '#{ key } ' in struct"
53+ end
54+ prop = properties [ key ]
55+ unless val_is_type? val , prop
56+ raise TypeError , "unexpected type #{ val . class } for #{ key . inspect } (expected #{ prop } )"
4457 end
4558
46- properties . each_key do |k |
47- define_method :"#{ k } =" do |val |
48- self [ k ] = val
49- end
59+ super key , val
60+ end
61+
62+ properties . each_key do |k |
63+ define_method :"#{ k } =" do |val |
64+ self [ k ] = val
5065 end
5166 end
5267 end
68+
69+ klass
5370 end
5471 end
5572
56- def initialize ( **attrs )
73+ def initialize ( *positional_attrs , * *attrs )
5774 opts = self . __class__ . options
75+ if opts [ :options ] [ :keyword_init ] == true && !positional_attrs . empty?
76+ raise ArgumentError , "wrong number of arguments (given #{ positional_attrs . size } , expected 0)"
77+ elsif ( opts [ :options ] [ :keyword_init ] == false && !attrs . empty? ) ||
78+ ( opts [ :options ] [ :keyword_init ] != true && !positional_attrs . empty? )
79+ positional_attrs << attrs unless attrs . empty?
80+ attrs = positional_attrs . zip ( self . members ) . to_h ( &:reverse )
81+ end
82+
83+ if attrs . size > members . size
84+ raise ArgumentError , "struct size differs"
85+ end
86+
5887 vals = opts [ :types ] . to_h do |prop , expected_type |
5988 value = attrs . fetch ( prop , opts [ :options ] [ :default ] )
6089 unless val_is_type? value , expected_type
61- raise "Unexpected type #{ value . class } for #{ prop . inspect } (expected #{ expected_type } )"
90+ raise TypeError , "unexpected type #{ value . class } for #{ prop . inspect } (expected #{ expected_type } )"
6291 end
6392 [ prop , value ]
6493 end
6594
66- super **vals
95+ if opts [ :options ] [ :keyword_init ] == true
96+ super **vals
97+ else
98+ super *vals . values
99+ end
67100 end
68101
69- Options = TypedStruct . new ( { default : nil } , default : Rbs ( "untyped" ) )
102+ Options = TypedStruct . new (
103+ { default : nil } ,
104+ default : Rbs ( "untyped" ) ,
105+ keyword_init : Rbs ( "bool?" ) ,
106+ class_name : Rbs ( "String? | Symbol?" )
107+ )
70108end
0 commit comments