# pack & unpack

<http://blog.bigbinary.com/2011/07/20/ruby-pack-unpack.html>

<http://www.blackbytes.info/2017/01/read-binary-data/?tl_inbound=1&tl_target_all=1&tl_form_type=1&tl_period_type=1>

## unpack = `String#unpack`

> Endian = Byte Order
>
> MSB, LSB = bit order
>
> 1 byte = 2 nibbles = 8bits

### bit

`C` Ascii = 67 `(2^0 + 2^1 + 2^6)`

```ruby
'C'.unpack('b*') # LSB
# => ["11000010"]

'C'.unpack('B*') # MSB
# => ["01000011"]
```

### String to ASCII Values

`C*` = `8-bit unsigned integer`

```ruby
"hello".unpack('C*')
=> [104, 101, 108, 108, 111]
```

### hex

`104.to_s 16` = hex value of the string.

```ruby
"hello".unpack('C*').map {|e| e.to_s 16}
=> ["68", "65", "6c", "6c", "6f"]
```

You can also do

```ruby
> "hello".unpack('H*')
=> ["68656c6c6f"]
```

```ruby
"hello".unpack('H*') # high nibble first
=> ["68656c6c6f"]

"hello".unpack('h*')# low nibble first
=> ["8656c6c6f6"]
```

```ruby
6 8 # high nibble first
X
8 6 # low nibble first
```

### count

```ruby
> "hello".unpack('CC')
=> [104, 101]

> "hello".unpack('CCC')
=> [104, 101, 108]

> "hello".unpack('CCCCC')
=> [104, 101, 108, 108, 111]
```

```ruby
"aa".unpack('b8B8') # mix MSB and LSB
=> ["10000110", "01100001"]
```

## pack = `Array#pack`

`pack` = read the stored data.

```ruby
[1000001].pack('C') # binary -> 8 bit unsigned integer
=> "A"

['1000001'].pack('b*')
=> "A"
```

```ruby
['A'].pack('H') # hex -> Ascii
=> "\xA0" # no Ascii for A0
['a'].pack('H') 
=> "\xA0" # in hex, 'A' = 'a'
['a'].pack('h')
=> "\n" # in Ascii table, '\x0A' = new line
```

## Binary File Parsing

or parse image

```ruby
binary_data     = "\x05\x00\x68\x65\x6c\x6c\x6f"
length, message = binary_data.unpack("Sa*")

# [5, "hello"]
```
