--- /dev/null
+# Copyright (C) 2015 Nippon Telegraph and Telephone Corporation.
+# Copyright (C) 2015 YAMAMOTO Takashi <yamamoto at valinux co jp>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import base64
+
+import six
+
+from ryu.lib import addrconv
+
+
+class TypeDescr(object):
+ pass
+
+
+class IntDescr(TypeDescr):
+ def __init__(self, size):
+ self.size = size
+
+ def to_user(self, binary):
+ i = 0
+ for _ in range(self.size):
+ c = binary[:1]
+ i = i * 256 + ord(c)
+ binary = binary[1:]
+ return i
+
+ def from_user(self, i):
+ binary = b''
+ for _ in range(self.size):
+ binary = six.int2byte(i & 255) + binary
+ i //= 256
+ return binary
+
+
+Int1 = IntDescr(1)
+Int2 = IntDescr(2)
+Int3 = IntDescr(3)
+Int4 = IntDescr(4)
+Int8 = IntDescr(8)
+Int9 = IntDescr(9)
+Int16 = IntDescr(16)
+
+
+def _split_str(s, n):
+ """
+ split string into list of strings by specified number.
+ """
+ length = len(s)
+ return [s[i:i + n] for i in range(0, length, n)]
+
+
+class IntDescrMlt(TypeDescr):
+ def __init__(self, length, num):
+ self.length = length
+ self.num = num
+ self.size = length * num
+
+ def to_user(self, binary):
+ assert len(binary) == self.size
+ lb = _split_str(binary, self.length)
+ li = []
+ for b in lb:
+ i = 0
+ for _ in range(self.length):
+ c = b[:1]
+ i = i * 256 + ord(c)
+ b = b[1:]
+ li.append(i)
+ return tuple(li)
+
+ def from_user(self, li):
+ assert len(li) == self.num
+ binary = b''
+ for i in li:
+ b = b''
+ for _ in range(self.length):
+ b = six.int2byte(i & 255) + b
+ i //= 256
+ binary += b
+ return binary
+
+
+Int4Double = IntDescrMlt(4, 2)
+
+
+class MacAddr(TypeDescr):
+ size = 6
+ to_user = addrconv.mac.bin_to_text
+ from_user = addrconv.mac.text_to_bin
+
+
+class IPv4Addr(TypeDescr):
+ size = 4
+ to_user = addrconv.ipv4.bin_to_text
+ from_user = addrconv.ipv4.text_to_bin
+
+
+class IPv6Addr(TypeDescr):
+ size = 16
+ to_user = addrconv.ipv6.bin_to_text
+ from_user = addrconv.ipv6.text_to_bin
+
+
+class UnknownType(TypeDescr):
+
+ @staticmethod
+ def to_user(data):
+ if six.PY3:
+ return base64.b64encode(data).decode('ascii')
+ else:
+ return base64.b64encode(data)
+
+ from_user = staticmethod(base64.b64decode)
+
+
+class TypeDisp(object):
+ _TYPES = {}
+ _REV_TYPES = None
+ _UNKNOWN_TYPE = None
+
+ @classmethod
+ def register_unknown_type(cls):
+ def _register_type(subcls):
+ cls._UNKNOWN_TYPE = subcls
+ return subcls
+ return _register_type
+
+ @classmethod
+ def register_type(cls, type_):
+ cls._TYPES = cls._TYPES.copy()
+
+ def _register_type(subcls):
+ cls._TYPES[type_] = subcls
+ cls._REV_TYPES = None
+ return subcls
+ return _register_type
+
+ @classmethod
+ def _lookup_type(cls, type_):
+ try:
+ return cls._TYPES[type_]
+ except KeyError:
+ return cls._UNKNOWN_TYPE
+
+ @classmethod
+ def _rev_lookup_type(cls, targ_cls):
+ if cls._REV_TYPES is None:
+ rev = dict((v, k) for k, v in cls._TYPES.items())
+ cls._REV_TYPES = rev
+ return cls._REV_TYPES[targ_cls]