Skip to content
This repository has been archived by the owner on Jan 4, 2024. It is now read-only.

Commit

Permalink
Merge pull request #12 from alexras/alexras/fix-string-decode
Browse files Browse the repository at this point in the history
Fix string decoding.
  • Loading branch information
alexras authored Dec 3, 2018
2 parents c6c0e93 + 7d02825 commit b65bb7b
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 32 deletions.
2 changes: 1 addition & 1 deletion bread/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from .lifecycle import *

__title__ = 'bread'
__version__ = '2.3.0'
__version__ = '3.0.0'
__author__ = 'Alex Rasmussen'
__license__ = 'MIT'
__copyright__ = 'Copyright 2015 Alex Rasmussen'
6 changes: 3 additions & 3 deletions bread/string.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@
from .field import BreadField


def string(length):
def string(length, encoding='utf-8'):
def make_string_field(parent, **field_options):
length_in_bits = length * 8

def encode_string(value):
if type(value) != bytes:
value = value.encode('utf-8')
value = value.encode(encoding)

return BitArray(bytes=value)

def decode_string(encoded):
return encoded.bytes
return encoded.bytes.decode(encoding)

return BreadField(length_in_bits, encode_string, decode_string,
str_format=field_options.get('str_format', None))
Expand Down
4 changes: 2 additions & 2 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@
# built documents.
#
# The short X.Y version.
version = '2.3.0'
version = '3.0.0'
# The full version, including alpha/beta/rc tags.
release = '2.3.0'
release = '3.0.0'

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
Expand Down
2 changes: 1 addition & 1 deletion docs/source/spec_language.rst
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ For convenience and improved readability, the following shorthands are defined:
Strings
~~~~~~~

``string(length)`` - the next ``length`` bytes represent a string of the given length
``string(length, encoding)`` - the next ``length`` bytes represent a string of the given length. You can pick an encoding for the strings to encode and decode in; the default is ``utf-8``.

Booleans
~~~~~~~~
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from setuptools import setup

setup(name='bread',
version='2.3.0',
version='3.0.0',
description='Binary format parsing made easier',
url='https://github.com/alexras/bread',
author='Alex Rasmussen',
Expand Down
55 changes: 31 additions & 24 deletions test.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
#!/usr/bin/env python
import pytest

import struct, sys, pprint, unittest, itertools, tempfile, os, json

import bread as b
import itertools
import json
import os
import struct
import tempfile

import bitstring
import bread as b
import pytest

# Shared structs for bread struct test

Expand Down Expand Up @@ -94,10 +97,10 @@ def test_simple_struct():

assert len(test) == 168

assert test.flag_one == True
assert test.flag_two == False
assert test.flag_three == True
assert test.flag_four == False
assert test.flag_one
assert not test.flag_two
assert test.flag_three
assert not test.flag_four
assert test.first == 0xfb
assert test.blah == 0xdddd

Expand Down Expand Up @@ -169,10 +172,10 @@ def test_updates_do_not_leak():

assert len(test2) == 168

assert test2.flag_one == False
assert test2.flag_two == False
assert test2.flag_three == False
assert test2.flag_four == True
assert not test2.flag_one
assert not test2.flag_two
assert not test2.flag_three
assert test2.flag_four
assert test2.first == 0xde
assert test2.blah == 0xfafe

Expand All @@ -182,10 +185,10 @@ def test_updates_do_not_leak():

# Updating test2 shouldn't impact test

assert test.flag_one == True
assert test.flag_two == False
assert test.flag_three == True
assert test.flag_four == False
assert test.flag_one
assert not test.flag_two
assert test.flag_three
assert not test.flag_four
assert test.first == 0xfb
assert test.blah == 0xdddd

Expand Down Expand Up @@ -269,7 +272,7 @@ def test_nested_struct():

assert supernested_test.__offsets__.dummy == current_byte * 8
current_byte += 1
assert supernested_test.dummy.ok == False
assert not supernested_test.dummy.ok

assert b.write(supernested_test, deeply_nested_struct) == bytearray(list(range(34)) + [0b0])

Expand Down Expand Up @@ -343,7 +346,7 @@ def test_conditional():
true_test = b.parse(true_data, conditional_test)

assert true_test._length == 13
assert true_test.qux == True
assert true_test.qux
assert hasattr(true_test, "frooz")
assert not hasattr(true_test, "fooz")
assert true_test.frooz == 0b1001
Expand All @@ -361,7 +364,7 @@ def test_conditional():
false_test = b.parse(false_data, conditional_test)

assert false_test._length == 17
assert false_test.qux == False
assert not false_test.qux
assert hasattr(false_test, "fooz")
assert not hasattr(false_test, "frooz")
assert false_test.fooz == 0b10010001
Expand Down Expand Up @@ -500,6 +503,7 @@ def test_array_of_conditionals():
assert test_parsed.foos[2].baz == 0b11
assert test_parsed._length == 32


def test_modifying_conditional_with_structs_that_have_different_lengths():
true_data = bitstring.BitArray(bytearray([0b11001010, 0b11101000]))
true_data.append('0b0')
Expand All @@ -510,6 +514,7 @@ def test_modifying_conditional_with_structs_that_have_different_lengths():
assert true_test._length == 17
assert true_test.fooz == 0b10010101


def test_field_properties_in_array():
array_endian_test = [
("little_arr", b.array(3, b.uint16), {"endianness": b.LITTLE_ENDIAN}),
Expand Down Expand Up @@ -600,26 +605,28 @@ def test_parse_str():

test_parsed = b.parse(test_str, test_struct)

assert test_parsed.str.decode('utf-8') == "gabbagabbahey"
assert test_parsed.str == "gabbagabbahey"


def test_str():
str_test = [("msg", b.string(5))]

data = bytearray([0x68, 0x65, 0x6c, 0x6c, 0x6f])
result = b.parse(data, str_test)
assert result.msg.decode('utf-8') == "hello"
assert result.msg == "hello"

assert b.write(result, str_test) == data

assert result.as_json() == json.dumps({'msg': 'hello'})


def test_str_unicode():
str_test = [("msg", b.string(5))]

data = bytearray([104, 101, 108, 108, 111])
result = b.parse(data, str_test)

assert result.msg.decode('utf-8') == "hello"
assert result.msg == "hello"
assert b.write(result, str_test) == data

result.msg = "abate"
Expand All @@ -628,7 +635,7 @@ def test_str_unicode():

edited_result = b.parse(output_data, str_test)

assert result.msg == "abate"
assert edited_result.msg == "abate"


def test_enum():
Expand Down Expand Up @@ -1068,7 +1075,7 @@ def test_new():

assert len(empty_struct) == 8 * 5 + 4

assert empty_struct.greeting == b'\x00\x00\x00\x00\x00'
assert empty_struct.greeting == b'\x00\x00\x00\x00\x00'.decode('utf-8')
assert empty_struct.age == 0

empty_struct.greeting = 'hello'
Expand Down

0 comments on commit b65bb7b

Please sign in to comment.