-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3 from Bhargavasomu/ssz_bool
Add basic API infrastructure with Boolean Support
- Loading branch information
Showing
7 changed files
with
239 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
from .codec import ( # noqa: F401 | ||
encode, | ||
decode | ||
) | ||
|
||
from .exceptions import ( # noqa: F401 | ||
SSZException, | ||
EncodingError, | ||
DecodingError, | ||
SerializationError, | ||
DeserializationError, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
from eth_utils import ( | ||
is_bytes, | ||
) | ||
|
||
from ssz.exceptions import ( | ||
DecodingError, | ||
) | ||
from ssz.utils import ( | ||
infer_sedes, | ||
) | ||
|
||
|
||
def encode(obj): | ||
""" | ||
Encode object in SSZ format. | ||
""" | ||
serialized_obj = infer_sedes(obj).serialize(obj) | ||
return serialized_obj | ||
|
||
|
||
def decode(ssz, sedes): | ||
""" | ||
Decode a SSZ encoded object. | ||
""" | ||
if not is_bytes(ssz): | ||
raise DecodingError('Can only decode SSZ bytes, got type %s' % type(ssz).__name__, ssz) | ||
|
||
obj = sedes.deserialize(ssz) | ||
return obj |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
class SSZException(Exception): | ||
""" | ||
Base class for exceptions raised by this package. | ||
""" | ||
pass | ||
|
||
|
||
class EncodingError(SSZException): | ||
""" | ||
Exception raised if encoding fails. | ||
""" | ||
|
||
def __init__(self, message, obj): | ||
super(EncodingError, self).__init__(message) | ||
self.obj = obj | ||
|
||
|
||
class DecodingError(SSZException): | ||
""" | ||
Exception raised if decoding fails. | ||
""" | ||
|
||
def __init__(self, message, ssz): | ||
super(DecodingError, self).__init__(message) | ||
self.ssz = ssz | ||
|
||
|
||
class SerializationError(SSZException): | ||
""" | ||
Exception raised if serialization fails. | ||
""" | ||
|
||
def __init__(self, message, obj): | ||
super(SerializationError, self).__init__(message) | ||
self.obj = obj | ||
|
||
|
||
class DeserializationError(SSZException): | ||
""" | ||
Exception raised if deserialization fails. | ||
""" | ||
|
||
def __init__(self, message, serial): | ||
super(DeserializationError, self).__init__(message) | ||
self.serial = serial |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
from .boolean import ( # noqa: F401 | ||
boolean, | ||
Boolean, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
from ssz.exceptions import ( | ||
DeserializationError, | ||
SerializationError, | ||
) | ||
|
||
|
||
class Boolean: | ||
""" | ||
A sedes for booleans. | ||
""" | ||
def serialize(self, obj): | ||
if not isinstance(obj, bool): | ||
raise SerializationError('Can only serialize boolean values', obj) | ||
|
||
if obj is False: | ||
return b'\x00' | ||
elif obj is True: | ||
return b'\x01' | ||
else: | ||
raise Exception("Invariant: no other options for boolean values") | ||
|
||
def deserialize(self, serialized_obj): | ||
if serialized_obj == b'\x00': | ||
return False | ||
elif serialized_obj == b'\x01': | ||
return True | ||
else: | ||
raise DeserializationError( | ||
'Invalid serialized boolean. Must be either 0x01 or 0x00', | ||
serialized_obj | ||
) | ||
|
||
|
||
boolean = Boolean() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
from ssz.sedes import ( | ||
boolean, | ||
) | ||
|
||
|
||
def is_sedes(obj): | ||
""" | ||
Check if `obj` is a sedes object. | ||
A sedes object is characterized by having the methods | ||
`serialize(obj)` and `deserialize(serial)`. | ||
""" | ||
return hasattr(obj, 'serialize') and hasattr(obj, 'deserialize') | ||
|
||
|
||
def infer_sedes(obj): | ||
""" | ||
Try to find a sedes objects suitable for a given Python object. | ||
""" | ||
if isinstance(obj, bool): | ||
return boolean | ||
|
||
msg = 'Did not find sedes handling type {}'.format(type(obj).__name__) | ||
raise TypeError(msg) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
import pytest | ||
|
||
from ssz import ( | ||
DeserializationError, | ||
SerializationError, | ||
decode, | ||
encode, | ||
) | ||
from ssz.sedes import ( | ||
Boolean, | ||
) | ||
|
||
|
||
@pytest.mark.parametrize( | ||
'value,expected', | ||
( | ||
(True, b'\x01'), | ||
(False, b'\x00'), | ||
), | ||
) | ||
def test_boolean_serialize_values(value, expected): | ||
sedes = Boolean() | ||
assert sedes.serialize(value) == expected | ||
|
||
|
||
@pytest.mark.parametrize( | ||
'value', | ||
( | ||
None, | ||
1, | ||
0, | ||
'True', | ||
b'True', | ||
), | ||
) | ||
def test_boolean_serialize_bad_values(value): | ||
sedes = Boolean() | ||
with pytest.raises(SerializationError): | ||
sedes.serialize(value) | ||
|
||
|
||
@pytest.mark.parametrize( | ||
'value,expected', | ||
( | ||
(b'\x01', True), | ||
(b'\x00', False), | ||
), | ||
) | ||
def test_boolean_deserialization(value, expected): | ||
sedes = Boolean() | ||
assert sedes.deserialize(value) == expected | ||
|
||
|
||
@pytest.mark.parametrize( | ||
'value', | ||
( | ||
b' ', | ||
b'\x02', | ||
b'\x00\x00', | ||
b'\x01\x00', | ||
b'\x00\x01', | ||
b'\x01\x01', | ||
), | ||
) | ||
def test_boolean_deserialization_bad_value(value): | ||
sedes = Boolean() | ||
with pytest.raises(DeserializationError): | ||
sedes.deserialize(value) | ||
|
||
|
||
@pytest.mark.parametrize( | ||
'value,expected', | ||
( | ||
(True, True), | ||
(False, False), | ||
), | ||
) | ||
def test_boolean_round_trip(value, expected): | ||
sedes = Boolean() | ||
assert sedes.deserialize(sedes.serialize(value)) == expected | ||
|
||
|
||
@pytest.mark.parametrize( | ||
'value,expected', | ||
( | ||
(True, True), | ||
(False, False), | ||
), | ||
) | ||
def test_boolean_round_trip_codec(value, expected): | ||
sedes = Boolean() | ||
assert decode(encode(value), sedes) == expected |