Module: Fontisan::Woff2::UInt255
- Defined in:
- lib/fontisan/woff2/uint255.rb
Overview
255UInt16 variable-length encoding per WOFF2 spec section 3.1.
Single source of truth for encoding and decoding this data type. All other WOFF2 code MUST delegate to this module — the previous inline copies had the code-byte mapping inverted for values ≥ 253.
Encoding table (per W3C spec pseudocode):
value range | encoding | bytes
----------------|-----------------------|------
0 .. 252 | literal | 1
253 .. 505 | code 255 + (v - 253) | 2
506 .. 761 | code 254 + (v - 506) | 2
762 .. 65535 | code 253 + uint16 | 3
Decoding (inverse):
code byte | meaning
----------|--------------------------------
0 .. 252 | literal value
253 | read uint16 → value
254 | read 1 byte → value + 506
255 | read 1 byte → value + 253
Constant Summary collapse
- WORD_CODE =
253- ONE_MORE_BYTE_CODE1 =
adds 253
255- ONE_MORE_BYTE_CODE2 =
adds 506
254- MAX_VALUE =
65_535
Class Method Summary collapse
-
.decode(io) ⇒ Integer?
Decode a 255UInt16 value from an IO stream.
-
.decode_at(data, pos) ⇒ Array(Integer, Integer)
Decode from a binary String at a given position.
-
.encode(value) ⇒ String
Encode a value (0..65535) into a 1-3 byte binary string.
Class Method Details
.decode(io) ⇒ Integer?
Decode a 255UInt16 value from an IO stream. Reads 1-3 bytes.
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/fontisan/woff2/uint255.rb', line 62 def self.decode(io) code = io.read(1)&.unpack1("C") return nil unless code case code when 0..252 code when WORD_CODE io.read(2)&.unpack1("n") when ONE_MORE_BYTE_CODE2 506 + (io.read(1)&.unpack1("C") || 0) when ONE_MORE_BYTE_CODE1 253 + (io.read(1)&.unpack1("C") || 0) end end |
.decode_at(data, pos) ⇒ Array(Integer, Integer)
Decode from a binary String at a given position. Returns the value and the new cursor position. Used by callers that index into a flat String rather than wrapping it in a StringIO.
85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/fontisan/woff2/uint255.rb', line 85 def self.decode_at(data, pos) code = data.getbyte(pos) pos += 1 case code when 0..252 [code, pos] when WORD_CODE [data[pos, 2].unpack1("n"), pos + 2] when ONE_MORE_BYTE_CODE2 [506 + data.getbyte(pos), pos + 1] when ONE_MORE_BYTE_CODE1 [253 + data.getbyte(pos), pos + 1] end end |
.encode(value) ⇒ String
Encode a value (0..65535) into a 1-3 byte binary string.
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/fontisan/woff2/uint255.rb', line 42 def self.encode(value) case value when 0..252 [value].pack("C") when 253..505 [ONE_MORE_BYTE_CODE1, value - 253].pack("C*") when 506..761 [ONE_MORE_BYTE_CODE2, value - 506].pack("C*") when 762..MAX_VALUE [WORD_CODE].pack("C") + [value].pack("n") else raise ArgumentError, "255UInt16 requires 0 <= value <= #{MAX_VALUE}, got #{value}" end end |