import string
from itertools import takewhile,islice
from types import *
import errors
from utils import AdvancedIterator
class InvalidData(errors.Standart):
pass
def _ext_str(itr):
dec_len=''.join(takewhile(lambda char:char!=':',itr))
try:
dec_len=int(dec_len)
except ValueError:
raise InvalidData(dec_len,"invalid string's length declaration")
ext_str=''.join(islice(itr,dec_len))
str_len=len(ext_str)
if dec_len!=str_len:
raise InvalidData(ext_str,"length of string (%(str_len)i) differs from "
"declared (%(dec_len)i)" %locals())
return ext_str
def _ext_int(itr):
# skipping 'i'
itr.shift()
ext_int=''.join(takewhile(lambda char:char!='e',itr))
try:
ext_int=int(ext_int)
except ValueError:
raise InvalidData,(ext_int,"is not an integer")
return ext_int
def _ext_list(itr):
# skipping 'l'
itr.shift()
ext_list=[]
for ichar in itr:
if ichar=='e':
break
else:
itr.shift(-1)
ext_list.append(_get_extractor(ichar)(itr))
return ext_list
def _ext_dict(itr):
# skipping 'd'
itr.shift()
ext_dict={}
for key_ichar in itr:
if key_ichar=='e':
break
else:
itr.shift(-1)
key=_get_extractor(key_ichar)(itr)
value=_get_extractor(itr._next())(itr)
ext_dict[key]=value
return ext_dict
def _enc_str(dec_str):
return '%i:%s' %(len(dec_str),dec_str)
def _enc_int(dec_int):
return 'i%ie' %dec_int
def _enc_list(dec_list):
return 'l%se' %''.join(_get_encoder(type(item))(item) for item in dec_list)
def _enc_dict(dec_dict):
content=''
for key in sorted(dec_dict.keys()):
if isinstance(key,(StringType,StringTypes)):
content+=(encode(key)+encode(dec_dict[key]))
else:
raise InvalidData(key,"dictionary keys must be strings")
return 'd%se' %content
def _enc_bool(dec_bool):
if dec_bool:
return _enc_int(1)
return _enc_int(0)
def _get_extractor(ichar):
if ichar in string.digits:
return _ext_str
elif ichar=='i':
return _ext_int
elif ichar=='l':
return _ext_list
elif ichar=='d':
return _ext_dict
else:
raise InvalidData(ichar,"invalid initial character")
def _get_encoder(type):
if type in (StringType,StringTypes):
return _enc_str
elif type in (IntType,LongType):
return _enc_int
elif type in (ListType,TupleType):
return _enc_list
elif type is DictType:
return _enc_dict
elif type is BooleanType:
return _enc_bool
else:
raise ValueError,"unsupported value type"
def decode(be_data):
return _get_extractor(be_data[0])(AdvancedIterator(be_data))
def encode(value):
return _get_encoder(type(value))(value)