@@ -11,6 +11,12 @@ Use [`ZeroPad`](@ref) or [`OnePad`](@ref) in layouts.
1111"""
1212abstract type Pad{N} end
1313
14+ function check_pad_bitwidth (N)
15+ N isa Integer || throw (ArgumentError (" padding bitwidth must be an integer, got $N " ))
16+ N >= 1 || throw (ArgumentError (" padding bitwidth must be positive, got $N " ))
17+ return Int (N)
18+ end
19+
1420"""
1521 ZeroPad{N} <: Pad{N}
1622 ZeroPad(N)
@@ -32,7 +38,12 @@ Tuple(nt) # (0x00, true, BitPacking.ZeroPad(7))
3238Raw-storage constructors validate that the corresponding padding bits are
3339zero.
3440"""
35- abstract type ZeroPad{N} <: Pad{N} end
41+ struct ZeroPad{N} <: Pad{N}
42+ function ZeroPad {N} () where N
43+ check_pad_bitwidth (N)
44+ new {N} ()
45+ end
46+ end
3647
3748"""
3849 OnePad{N} <: Pad{N}
@@ -54,28 +65,18 @@ Tuple(nt) # (0x00, true, BitPacking.OnePad(7))
5465Raw-storage constructors validate that the corresponding padding bits are
5566one.
5667"""
57- abstract type OnePad{N} <: Pad{N} end
58-
59- struct ZeroPadValue{N} <: ZeroPad{N} end
60- struct OnePadValue{N} <: OnePad{N} end
61-
62- function check_pad_bitwidth (N)
63- N isa Integer || throw (ArgumentError (" padding bitwidth must be an integer, got $N " ))
64- N >= 1 || throw (ArgumentError (" padding bitwidth must be positive, got $N " ))
65- return Int (N)
68+ struct OnePad{N} <: Pad{N}
69+ function OnePad {N} () where N
70+ check_pad_bitwidth (N)
71+ new {N} ()
72+ end
6673end
6774
68- ZeroPad (N) = ZeroPadValue {check_pad_bitwidth(N)} ()
69- OnePad (N) = OnePadValue {check_pad_bitwidth(N)} ()
70- (:: Type{ZeroPad{N}} )() where N = ZeroPadValue {check_pad_bitwidth(N)} ()
71- (:: Type{OnePad{N}} )() where N = OnePadValue {check_pad_bitwidth(N)} ()
75+ ZeroPad (N) = ZeroPad {N} ()
76+ OnePad (N) = OnePad {N} ()
7277
7378bitwidth (:: Type{<:Pad{N}} ) where N = check_pad_bitwidth (N)
7479
75- is_pad_type (:: Type{T} ) where T = T <: Pad
76- is_zero_pad_type (:: Type{T} ) where T = T <: ZeroPad
77- is_one_pad_type (:: Type{T} ) where T = T <: OnePad
78-
7980layout_fieldtype (:: Type{T} ) where {N,T<: ZeroPad{N} } = ZeroPad{N}
8081layout_fieldtype (:: Type{T} ) where {N,T<: OnePad{N} } = OnePad{N}
8182layout_fieldtype (:: Type{T} ) where T = T
@@ -84,8 +85,6 @@ function layout_tuple_type(::Type{Ts}) where Ts<:Tuple
8485 return Tuple{map (layout_fieldtype, fieldtypes (Ts))... }
8586end
8687
87- materialized_fieldtype (:: Type{T} ) where {N,T<: ZeroPad{N} } = ZeroPadValue{N}
88- materialized_fieldtype (:: Type{T} ) where {N,T<: OnePad{N} } = OnePadValue{N}
8988materialized_fieldtype (:: Type{T} ) where T = T
9089
9190function materialized_fieldtypes (:: Type{Ts} ) where Ts<: Tuple
@@ -97,15 +96,15 @@ function materialized_tuple_type(::Type{Ts}) where Ts<:Tuple
9796end
9897
9998function unpadded_fieldtypes (:: Type{Ts} ) where Ts<: Tuple
100- return Tuple (T for T in fieldtypes (Ts) if ! is_pad_type (T ))
99+ return Tuple (T for T in fieldtypes (Ts) if ! (T <: Pad ))
101100end
102101
103102function unpadded_tuple_type (:: Type{Ts} ) where Ts<: Tuple
104103 return Tuple{unpadded_fieldtypes (Ts)... }
105104end
106105
107- pad_value (:: Type{T} ) where {N,T<: ZeroPad{N} } = ZeroPadValue {N} ( )
108- pad_value (:: Type{T} ) where {N,T<: OnePad{N} } = OnePadValue {N} ( )
106+ pad_value (:: Type{T} ) where {N,T<: ZeroPad{N} } = ZeroPad (N )
107+ pad_value (:: Type{T} ) where {N,T<: OnePad{N} } = OnePad (N )
109108
110109function check_narrow_tuple_type (:: Type{Ts} ) where Ts<: Tuple
111110 for T in fieldtypes (Ts)
@@ -115,9 +114,7 @@ function check_narrow_tuple_type(::Type{Ts}) where Ts<:Tuple
115114 W isa Integer ||
116115 throw (ArgumentError (" bitwidth($T ) must be an integer, got $W " ))
117116
118- if is_pad_type (T)
119- (is_zero_pad_type (T) || is_one_pad_type (T)) ||
120- throw (ArgumentError (" NarrowTuple padding field type must be ZeroPad or OnePad, got $T " ))
117+ if T <: Pad
121118 W >= 1 || throw (ArgumentError (" padding bitwidth must be positive, got $W " ))
122119 else
123120 isbitstype (T) ||
@@ -231,7 +228,7 @@ struct NarrowTuple{Ts<:Tuple,D<:Storage}
231228 end
232229end
233230
234- bitwidth (:: Type{<:NarrowTuple{Ts}} ) where Ts = bitwidth (Ts )
231+ bitwidth (:: Type{<:NarrowTuple{Ts}} ) where Ts = sum (bitwidth, Ts . parameters; init = 0 )
235232
236233@generated function narrow_tuple_pack (:: Val{Ws} , :: Type{Layout} , :: Type{D} , xs:: Values ) where {Ws,Layout<: Tuple ,D<: Storage ,Values<: Tuple }
237234 types = fieldtypes (Layout)
@@ -243,7 +240,7 @@ bitwidth(::Type{<:NarrowTuple{Ts}}) where Ts = bitwidth(Ts)
243240 length (widths) == length (types) ||
244241 throw (ArgumentError (" expected $(length (types)) field bitwidths for $Layout , got $(length (widths)) " ))
245242 for (T, W) in zip (types, widths)
246- is_pad_type (T) && continue
243+ T <: Pad && continue
247244 1 <= W <= 8 * sizeof (T) ||
248245 throw (ArgumentError (" bitwidth($T ) must be in 1:$(8 * sizeof (T)) , got $W " ))
249246 end
@@ -257,8 +254,8 @@ bitwidth(::Type{<:NarrowTuple{Ts}}) where Ts = bitwidth(Ts)
257254 if D <: Unsigned
258255 terms = Any[]
259256 for (index, (T, W, start)) in enumerate (zip (types, widths, starts))
260- if is_pad_type (T)
261- is_one_pad_type (T) || continue
257+ if T <: Pad
258+ T <: OnePad || continue
262259 expr = :($ D ($ (narrow_mask (D, W))))
263260 else
264261 U = unsigned_type (sizeof (T))
@@ -289,8 +286,8 @@ bitwidth(::Type{<:NarrowTuple{Ts}}) where Ts = bitwidth(Ts)
289286 dest_shift = first_bit - byte_first_bit
290287 width = last_bit - first_bit + 1
291288
292- if is_pad_type (T)
293- is_one_pad_type (T) || continue
289+ if T <: Pad
290+ T <: OnePad || continue
294291 expr = :(UInt8 ($ (_low_mask (width))))
295292 else
296293 expr = field_raw_expr (:xs , field_index, T)
@@ -318,7 +315,7 @@ function materialize_narrow_tuple_values(::Type{Ts}, xs::Tuple) where Ts<:Tuple
318315 value_index = 1
319316
320317 for T in fieldtypes (Ts)
321- if is_pad_type (T)
318+ if T <: Pad
322319 push! (result, pad_value (T))
323320 else
324321 push! (result, values[value_index])
@@ -346,7 +343,7 @@ NarrowTuple(xs::Ts) where Ts<:Tuple = NarrowTuple{layout_tuple_type(Ts)}(xs)
346343 length (widths) == length (types) ||
347344 throw (ArgumentError (" expected $(length (types)) field bitwidths for $Ts , got $(length (widths)) " ))
348345 for (T, W) in zip (types, widths)
349- is_pad_type (T) && continue
346+ T <: Pad && continue
350347 1 <= W <= 8 * sizeof (T) ||
351348 throw (ArgumentError (" bitwidth($T ) must be in 1:$(8 * sizeof (T)) , got $W " ))
352349 end
@@ -360,7 +357,7 @@ NarrowTuple(xs::Ts) where Ts<:Tuple = NarrowTuple{layout_tuple_type(Ts)}(xs)
360357
361358 if D <: Unsigned
362359 for (index, (T, W, start)) in enumerate (zip (types, widths, starts))
363- if is_pad_type (T)
360+ if T <: Pad
364361 push! (values, pad_value (T))
365362 continue
366363 end
@@ -375,7 +372,7 @@ NarrowTuple(xs::Ts) where Ts<:Tuple = NarrowTuple{layout_tuple_type(Ts)}(xs)
375372 end
376373
377374 for (field_index, (T, W, field_first_bit)) in enumerate (zip (types, widths, starts))
378- if is_pad_type (T)
375+ if T <: Pad
379376 push! (values, pad_value (T))
380377 continue
381378 end
@@ -419,18 +416,18 @@ end
419416
420417 if D <: Unsigned
421418 for (T, W, start) in zip (types, widths, starts)
422- is_pad_type (T) || continue
419+ T <: Pad || continue
423420
424421 actual = :data
425422 start > 0 && (actual = :($ actual >>> $ start))
426423 actual = :($ actual & $ (narrow_mask (D, W)))
427- expected = is_one_pad_type (T) ? narrow_mask (D, W) : zero (D)
424+ expected = T <: OnePad ? narrow_mask (D, W) : zero (D)
428425 message = " packed data does not match padding bits for $T "
429426 push! (checks, :($ actual == $ expected || throw (ArgumentError ($ message))))
430427 end
431428 else
432429 for (T, W, field_first_bit) in zip (types, widths, starts)
433- is_pad_type (T) || continue
430+ T <: Pad || continue
434431
435432 field_last_bit = field_first_bit + W - 1
436433 first_byte = field_first_bit ÷ 8
449446 actual = :(Core. getfield (data, $ (byte_index + 1 )))
450447 source_shift > 0 && (actual = :($ actual >>> $ source_shift))
451448 width < 8 && (actual = :($ actual & $ (_low_mask (width))))
452- expected = is_one_pad_type (T) ? _low_mask (width) : 0x00
449+ expected = T <: OnePad ? _low_mask (width) : 0x00
453450 message = " packed data does not match padding bits for $T "
454451 push! (checks, :($ actual == $ expected || throw (ArgumentError ($ message))))
455452 end
@@ -471,11 +468,11 @@ Base.iterate(nt::NarrowTuple, state...) = iterate(Tuple(nt), state...)
471468Base. convert (:: Type{Values} , nt:: NarrowTuple ) where Values<: Tuple = convert (Values, Tuple (nt))
472469Base. reinterpret (:: Type{T} , nt:: NarrowTuple ) where T = reinterpret (T, nt. data)
473470
474- Base. show (io:: IO , :: ZeroPadValue {N} ) where N = print (io, " BitPacking. ZeroPad(" , N, " )" )
475- Base. show (io:: IO , :: OnePadValue {N} ) where N = print (io, " BitPacking. OnePad(" , N, " )" )
471+ Base. show (io:: IO , :: ZeroPad {N} ) where N = print (io, ZeroPad, " (" , N, " )" )
472+ Base. show (io:: IO , :: OnePad {N} ) where N = print (io, OnePad, " (" , N, " )" )
476473
477474function Base. show (io:: IO , nt:: NarrowTuple )
478- print (io, " @NarrowTuple(" )
475+ print (io, var "@NarrowTuple" , " (" )
479476 for (i, x) in enumerate (Tuple (nt))
480477 i > 1 && print (io, " , " )
481478 show (io, x)
@@ -502,7 +499,7 @@ function Base.show(io::IO, ::Type{T}) where {T<:NarrowTuple}
502499 return invoke (show, Tuple{IO,Type}, io, T)
503500 end
504501
505- print (io, " @NarrowTuple{" )
502+ print (io, var "@NarrowTuple" , " {" )
506503 show_narrow_tuple_fields (io, Ts)
507504 print (io, " }" )
508505end
0 commit comments