bitint 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +2 -0
- data/Gemfile.lock +30 -0
- data/Steepfile +3 -3
- data/lib/bitint/base.rb +552 -0
- data/lib/bitint/bitint.rb +33 -300
- data/lib/bitint/constants.rb +18 -2
- data/lib/bitint/native.rb +99 -43
- data/lib/bitint/overflow_error.rb +15 -0
- data/lib/bitint/refinements.rb +17 -16
- data/lib/bitint/version.rb +3 -2
- data/lib/bitint.rb +3 -1
- data/sig/{bitint/version.rbs → bitint.rbs} +0 -1
- data/sig/generated/bitint/base.rbs +422 -0
- data/sig/generated/bitint/bitint.rbs +51 -0
- data/sig/generated/bitint/constants.rbs +33 -0
- data/sig/generated/bitint/native.rbs +74 -0
- data/sig/generated/bitint/overflow_error.rbs +12 -0
- data/sig/generated/bitint/refinements.rbs +72 -0
- data/sig/generated/bitint/version.rbs +6 -0
- metadata +14 -11
- data/sig/bitint/bitint.rbs +0 -62
- data/sig/bitint/error.rbs +0 -4
- data/sig/bitint/refinements.rb +0 -4
data/lib/bitint/bitint.rb
CHANGED
|
@@ -1,318 +1,51 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
# rbs_inline: enabled
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
class OverflowError < RuntimeError
|
|
6
|
-
attr_reader :integer, :range
|
|
4
|
+
module BitInt
|
|
5
|
+
module_function
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
super "#{integer} is out of bounds (range=#{range})"
|
|
10
|
-
@integer = integer
|
|
11
|
-
@range = range
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
@classes = {}
|
|
16
|
-
|
|
17
|
-
class << self
|
|
18
|
-
private :new
|
|
19
|
-
|
|
20
|
-
# Creates a new unsigned +BitInt+ class.
|
|
21
|
-
#
|
|
22
|
-
# === Example
|
|
23
|
-
# puts BitInt::U(16)::MAX #=> 65535
|
|
24
|
-
def U(bits) = self[bits, signed: false]
|
|
25
|
-
alias unsigned U
|
|
26
|
-
|
|
27
|
-
# Creates a new signed +BitInt+ class.
|
|
28
|
-
#
|
|
29
|
-
# === Example
|
|
30
|
-
# puts BitInt::I(16)::MAX #=> 32767
|
|
31
|
-
def I(bits) = self[bits, signed: true]
|
|
32
|
-
alias signed I
|
|
33
|
-
alias S I
|
|
34
|
-
|
|
35
|
-
# Creates a new +BitInt+. Raises an ArgumentError if bits is negative.
|
|
36
|
-
#
|
|
37
|
-
# === Example
|
|
38
|
-
# puts BitInt[8]::MAX #=> 255
|
|
39
|
-
# puts BitInt[8, signed: false]::MAX #=> 255
|
|
40
|
-
# puts BitInt[8, signed: true]::MAX #=> 127
|
|
41
|
-
def [](bits, signed: false) = create(bits: bits, signed: signed)
|
|
42
|
-
|
|
43
|
-
def create(bits: nil, bytes: nil, signed:)
|
|
44
|
-
if bits.nil? == bytes.nil?
|
|
45
|
-
raise ArgumentError, 'exactly one of `bits` or `bytes` must be supplied'
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
bits ||= bytes * 8
|
|
49
|
-
|
|
50
|
-
raise ArgumentError, 'bit count must be at least 1' unless bits.positive?
|
|
51
|
-
|
|
52
|
-
@classes[[bits, signed].freeze] ||= Class.new(self) do |cls|
|
|
53
|
-
cls.setup!(bits, signed)
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
# Returns whether this class represents a signed integer.
|
|
58
|
-
#
|
|
59
|
-
# === Example
|
|
60
|
-
# puts BitInt::U(8).signed? #=> false
|
|
61
|
-
# puts BitInt::I(8).signed? #=> true
|
|
62
|
-
def signed? = @signed
|
|
63
|
-
|
|
64
|
-
# Returns whether this class represents an unsigned integer.
|
|
65
|
-
#
|
|
66
|
-
# === Example
|
|
67
|
-
# puts BitInt::U(8).unsigned? #=> false
|
|
68
|
-
# puts BitInt::I(8).unsigned? #=> true
|
|
69
|
-
def unsigned? = !signed?
|
|
70
|
-
|
|
71
|
-
def inspect = name || "#{signed? ? 'I' : 'U'}#@bits"
|
|
72
|
-
alias to_s inspect
|
|
73
|
-
|
|
74
|
-
# :stopdoc:
|
|
75
|
-
protected def setup!(bits, signed)
|
|
76
|
-
@bits = bits
|
|
77
|
-
@signed = signed
|
|
78
|
-
|
|
79
|
-
create = ->(int) {
|
|
80
|
-
allocate.tap { |x| x.instance_variable_set :@int, int }
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
class << self
|
|
84
|
-
public :new
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
const_set :BITS, @bits
|
|
88
|
-
const_set :BYTES, (@bits / 8.0).ceil
|
|
89
|
-
const_set :MASK, (1 << @bits).pred
|
|
90
|
-
const_set :ZERO, create[0]
|
|
91
|
-
const_set :ONE, create[1]
|
|
92
|
-
const_set :MIN, create[signed? ? -(1 << @bits.pred) : 0]
|
|
93
|
-
const_set :MAX, create[signed? ? (1 << @bits.pred).pred : (1 << @bits).pred]
|
|
94
|
-
const_set :BOUNDS, self::MIN .. self::MAX
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
def pack_char
|
|
98
|
-
|
|
99
|
-
end
|
|
100
|
-
# :startdoc:
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
# Creates a new BitInt by masking +int+.
|
|
7
|
+
# Helper to create new unsigned {BitInt::Base} classes.
|
|
104
8
|
#
|
|
105
|
-
#
|
|
106
|
-
# OverflowError is raised.
|
|
9
|
+
# This method just wraps {Base.create}
|
|
107
10
|
#
|
|
108
|
-
#
|
|
109
|
-
#
|
|
110
|
-
# puts BitInt::U(8).new(-1) #=> 255
|
|
111
|
-
# puts BitInt::U(8).new(-1, wrap: false) #=> OverflowError
|
|
112
|
-
# puts BitInt::I(8).new(255) #=> -1
|
|
113
|
-
def initialize(int, wrap: true)
|
|
114
|
-
unless wrap || (bounds = self.class::BOUNDS).include?(int)
|
|
115
|
-
raise OverflowError.new(int, bounds)
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
@int = ((int - self.class::MIN.to_i) & self.class::MASK) + self.class::MIN.to_i
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
# Checks to see if +rhs.to_i+ is equal to this class
|
|
11
|
+
# @param bits [Integer] number of bits; must be nonzero
|
|
12
|
+
# @return [subclass of Base] a +Class+ that inherits from +Base+
|
|
122
13
|
#
|
|
123
14
|
# === Example
|
|
124
|
-
#
|
|
125
|
-
# twelve = U64.new(12)
|
|
126
|
-
#
|
|
127
|
-
# # Behaves as you'd expect.
|
|
128
|
-
# puts twelve == U64.new(12) #=> true
|
|
129
|
-
# puts twelve == U64.new(13) #=> false
|
|
130
|
-
# puts twelve == 12 #=> true
|
|
131
|
-
# puts twelve == 12.0 #=> true
|
|
132
|
-
# puts twelve == 13 #=> false
|
|
133
|
-
# puts twelve == Object.new #=> false
|
|
134
|
-
def ==(rhs) = rhs.respond_to?(:to_i) && @int == rhs.to_i
|
|
135
|
-
|
|
136
|
-
# Overwite rdoc-ref:Numeric#integer? as we're an integer.
|
|
137
|
-
def integer? = true
|
|
138
|
-
|
|
139
|
-
# :section: Conversions
|
|
140
|
-
|
|
141
|
-
# Returns the underlying integer.
|
|
142
|
-
def to_i = @int
|
|
143
|
-
alias to_int to_i
|
|
144
|
-
|
|
145
|
-
# Converts self to a Float.
|
|
146
|
-
def to_f = @int.to_f
|
|
147
|
-
|
|
148
|
-
# Converts self to a String.
|
|
15
|
+
# puts BitInt::U(16)::MAX #=> 65535
|
|
149
16
|
#
|
|
150
|
-
#
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
return @int.to_s if base.nil?
|
|
154
|
-
|
|
155
|
-
adjusted = negative? ? (-2*self.class::MIN + self).to_i : @int
|
|
156
|
-
adjusted.to_s(base).rjust(self.class::BITS / Math.log2(base), negative? ? '1' : '0')
|
|
157
|
-
end
|
|
17
|
+
# @rbs (Integer) -> untyped
|
|
18
|
+
def U(bits) = Base.create(bits: bits, signed: false)
|
|
19
|
+
alias unsigned U
|
|
158
20
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
# Returns a base-16 string of +self+. Equivalent to +to_s(16)+.
|
|
21
|
+
# Helper to create new signed {BitInt::Base} classes.
|
|
162
22
|
#
|
|
163
|
-
#
|
|
23
|
+
# This method just wraps {Base.create}
|
|
164
24
|
#
|
|
165
|
-
#
|
|
166
|
-
#
|
|
167
|
-
# puts BitInt::U16.new(1234, upper: true).hex #=> 04D2
|
|
168
|
-
def hex(upper: false)
|
|
169
|
-
to_s(16).tap { _1.upcase! if upper }
|
|
170
|
-
end
|
|
171
|
-
|
|
172
|
-
# Returns a base-8 string of +self+. Equivalent to +to_s(8)+.
|
|
25
|
+
# @param bits [Integer] number of bits; must be nonzero
|
|
26
|
+
# @return [subclass of Base] a +Class+ that inherits from +Base+
|
|
173
27
|
#
|
|
174
28
|
# === Example
|
|
175
|
-
# puts BitInt::
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
29
|
+
# puts BitInt::I(16)::MAX #=> 32767
|
|
30
|
+
#
|
|
31
|
+
# @rbs (Integer) -> untyped
|
|
32
|
+
def I(bits) = Base.create(bits: bits, signed: true)
|
|
33
|
+
alias signed I
|
|
34
|
+
alias S I
|
|
179
35
|
|
|
180
|
-
#
|
|
36
|
+
# Helper to create new {BitInt::Base} classes.
|
|
37
|
+
#
|
|
38
|
+
# This method just wraps {Base.create}.
|
|
39
|
+
#
|
|
40
|
+
# @param bits [Integer] number of bits; must be nonzero
|
|
41
|
+
# @param signed [bool] whether the subclass should be signed
|
|
42
|
+
# @return [subclass of Base] a +Class+ that inherits from +Base+
|
|
181
43
|
#
|
|
182
44
|
# === Example
|
|
183
|
-
# puts BitInt::
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
end
|
|
187
|
-
|
|
188
|
-
# :section: Math
|
|
189
|
-
|
|
190
|
-
# Numerically negates +self+.
|
|
191
|
-
def -@ = self.class.new(-@int)
|
|
192
|
-
|
|
193
|
-
# Bitwise negates +self+.
|
|
194
|
-
def ~ = self.class.new(~@int)
|
|
195
|
-
|
|
196
|
-
# Compares +self+ to +rhs+.
|
|
197
|
-
def <=>(rhs) = rhs.respond_to?(:to_i) ? @int <=> (_ = rhs).to_i : nil
|
|
198
|
-
|
|
199
|
-
# Adds +self+ to +rhs+.
|
|
200
|
-
def +(rhs) = self.class.new(@int + rhs.to_i)
|
|
201
|
-
|
|
202
|
-
# Subtracts +rhs+ from +self+.
|
|
203
|
-
def -(rhs) = self.class.new(@int - rhs.to_i)
|
|
204
|
-
|
|
205
|
-
# Multiplies +self+ by +rhs+.
|
|
206
|
-
def *(rhs) = self.class.new(@int * rhs.to_i)
|
|
207
|
-
|
|
208
|
-
# Divides +self+ by +rhs+.
|
|
209
|
-
def /(rhs) = self.class.new(@int / rhs.to_i)
|
|
210
|
-
|
|
211
|
-
# Modulos +self+ by +rhs+.
|
|
212
|
-
def %(rhs) = self.class.new(@int % rhs.to_i)
|
|
213
|
-
|
|
214
|
-
# :section:
|
|
215
|
-
|
|
216
|
-
# Returns whether +self+ is a positive integer. Zero is not positive.
|
|
217
|
-
def positive?
|
|
218
|
-
@int.positive?
|
|
219
|
-
end
|
|
220
|
-
|
|
221
|
-
# Return whether +self+ is a negative integer. Zero is not negative.
|
|
222
|
-
def negative?
|
|
223
|
-
@int.negative?
|
|
224
|
-
end
|
|
225
|
-
|
|
226
|
-
# Returns whether +self+ is zero.
|
|
227
|
-
def zero?
|
|
228
|
-
@int.zero?
|
|
229
|
-
end
|
|
230
|
-
|
|
231
|
-
# Returns a falsey value if zero, otherwise returns +self+.
|
|
232
|
-
def nonzero?
|
|
233
|
-
@int.nonzero? && self
|
|
234
|
-
end
|
|
235
|
-
|
|
236
|
-
# Checks to see if +self+ is even.
|
|
237
|
-
def even?
|
|
238
|
-
@int.even?
|
|
239
|
-
end
|
|
240
|
-
|
|
241
|
-
# Checks to see if +self+ is odd.
|
|
242
|
-
def odd?
|
|
243
|
-
@int.odd?
|
|
244
|
-
end
|
|
245
|
-
|
|
246
|
-
##################################
|
|
247
|
-
# :section: Bit-level operations #
|
|
248
|
-
##################################
|
|
249
|
-
|
|
250
|
-
# Raises +self+ to the +rhs+th power.
|
|
251
|
-
#--
|
|
252
|
-
# Note that `Numeric` only defines `.to_int` (not `.to_i`)
|
|
253
|
-
#++
|
|
254
|
-
def **(rhs) = self.class.new((@int ** rhs.to_i).to_int)
|
|
255
|
-
|
|
256
|
-
# Shifts +self+ left by +rhs+ bits.
|
|
257
|
-
def <<(rhs) = self.class.new(@int << rhs.to_i)
|
|
258
|
-
|
|
259
|
-
# Shifts +self+ right by +rhs+ bits.
|
|
260
|
-
def >>(rhs) = self.class.new(@int >> rhs.to_i)
|
|
261
|
-
|
|
262
|
-
# Bitwise ANDs +self+ and +rhs+.
|
|
263
|
-
def &(rhs) = self.class.new(@int & rhs.to_i)
|
|
264
|
-
|
|
265
|
-
# Bitwise ORs +self+ and +rhs+.
|
|
266
|
-
def |(rhs) = self.class.new(@int | rhs.to_i)
|
|
267
|
-
|
|
268
|
-
# Bitwise XORs +self+ and +rhs+.
|
|
269
|
-
def ^(rhs) = self.class.new(@int ^ rhs.to_i)
|
|
270
|
-
|
|
271
|
-
# Gets the bit at index +idx+ or returns +nil+.
|
|
45
|
+
# puts BitInt[9]::MAX #=> 511
|
|
46
|
+
# puts BitInt[9, signed: false]::MAX #=> 511
|
|
47
|
+
# puts BitInt[9, signed: true]::MAX #=> 255
|
|
272
48
|
#
|
|
273
|
-
#
|
|
274
|
-
def [](
|
|
275
|
-
|
|
276
|
-
def anybits?(mask) = @int.anybits?(mask)
|
|
277
|
-
def allbits?(mask) = @int.allbits?(mask)
|
|
278
|
-
def nobits?(mask) = @int.nobits?(mask)
|
|
279
|
-
def bit_length = @int.bit_length
|
|
280
|
-
|
|
281
|
-
def size = (self.class::BITS / 8.0).ceil
|
|
282
|
-
|
|
283
|
-
PACK_FMT = {
|
|
284
|
-
[:native, 8, false].freeze => 'C',
|
|
285
|
-
[:native, 16, false].freeze => 'S',
|
|
286
|
-
[:native, 32, false].freeze => 'L',
|
|
287
|
-
[:native, 64, false].freeze => 'Q',
|
|
288
|
-
[:native, 8, true].freeze => 'c',
|
|
289
|
-
[:native, 16, true].freeze => 's',
|
|
290
|
-
[:native, 32, true].freeze => 'l',
|
|
291
|
-
[:native, 64, true].freeze => 'q',
|
|
292
|
-
}.freeze
|
|
293
|
-
private_constant :PACK_FMT
|
|
294
|
-
|
|
295
|
-
def bytes(endian = :native)
|
|
296
|
-
return to_enum(__method__, endian) unless block_given?
|
|
297
|
-
|
|
298
|
-
template = '_CS_L___Q'[self.class::BYTES]
|
|
299
|
-
if template.nil? || template == '_'
|
|
300
|
-
raise ArgumentError, 'bytes only works for sizes of 8, 16, 32, or 64.'
|
|
301
|
-
end
|
|
302
|
-
|
|
303
|
-
template.downcase! if self.class.signed?
|
|
304
|
-
|
|
305
|
-
case endian
|
|
306
|
-
when :native
|
|
307
|
-
when :little then template.concat '<'
|
|
308
|
-
when :big then template.concat '>'
|
|
309
|
-
else raise raise ArgumentError, 'endian must be :big, :little, or :native'
|
|
310
|
-
end
|
|
311
|
-
|
|
312
|
-
[to_i].pack(template).unpack('C*').map(&U8.method(:new))
|
|
313
|
-
end
|
|
314
|
-
|
|
315
|
-
def bytes_hex(...)
|
|
316
|
-
bytes(...).map(&:hex)
|
|
317
|
-
end
|
|
49
|
+
# @rbs (Integer, ?signed: bool) -> untyped
|
|
50
|
+
def [](bits, signed: false) = Base.create(bits: bits, signed: signed)
|
|
318
51
|
end
|
data/lib/bitint/constants.rb
CHANGED
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
# rbs_inline: enabled
|
|
3
|
+
|
|
4
|
+
# @rbs!
|
|
5
|
+
# module BitInt
|
|
6
|
+
# class U8 < Base end
|
|
7
|
+
# class U16 < Base end
|
|
8
|
+
# class U32 < Base end
|
|
9
|
+
# class U64 < Base end
|
|
10
|
+
# class U128 < Base end
|
|
11
|
+
# class I8 < Base end
|
|
12
|
+
# class I16 < Base end
|
|
13
|
+
# class I32 < Base end
|
|
14
|
+
# class I64 < Base end
|
|
15
|
+
# class I128 < Base end
|
|
16
|
+
# end
|
|
17
|
+
|
|
18
|
+
# @rbs skip
|
|
19
|
+
module BitInt
|
|
4
20
|
# An unsigned 8-bit integer
|
|
5
21
|
U8 = U(8)
|
|
6
22
|
|
data/lib/bitint/native.rb
CHANGED
|
@@ -1,88 +1,144 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
# rbs_inline: enabled
|
|
2
3
|
|
|
3
4
|
require 'fiddle'
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
#
|
|
6
|
+
module BitInt
|
|
7
|
+
# +BitInt+s that correspond to underlying C integer sizes.
|
|
7
8
|
module Native
|
|
8
|
-
# On big-endian systems, the unpack will equal
|
|
9
|
+
# On big-endian systems, the unpack will equal +0x00AA+.
|
|
9
10
|
IS_LITTLE_ENDIAN = [0xAA00].pack('S').unpack('S<') == [0xAA00]
|
|
10
11
|
private_constant :IS_LITTLE_ENDIAN
|
|
11
12
|
|
|
12
13
|
module_function
|
|
13
14
|
|
|
14
|
-
#
|
|
15
|
+
# Helper method to fetch the endianness of the underlying system.
|
|
16
|
+
#
|
|
17
|
+
# @rbs () -> (:little | :big)
|
|
15
18
|
def endianness
|
|
16
|
-
|
|
19
|
+
IS_LITTLE_ENDIAN ? :little : :big
|
|
17
20
|
end
|
|
18
21
|
|
|
19
22
|
class << self
|
|
20
23
|
alias endian endianness
|
|
21
24
|
end
|
|
22
25
|
|
|
23
|
-
# Returns
|
|
26
|
+
# Returns +true+ when on a little endian system.
|
|
27
|
+
#
|
|
28
|
+
# @rbs () -> bool
|
|
24
29
|
def little_endian?
|
|
25
30
|
endianness == :little
|
|
26
31
|
end
|
|
27
32
|
|
|
28
|
-
# Returns
|
|
33
|
+
# Returns +true+ when on a big endian system.
|
|
34
|
+
#
|
|
35
|
+
# @rbs () -> bool
|
|
29
36
|
def big_endian?
|
|
30
37
|
endianness == :big
|
|
31
38
|
end
|
|
32
39
|
|
|
33
|
-
#
|
|
40
|
+
# @rbs!
|
|
41
|
+
# class SCHAR < Base end
|
|
42
|
+
# class UCHAR < Base end
|
|
43
|
+
# class SHORT < Base end
|
|
44
|
+
# class USHORT < Base end
|
|
45
|
+
# class INT < Base end
|
|
46
|
+
# class UINT < Base end
|
|
47
|
+
# class LONG < Base end
|
|
48
|
+
# class ULONG < Base end
|
|
49
|
+
# class LONG_LONG < Base end
|
|
50
|
+
# class ULONG_LONG < Base end
|
|
51
|
+
# class VOIDP < Base end
|
|
52
|
+
# class SIZE_T < Base end
|
|
53
|
+
# class SSIZE_T < Base end
|
|
54
|
+
# class PTRDIFF_T < Base end
|
|
55
|
+
# class INTPTR_T < Base end
|
|
56
|
+
# class UINTPTR_T < Base end
|
|
57
|
+
|
|
58
|
+
# A signed +sizeof(char)+-byte BitInt.
|
|
34
59
|
#
|
|
35
|
-
# Technically C has a difference between
|
|
36
|
-
# no real easy way to tell from within ruby code. So
|
|
60
|
+
# Technically C has a difference between +char+, +unsigned char+, and +signed char+. But there's
|
|
61
|
+
# no real easy way to tell from within ruby code. So +CHAR+ doesn't exist.
|
|
37
62
|
#
|
|
38
|
-
|
|
63
|
+
# @rbs skip
|
|
64
|
+
SCHAR = Base.create(bytes: Fiddle::SIZEOF_CHAR, signed: true)
|
|
39
65
|
|
|
40
|
-
# An unsigned
|
|
41
|
-
|
|
66
|
+
# An unsigned +sizeof(char)+-byte BitInt.
|
|
67
|
+
#
|
|
68
|
+
# @rbs skip
|
|
69
|
+
UCHAR = Base.create(bytes: Fiddle::SIZEOF_CHAR, signed: false)
|
|
42
70
|
|
|
43
|
-
# A signed
|
|
44
|
-
|
|
71
|
+
# A signed +sizeof(short)+-byte BitInt.
|
|
72
|
+
#
|
|
73
|
+
# @rbs skip
|
|
74
|
+
SHORT = Base.create(bytes: Fiddle::SIZEOF_SHORT, signed: true)
|
|
45
75
|
|
|
46
|
-
# An unsigned
|
|
47
|
-
|
|
76
|
+
# An unsigned +sizeof(short)+-byte BitInt.
|
|
77
|
+
#
|
|
78
|
+
# @rbs skip
|
|
79
|
+
USHORT = Base.create(bytes: Fiddle::SIZEOF_SHORT, signed: false)
|
|
48
80
|
|
|
49
|
-
# A signed
|
|
50
|
-
|
|
81
|
+
# A signed +sizeof(int)+-byte BitInt.
|
|
82
|
+
#
|
|
83
|
+
# @rbs skip
|
|
84
|
+
INT = Base.create(bytes: Fiddle::SIZEOF_INT, signed: true)
|
|
51
85
|
|
|
52
|
-
# An unsigned
|
|
53
|
-
|
|
86
|
+
# An unsigned +sizeof(int)+-byte BitInt.
|
|
87
|
+
#
|
|
88
|
+
# @rbs skip
|
|
89
|
+
UINT = Base.create(bytes: Fiddle::SIZEOF_INT, signed: false)
|
|
54
90
|
|
|
55
|
-
# A signed
|
|
56
|
-
|
|
91
|
+
# A signed +sizeof(long)+-byte BitInt.
|
|
92
|
+
#
|
|
93
|
+
# @rbs skip
|
|
94
|
+
LONG = Base.create(bytes: Fiddle::SIZEOF_LONG, signed: true)
|
|
57
95
|
|
|
58
|
-
# An unsigned
|
|
59
|
-
|
|
96
|
+
# An unsigned +sizeof(long)+-byte BitInt.
|
|
97
|
+
#
|
|
98
|
+
# @rbs skip
|
|
99
|
+
ULONG = Base.create(bytes: Fiddle::SIZEOF_LONG, signed: false)
|
|
60
100
|
|
|
61
|
-
# Some platforms Ruby supports don't actually support
|
|
101
|
+
# Some platforms Ruby supports don't actually support +long long+s (in this day and age...)
|
|
62
102
|
if defined? Fiddle::SIZEOF_LONG_LONG
|
|
63
|
-
# A signed
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
103
|
+
# A signed +sizeof(long long)+-byte BitInt. Only enabled if the platform supports +long long+.
|
|
104
|
+
#
|
|
105
|
+
# @rbs skip
|
|
106
|
+
LONG_LONG = Base.create(bytes: Fiddle::SIZEOF_LONG_LONG, signed: true)
|
|
107
|
+
|
|
108
|
+
# An unsigned +sizeof(long long)+-byte BitInt. Only enabled if the platform supports +long long+.
|
|
109
|
+
#
|
|
110
|
+
# @rbs skip
|
|
111
|
+
ULONG_LONG = Base.create(bytes: Fiddle::SIZEOF_LONG_LONG, signed: false)
|
|
68
112
|
end
|
|
69
113
|
|
|
70
|
-
# An unsigned
|
|
71
|
-
|
|
114
|
+
# An unsigned +sizeof(void *)+-byte BitInt.
|
|
115
|
+
#
|
|
116
|
+
# @rbs skip
|
|
117
|
+
VOIDP = Base.create(bytes: Fiddle::SIZEOF_VOIDP, signed: false)
|
|
72
118
|
|
|
73
|
-
# An unsigned
|
|
74
|
-
|
|
119
|
+
# An unsigned +sizeof(size_t)+-byte BitInt.
|
|
120
|
+
#
|
|
121
|
+
# @rbs skip
|
|
122
|
+
SIZE_T = Base.create(bytes: Fiddle::SIZEOF_SIZE_T, signed: false)
|
|
75
123
|
|
|
76
|
-
# A signed
|
|
77
|
-
|
|
124
|
+
# A signed +sizeof(ssize_t)+-byte BitInt.
|
|
125
|
+
#
|
|
126
|
+
# @rbs skip
|
|
127
|
+
SSIZE_T = Base.create(bytes: Fiddle::SIZEOF_SSIZE_T, signed: true)
|
|
78
128
|
|
|
79
|
-
# A signed
|
|
80
|
-
|
|
129
|
+
# A signed +sizeof(ptrdiff_t)+-byte BitInt.
|
|
130
|
+
#
|
|
131
|
+
# @rbs skip
|
|
132
|
+
PTRDIFF_T = Base.create(bytes: Fiddle::SIZEOF_PTRDIFF_T, signed: true)
|
|
81
133
|
|
|
82
|
-
# A signed
|
|
83
|
-
|
|
134
|
+
# A signed +sizeof(intptr_t)+-byte BitInt.
|
|
135
|
+
#
|
|
136
|
+
# @rbs skip
|
|
137
|
+
INTPTR_T = Base.create(bytes: Fiddle::SIZEOF_INTPTR_T, signed: true)
|
|
84
138
|
|
|
85
|
-
# An unsigned
|
|
86
|
-
|
|
139
|
+
# An unsigned +sizeof(uintptr_t)+-byte BitInt.
|
|
140
|
+
#
|
|
141
|
+
# @rbs skip
|
|
142
|
+
UINTPTR_T = Base.create(bytes: Fiddle::SIZEOF_UINTPTR_T, signed: false)
|
|
87
143
|
end
|
|
88
144
|
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# rbs_inline: enabled
|
|
3
|
+
|
|
4
|
+
module BitInt
|
|
5
|
+
# Indicates that +BitInt::Base.create+ was called with an integer that was too large.
|
|
6
|
+
class OverflowError < RuntimeError
|
|
7
|
+
attr_reader :integer, :range
|
|
8
|
+
|
|
9
|
+
def initialize(integer, range)
|
|
10
|
+
super "#{integer} is out of bounds (range=#{range})"
|
|
11
|
+
@integer = integer
|
|
12
|
+
@range = range
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
data/lib/bitint/refinements.rb
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
# rbs_inline: enabled
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
# Refinements to Integer for easy "BitInt literals" (eg
|
|
4
|
+
module BitInt
|
|
5
|
+
# Refinements to +Integer+ for easy "+BitInt+ literals" (eg +puts(12.u8)+)
|
|
5
6
|
module Refinements
|
|
6
7
|
refine Integer do
|
|
7
8
|
# Converts +self+ into an unsigned +bits+-bit integer.
|
|
@@ -12,7 +13,7 @@ class BitInt
|
|
|
12
13
|
# puts BitInt::U(16)::MAX #=> 65535
|
|
13
14
|
#
|
|
14
15
|
def u(bits, ...)
|
|
15
|
-
BitInt::U(bits
|
|
16
|
+
BitInt::U(bits).new(self, ...)
|
|
16
17
|
end
|
|
17
18
|
|
|
18
19
|
# Converts +self+ into a signed +bits+-bit integer.
|
|
@@ -20,61 +21,61 @@ class BitInt
|
|
|
20
21
|
# If no arguments are given, this instead forwards to Numeric#i.
|
|
21
22
|
#
|
|
22
23
|
# Any additional arguments are forwarded to +BitInt#new+
|
|
23
|
-
def i(bits = bits_not_given=true,
|
|
24
|
-
bits_not_given and return super
|
|
24
|
+
def i(bits = bits_not_given=true, ...)
|
|
25
|
+
bits_not_given and return super()
|
|
25
26
|
|
|
26
|
-
BitInt::
|
|
27
|
+
BitInt::I(bits).new(self, ...)
|
|
27
28
|
end
|
|
28
29
|
|
|
29
30
|
# Converts +self+ into an unsigned 8-bit integer.
|
|
30
31
|
#
|
|
31
32
|
# Any additional arguments are forwarded to +BitInt#new+
|
|
32
|
-
def u8(...) =
|
|
33
|
+
def u8(...) = U8.new(self, ...)
|
|
33
34
|
|
|
34
35
|
# Converts +self+ into an unsigned 16-bit integer.
|
|
35
36
|
#
|
|
36
37
|
# Any additional arguments are forwarded to +BitInt#new+
|
|
37
|
-
def u16(...) =
|
|
38
|
+
def u16(...) = U16.new(self, ...)
|
|
38
39
|
|
|
39
40
|
# Converts +self+ into an unsigned 32-bit integer.
|
|
40
41
|
#
|
|
41
42
|
# Any additional arguments are forwarded to +BitInt#new+
|
|
42
|
-
def u32(...) =
|
|
43
|
+
def u32(...) = U32.new(self, ...)
|
|
43
44
|
|
|
44
45
|
# Converts +self+ into an unsigned 64-bit integer.
|
|
45
46
|
#
|
|
46
47
|
# Any additional arguments are forwarded to +BitInt#new+
|
|
47
|
-
def u64(...) =
|
|
48
|
+
def u64(...) = U64.new(self, ...)
|
|
48
49
|
|
|
49
50
|
# Converts +self+ into an unsigned 128-bit integer.
|
|
50
51
|
#
|
|
51
52
|
# Any additional arguments are forwarded to +BitInt#new+
|
|
52
|
-
def u128(...) =
|
|
53
|
+
def u128(...) = U128.new(self, ...)
|
|
53
54
|
|
|
54
55
|
# Converts +self+ into a signed 8-bit integer.
|
|
55
56
|
#
|
|
56
57
|
# Any additional arguments are forwarded to +BitInt#new+
|
|
57
|
-
def i8(...) =
|
|
58
|
+
def i8(...) = I8.new(self, ...)
|
|
58
59
|
|
|
59
60
|
# Converts +self+ into a signed 16-bit integer.
|
|
60
61
|
#
|
|
61
62
|
# Any additional arguments are forwarded to +BitInt#new+
|
|
62
|
-
def i16(...) =
|
|
63
|
+
def i16(...) = I16.new(self, ...)
|
|
63
64
|
|
|
64
65
|
# Converts +self+ into a signed 32-bit integer.
|
|
65
66
|
#
|
|
66
67
|
# Any additional arguments are forwarded to +BitInt#new+
|
|
67
|
-
def i32(...) =
|
|
68
|
+
def i32(...) = I32.new(self, ...)
|
|
68
69
|
|
|
69
70
|
# Converts +self+ into a signed 64-bit integer.
|
|
70
71
|
#
|
|
71
72
|
# Any additional arguments are forwarded to +BitInt#new+
|
|
72
|
-
def i64(...) =
|
|
73
|
+
def i64(...) = I64.new(self, ...)
|
|
73
74
|
|
|
74
75
|
# Converts +self+ into a signed 128-bit integer.
|
|
75
76
|
#
|
|
76
77
|
# Any additional arguments are forwarded to +BitInt#new+
|
|
77
|
-
def i128(...) =
|
|
78
|
+
def i128(...) = I128.new(self, ...)
|
|
78
79
|
end
|
|
79
80
|
end
|
|
80
81
|
end
|