Skip to content

Instantly share code, notes, and snippets.

@koehlma
Last active December 16, 2015 11:18
Show Gist options
  • Save koehlma/5425959 to your computer and use it in GitHub Desktop.
Save koehlma/5425959 to your computer and use it in GitHub Desktop.
PDEF (=Portable Data Exchange Format) is a JSON like format that encodes into binary data.
# -*- coding:utf-8 -*-
#
# Copyright (C) 2013, Maximilian Köhl <[email protected]>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Version 0.0.1 - Draft
import struct
def encode_varint(integer):
data = []
while integer > 127:
data.append(integer & 0x7f | 0x80)
integer >>= 7
data.append(integer)
return bytes(data)
def decode_varint(buffer):
integer, shift = 0, 0
while True:
byte = buffer.get_byte()
integer |= (byte & 0x7f) << shift
if not (byte & 0x80):
return integer
shift += 7
def encode(structure):
if isinstance(structure, list):
data = b''.join([encode(item) for item in structure])
return b'\x10' + encode_varint(len(data)) + data
elif isinstance(structure, tuple):
data = b''.join([encode(item) for item in structure])
return b'\x11' + encode_varint(len(data)) + data
elif isinstance(structure, dict):
data = b''.join([encode((key, val)) for key, val in structure.items()])
return b'\x12' + encode_varint(len(data)) + data
elif isinstance(structure, bytes):
return b'\x20' + encode_varint(len(structure)) + structure
elif isinstance(structure, str):
data = structure.encode('utf-8')
return b'\x21' + encode_varint(len(data)) + data
elif structure is True:
return b'\x30'
elif structure is False:
return b'\x31'
elif structure is None:
return b'\x32'
elif isinstance(structure, int):
if structure >= 0:
return b'\x40' + encode_varint(structure)
else:
return b'\x41' + encode_varint(-structure)
elif isinstance(structure, float):
return b'\x42' + struct.pack('!f', structure)
def decode(buffer):
field = buffer.get_byte()
if field in (0x10, 0x11, 0x12):
size, inital = decode_varint(buffer), buffer.pointer
result = []
while buffer.pointer - inital < size:
result.append(decode(buffer))
if field == 0x10:
return result
elif field == 0x11:
return tuple(result)
else:
return dict(result)
elif field in (0x20, 0x21):
size = decode_varint(buffer)
result = buffer.get_bytes(size)
if field == 0x20:
return result
else:
return result.decode('utf-8')
elif field == 0x30:
return True
elif field == 0x31:
return False
elif field == 0x32:
return None
elif field in (0x40, 0x41):
integer = decode_varint(buffer)
return integer if field == 0x40 else -integer
elif field == 0x42:
return struct.unpack('!f', buffer.get_bytes(4))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment