asn1rt: 2nd step to enable non UNIQUE keys into table constraint

This commit is contained in:
mich 2018-12-03 19:37:55 +01:00
parent 199666cfdf
commit 8144f262e3
4 changed files with 126 additions and 53 deletions

View File

@ -341,40 +341,76 @@ class ASN1Obj(Element):
.format(self.fullname(), val)))
if self._SAFE_BNDTAB and self._const_tab and self._const_tab_at:
# check val against a constraint defined within the table constraint
try:
const_val = self._get_tab_obj()
except Exception as err:
const_val_type, const_val = self._get_tab_obj()
if const_val_type == CLASET_NONE:
if not self._SILENT:
asnlog('%s._from_per_ws: %s, unable to retrieve a defined object, %s'\
% (self.__class__.__name__, self._name, err))
else:
if self._mode == MODE_VALUE and val != const_val or \
self._mode == MODE_SET and val not in const_val:
elif self._mode == MODE_VALUE and const_val_type == CLASET_UNIQ:
if val != const_val:
raise(ASN1ObjErr('{0}: value out of table constraint, {1!r}'\
.format(self.fullname(), val)))
elif self._mode == MODE_SET or const_val_type == CLASET_MULT:
if val not in const_val:
raise(ASN1ObjErr('{0}: value out of table constraint, {1!r}'\
.format(self.fullname(), val)))
def _get_tab_obj(self):
ret = (CLASET_NONE, None)
try:
IndIdent = self._get_obj_by_path(self._const_tab_at)._const_tab_id
IndVal = self._get_val_by_path(self._const_tab_at)
except:
IndVal = self._get_val_by_path(self._const_tab_at)
except Exception:
return ret
cla_val_type, cla_val = self._const_tab.get(IndIdent, IndVal)
if cla_val_type == CLASET_UNIQ and self._const_tab_id in cla_val:
return (CLASET_UNIQ, cla_val[self._const_tab_id])
elif cla_val_type == CLASET_MULT:
# filter cla_val for the given tab_id
cla_val = [val[self._const_tab_id] for val in cla_val if self._const_tab_id in val]
if len(cla_val) > 1:
return (CLASET_MULT, vals)
elif cla_val:
return (CLASET_UNIQ, vals[0])
return ret
def _get_tab_obj_uniq(self):
try:
IndIdent = self._get_obj_by_path(self._const_tab_at)._const_tab_id
IndVal = self._get_val_by_path(self._const_tab_at)
except Exception:
raise(ASN1ObjErr('{0}: invalid table constraint @ path, {1!r}'\
.format(self.fullname(), self._const_tab_at)))
try:
claval = self._const_tab(IndIdent, IndVal)
except:
raise(ASN1ObjErr('{0}: invalid identifier {1} for the table constraint'\
.format(self.fullname(), IndIdent)))
claval = self._const_tab.get_uniq(IndIdent, IndVal)
if claval is None:
raise(ASN1ObjErr('{0}: non-existent value {1} for identifier {2} in the table constraint'\
.format(self.fullname(), IndVal, IndIdent)))
else:
try:
return claval[self._const_tab_id]
except:
except KeyError:
raise(ASN1ObjErr('{0}: non-existent ident {1} within table constraint value'\
.format(self.fullname(), self._const_tab_id)))
def _get_tab_obj_nonuniq(self):
ret = []
try:
IndIdent = self._get_obj_by_path(self._const_tab_at)._const_tab_id
IndVal = self._get_val_by_path(self._const_tab_at)
except Exception:
return []
clavals = self._const_tab.get_mult(IndIdent, IndVal)
if not clavals:
return []
else:
ret = []
for claval in clavals:
try:
ret.append( claval[self._const_tab_id] )
except KeyError:
pass
return ret
#--------------------------------------------------------------------------#
# user-friendly generic representation
#--------------------------------------------------------------------------#

View File

