from . import nanomsg, ffi
import sys

NN_MSG = int(ffi.cast("size_t", -1))

ustr = str if sys.version_info[0] > 2 else unicode

class Socket(object):
    
    def __init__(self, domain, protocol):
        self.sock = nanomsg.nn_socket(domain, protocol)
    
    def close(self):
        nanomsg.nn_close(self.sock)
    
    def getsockopt(self, level, option):
        buf = ffi.new('int*')
        size = ffi.new('size_t*')
        size[0] = 4
        rc = nanomsg.nn_getsockopt(self.sock, level, option, buf, size)
        assert rc >= 0, rc
        return buf[0]
    
    def setsockopt(self, level, option, value):
        if isinstance(value, int):
            buf = ffi.new('int*')
            buf[0] = value
            vlen = 4
        elif isinstance(value, ustr):
            buf = ffi.new('char[%s]' % len(value), value.encode())
            vlen = len(value)
        elif isinstance(value, bytes):
            buf = ffi.new('char[%s]' % len(value), value)
            vlen = len(value)
        else:
            raise TypeError("value must be a int, str or bytes")
        rc = nanomsg.nn_setsockopt(self.sock, level, option, buf, vlen)
        assert rc >= 0, rc
    
    def bind(self, addr):
        addr = addr.encode() if isinstance(addr, ustr) else addr
        buf = ffi.new('char[]', addr)
        rc = nanomsg.nn_bind(self.sock, buf)
        assert rc > 0, rc
    
    def connect(self, addr):
        addr = addr.encode() if isinstance(addr, ustr) else addr
        buf = ffi.new('char[]', addr)
        rc = nanomsg.nn_connect(self.sock, buf)
        assert rc > 0, rc
    
    def send(self, data, flags=0):
        if isinstance(data, memoryview):
            buf = ffi.from_buffer(data)
        else:
            data = data.encode() if isinstance(data, ustr) else data
            buf = ffi.new('char[%i]' % len(data), data)
        rc = nanomsg.nn_send(self.sock, buf, len(data), flags)
        assert rc > 0, rc
    
    def recv(self, flags=0):
        buf = ffi.new('char**')
        rc = nanomsg.nn_recv(self.sock, buf, NN_MSG, flags)
        assert rc > 0, rc
        s = ffi.buffer(buf[0], rc)[:]
        nanomsg.nn_freemsg(buf[0])
        return s

@@ -122,16 +122,52 @@
 nicode%0A%0A
+class NNError(Exception):%0A    pass%0A%0A
 class So
@@ -176,24 +176,24 @@
 et(object):%0A
-
     %0A    def
@@ -284,24 +284,267 @@
 tocol)%0A    %0A
+    def _error(self, rc, value=None):%0A        if rc %3C 0:%0A            chars = nanomsg.nn_strerror(nanomsg.nn_errno())%0A            raise NNError(ffi.string(chars))%0A        if callable(value):%0A            return value()%0A        return value%0A    %0A
     def clos
@@ -802,48 +802,46 @@
     
-assert rc %3E= 0, rc%0A        return
+return self._error(rc, lambda:
  buf%5B0%5D
+)
 %0A   
@@ -1432,26 +1432,23 @@
     
-assert rc %3E= 0, 
+self._error(
 rc
+)
 %0A   
@@ -1631,33 +1631,42 @@
         
-assert rc %3E 0
+return self._error(rc
 , rc
+)
 %0A    %0A  
@@ -1851,33 +1851,42 @@
         
-assert rc %3E 0
+return self._error(rc
 , rc
+)
 %0A    %0A  
@@ -2209,33 +2209,42 @@
         
-assert rc %3E 0
+return self._error(rc
 , rc
+)
 %0A    %0A  
@@ -2374,25 +2374,23 @@
     
-assert rc %3E 0, 
+self._error(
 rc
+)
 %0A   

Raise descriptive Exception on errors