papi: support default for type alias decaying to basetype
Add PAPI support for VppTypeAlias decaying to BaseType. E.g vl_api_interface_index_t sw_if_index [default=0xffffffff] Type: feature Signed-off-by: Ole Troan <ot@cisco.com> Change-Id: I2061392157c9c11fbb0ff9e5406ea65489b017e9
This commit is contained in:
@ -204,7 +204,7 @@ define sw_interface_dump
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
vl_api_interface_index_t sw_if_index;
|
||||
vl_api_interface_index_t sw_if_index [default=0xFFFFFFFF];
|
||||
bool name_filter_valid;
|
||||
string name_filter[];
|
||||
};
|
||||
|
@ -66,7 +66,32 @@ def conversion_unpacker(data, field_type):
|
||||
return vpp_format.conversion_unpacker_table[field_type](data)
|
||||
|
||||
|
||||
class BaseTypes(object):
|
||||
# TODO: post 20.01, remove inherit from object.
|
||||
class Packer(object):
|
||||
options = {}
|
||||
|
||||
def pack(self, data, kwargs):
|
||||
raise NotImplementedError
|
||||
|
||||
def unpack(self, data, offset, result=None, ntc=False):
|
||||
raise NotImplementedError
|
||||
|
||||
# override as appropriate in subclasses
|
||||
def _get_packer_with_options(self, f_type, options):
|
||||
return types[f_type]
|
||||
|
||||
def get_packer_with_options(self, f_type, options):
|
||||
if options is not None:
|
||||
try:
|
||||
return self._get_packer_with_options(f_type, options)
|
||||
except IndexError:
|
||||
raise VPPSerializerValueError(
|
||||
"Options not supported for {}{} ({})".
|
||||
format(f_type, types[f_type].__class__,
|
||||
options))
|
||||
|
||||
|
||||
class BaseTypes(Packer):
|
||||
def __init__(self, type, elements=0, options=None):
|
||||
base_types = {'u8': '>B',
|
||||
'i8': '>b',
|
||||
@ -99,8 +124,12 @@ class BaseTypes(object):
|
||||
def unpack(self, data, offset, result=None, ntc=False):
|
||||
return self.packer.unpack_from(data, offset)[0], self.packer.size
|
||||
|
||||
def _get_packer_with_options(self, f_type, options):
|
||||
c = types[f_type].__class__
|
||||
return c(f_type, options=options)
|
||||
|
||||
class String(object):
|
||||
|
||||
class String(Packer):
|
||||
def __init__(self, name, num, options):
|
||||
self.name = name
|
||||
self.num = num
|
||||
@ -150,6 +179,7 @@ types = {'u8': BaseTypes('u8'), 'u16': BaseTypes('u16'),
|
||||
|
||||
class_types = {}
|
||||
|
||||
|
||||
def vpp_get_type(name):
|
||||
try:
|
||||
return types[name]
|
||||
@ -161,7 +191,7 @@ class VPPSerializerValueError(ValueError):
|
||||
pass
|
||||
|
||||
|
||||
class FixedList_u8(object):
|
||||
class FixedList_u8(Packer):
|
||||
def __init__(self, name, field_type, num):
|
||||
self.name = name
|
||||
self.num = num
|
||||
@ -187,6 +217,7 @@ class FixedList_u8(object):
|
||||
raise VPPSerializerValueError(
|
||||
'Packing failed for "{}" {}'
|
||||
.format(self.name, kwargs))
|
||||
|
||||
def unpack(self, data, offset=0, result=None, ntc=False):
|
||||
if len(data[offset:]) < self.num:
|
||||
raise VPPSerializerValueError(
|
||||
@ -196,7 +227,7 @@ class FixedList_u8(object):
|
||||
return self.packer.unpack(data, offset)
|
||||
|
||||
|
||||
class FixedList(object):
|
||||
class FixedList(Packer):
|
||||
def __init__(self, name, field_type, num):
|
||||
self.num = num
|
||||
self.packer = types[field_type]
|
||||
@ -226,7 +257,7 @@ class FixedList(object):
|
||||
return result, total
|
||||
|
||||
|
||||
class VLAList(object):
|
||||
class VLAList(Packer):
|
||||
def __init__(self, name, field_type, len_field_name, index):
|
||||
self.name = name
|
||||
self.field_type = field_type
|
||||
@ -274,7 +305,7 @@ class VLAList(object):
|
||||
return r, total
|
||||
|
||||
|
||||
class VLAList_legacy():
|
||||
class VLAList_legacy(Packer):
|
||||
def __init__(self, name, field_type):
|
||||
self.packer = types[field_type]
|
||||
self.size = self.packer.size
|
||||
@ -304,7 +335,7 @@ class VLAList_legacy():
|
||||
return r, total
|
||||
|
||||
|
||||
class VPPEnumType(object):
|
||||
class VPPEnumType(Packer):
|
||||
def __init__(self, name, msgdef, options=None):
|
||||
self.size = types['u32'].size
|
||||
self.name = name
|
||||
@ -330,6 +361,7 @@ class VPPEnumType(object):
|
||||
def __bool__(self):
|
||||
return True
|
||||
|
||||
# TODO: Remove post 20.01.
|
||||
if sys.version[0] == '2':
|
||||
__nonzero__ = __bool__
|
||||
|
||||
@ -346,8 +378,12 @@ class VPPEnumType(object):
|
||||
x, size = types[self.enumtype].unpack(data, offset)
|
||||
return self.enum(x), size
|
||||
|
||||
def _get_packer_with_options(self, f_type, options):
|
||||
c = types[f_type].__class__
|
||||
return c(f_type, types[f_type].msgdef, options=options)
|
||||
|
||||
class VPPUnionType(object):
|
||||
|
||||
class VPPUnionType(Packer):
|
||||
def __init__(self, name, msgdef):
|
||||
self.name = name
|
||||
self.size = 0
|
||||
@ -397,9 +433,10 @@ class VPPUnionType(object):
|
||||
return self.tuple._make(r), maxsize
|
||||
|
||||
|
||||
class VPPTypeAlias(object):
|
||||
def __init__(self, name, msgdef):
|
||||
class VPPTypeAlias(Packer):
|
||||
def __init__(self, name, msgdef, options=None):
|
||||
self.name = name
|
||||
self.msgdef = msgdef
|
||||
t = vpp_get_type(msgdef['type'])
|
||||
if not t:
|
||||
raise ValueError('No such type: {}'.format(msgdef['type']))
|
||||
@ -418,6 +455,7 @@ class VPPTypeAlias(object):
|
||||
|
||||
types[name] = self
|
||||
self.toplevelconversion = False
|
||||
self.options = options
|
||||
|
||||
def pack(self, data, kwargs=None):
|
||||
if data and conversion_required(data, self.name):
|
||||
@ -426,11 +464,20 @@ class VPPTypeAlias(object):
|
||||
# Python 2 and 3 raises different exceptions from inet_pton
|
||||
except(OSError, socket.error, TypeError):
|
||||
pass
|
||||
if data is None: # Default to zero if not specified
|
||||
if self.options and 'default' in self.options:
|
||||
data = self.options['default']
|
||||
else:
|
||||
data = 0
|
||||
|
||||
return self.packer.pack(data, kwargs)
|
||||
|
||||
def _get_packer_with_options(self, f_type, options):
|
||||
c = types[f_type].__class__
|
||||
return c(f_type, types[f_type].msgdef, options=options)
|
||||
|
||||
def unpack(self, data, offset=0, result=None, ntc=False):
|
||||
if ntc == False and self.name in vpp_format.conversion_unpacker_table:
|
||||
if ntc is False and self.name in vpp_format.conversion_unpacker_table:
|
||||
# Disable type conversion for dependent types
|
||||
ntc = True
|
||||
self.toplevelconversion = True
|
||||
@ -441,7 +488,7 @@ class VPPTypeAlias(object):
|
||||
return t, size
|
||||
|
||||
|
||||
class VPPType(object):
|
||||
class VPPType(Packer):
|
||||
# Set everything up to be able to pack / unpack
|
||||
def __init__(self, name, msgdef):
|
||||
self.name = name
|
||||
@ -496,14 +543,12 @@ class VPPType(object):
|
||||
p = VLAList(f_name, f_type, f[3], length_index)
|
||||
self.packers.append(p)
|
||||
else:
|
||||
# Support default for basetypes and enums
|
||||
# default support for types that decay to basetype
|
||||
if 'default' in self.options:
|
||||
try:
|
||||
p = BaseTypes(f_type, 0, self.options)
|
||||
except KeyError:
|
||||
p = class_types[f_type](f_name, types[f_type].msgdef, self.options)
|
||||
p = self.get_packer_with_options(f_type, self.options)
|
||||
else:
|
||||
p = types[f_type]
|
||||
|
||||
self.packers.append(p)
|
||||
size += p.size
|
||||
|
||||
@ -545,7 +590,7 @@ class VPPType(object):
|
||||
# Return a list of arguments
|
||||
result = []
|
||||
total = 0
|
||||
if ntc == False and self.name in vpp_format.conversion_unpacker_table:
|
||||
if ntc is False and self.name in vpp_format.conversion_unpacker_table:
|
||||
# Disable type conversion for dependent types
|
||||
ntc = True
|
||||
self.toplevelconversion = True
|
||||
|
Reference in New Issue
Block a user