@ -169,12 +169,25 @@ Specific method:
# this is using the _lut attribute, which is built at module init
# for every CLASS set defined at the root of a module
if hasattr(self, '_lut'):
if key == self._lut['__lut__']:
return self._lut.get(val, (CLASET_NONE, None))
if key == self._lut['__key__']:
try:
return self._lut[val]
except KeyError:
return (CLASET_NONE, None)
if self._CLASET_MULT:
return self.get_mult(key, val)
ret = self.get_mult(key, val)
if len(ret) > 1:
return (CLASET_MULT, ret)
elif ret:
return (CLASET_UNIQ, ret[0])
else:
(CLASET_NONE, None)
else:
return self.get_uniq(key, val)
ret = self.get_uniq(key, val)
if ret:
return (CLASET_UNIQ, ret)
else:
return (CLASET_NONE, None)
def get_uniq(self, name, val):
# this is using an enumeration of all CLASS set of values,

View File

@ -234,13 +234,18 @@ Single value: Python 2-tuple
def _from_per_ws(self, char):
# try to get a defined object from a table constraint
if self._TAB_LUT and self._const_tab and self._const_tab_at:
try:
Obj = self._get_tab_obj()
except Exception as err:
const_obj_type, const_obj = self._get_tab_obj()
if const_obj_type == CLASET_NONE:
if not self._SILENT:
asnlog('OPEN._from_per_ws: %s, unable to retrieve a table-looked up object, %s'\
% (self.fullname(), err))
Obj = None
elif const_obj_type == CLASET_UNIQ:
Obj = const_obj
else:
# const_obj_type == CLASET_MULT
# with PER, no tag to select a given object
Obj = const_obj[0]
else:
# TODO: another way to provide a (set of) potential defined object(s)
# is to look into value constraint self._const_val
@ -250,7 +255,7 @@ Single value: Python 2-tuple
#
if Obj is None:
if self._const_val:
asnlog('OPEN._from_per_ws: %s, potential type constraint(s) available'\
asnlog('OPEN._from_per_ws: %s, potential type constraint(s) available but unused'\
% self.fullname())
val, GEN = ASN1CodecPER.decode_unconst_open_ws(char, wrapped=None)
assert( isinstance(val, bytes_types) )
@ -268,13 +273,18 @@ Single value: Python 2-tuple
def _from_per(self, char):
# try to get a defined object from a table constraint
if self._TAB_LUT and self._const_tab and self._const_tab_at:
try:
Obj = self._get_tab_obj()
except Exception as err:
const_obj_type, const_obj = self._get_tab_obj()
if const_obj_type == CLASET_NONE:
if not self._SILENT:
asnlog('OPEN._from_per: %s, unable to retrieve a defined object, %s'\
asnlog('OPEN._from_per: %s, unable to retrieve a table-looked up object, %s'\
% (self.fullname(), err))
Obj = None
elif const_obj_type == CLASET_UNIQ:
Obj = const_obj
else:
# const_obj_type == CLASET_MULT
# with PER, no tag to select a given object
Obj = const_obj[0]
else:
# TODO: another way to provide a (set of) potential defined object(s)
# is to look into value constraint self._const_val
@ -285,7 +295,7 @@ Single value: Python 2-tuple
val = ASN1CodecPER.decode_unconst_open(char, wrapped=Obj)
if Obj is None:
if self._const_val:
asnlog('OPEN._from_per: %s, potential type constraint(s) available'\
asnlog('OPEN._from_per: %s, potential type constraint(s) available but unused'\
% self.fullname())
assert( isinstance(val, bytes_types) )
self._val = ('_unk_004', val)
@ -340,12 +350,17 @@ Single value: Python 2-tuple
tag, Obj = (cl, tval), None
# try to get a defined object from a table constraint
if self._TAB_LUT and self._const_tab and self._const_tab_at:
try:
Obj = self._get_tab_obj()
except Exception as err:
const_obj_type, const_obj = self._get_tab_obj()
if const_obj_type == CLASET_NONE:
if not self._SILENT:
asnlog('OPEN._decode_ber_cont_ws: %s, unable to retrieve an object in the table '\
'constraint (%s)' % (self.fullname(), err))
asnlog('OPEN._decode_ber_cont_ws: %s, unable to retrieve a table-looked up object, %s'\
% (self.fullname(), err))
Obj = None
elif const_obj_type == CLASET_UNIQ:
Obj = const_obj
else:
# const_obj_type == CLASET_MULT
Obj = get_obj_by_tag(self, tag, const_obj)
#
elif self._const_val is not None:
# another way to provide a (set of) potential defined object(s)
@ -426,12 +441,17 @@ Single value: Python 2-tuple
tag, Obj = (cl, tval), None
# try to get a defined object from a table constraint
if self._TAB_LUT and self._const_tab and self._const_tab_at:
try:
Obj = self._get_tab_obj()
except Exception as err:
const_obj_type, const_obj = self._get_tab_obj()
if const_obj_type == CLASET_NONE:
if not self._SILENT:
asnlog('OPEN._decode_ber_cont: %s, unable to retrieve an object in the table '\
'constraint (%s)' % (self.fullname(), err))
asnlog('OPEN._decode_ber_cont: %s, unable to retrieve a table-looked up object, %s'\
% (self.fullname(), err))
Obj = None
elif const_obj_type == CLASET_UNIQ:
Obj = const_obj
else:
# const_obj_type == CLASET_MULT
Obj = get_obj_by_tag(self, tag, const_obj)
#
elif self._const_val is not None:
# another way to provide a (set of) potential defined object(s)

View File

@ -458,14 +458,17 @@ def match_tag(Obj, tag):
# Obj is an untagged OPEN / ANY object: this is a bit more tricky again
if Obj._TAB_LUT and Obj._const_tab and Obj._const_tab_at:
# a usable table constraint is defined
try:
ConstObj = Obj._get_tab_obj()
except Exception as err:
# unable to retrieve a corresponding object in the table
const_obj_type, const_obj = Obj._get_tab_obj()
if const_obj_type == CLASET_NONE:
return 3
elif const_obj_type == CLASET_UNIQ:
ret = match_tag(const_obj, tag)
if ret:
return ret
else:
if ConstObj is not None:
ret = match_tag(ConstObj, tag)
# const_obj_type == CLASET_MULT:
for obj in const_obj:
ret = match_tag(obj, tag)
if ret:
return ret
elif Obj._const_val:
@ -491,22 +494,23 @@ def match_tag(Obj, tag):
assert()
return 0
def get_obj_by_tag(ObjOpen, tag):
def get_obj_by_tag(ObjOpen, tag, ConstList=None):
"""Check within the value constraint of an OPEN / ANY object ObjOpen
for a given tag (tag_class, tag_value) and return the matching object,
in case the tag correspond
in case the tag matches
"""
for ConstObj in ObjOpen._const_val.root:
if ConstObj.tagc and tag == ConstObj._tagc[0]:
if not ConstList:
# build ConstList from ObjOpen._const_val.root and ObjOpen._const_val.ext
ConstList = ObjOpen._const_val.root
if ObjOpen._const_val.ext:
ConstList = ConstList + ObjOpen._const_val.ext
#
for ConstObj in ConstList:
if ConstObj._tagc and tag == ConstObj._tagc[0]:
return ConstObj
elif ConstObj.TYPE == TYPE_CHOICE and tag in ConstObj._cont_tags:
return ConstObj
if ObjOpen._const_val.ext:
for ConstObj in ObjOpen._const_val.ext:
if ConstObj.tagc and tag == ConstObj._tagc[0]:
return ConstObj
elif ConstObj.TYPE == TYPE_CHOICE and tag in ConstObj._cont_tags:
return ConstObj
#
return None
#------------------------------------------------------------------------------#