Source

crossroads / crossroads / message.py

Full commit
# -*- coding: utf-8 -*-
'''Crossroads.IO messages.'''

from ctypes import sizeof, string_at, c_ubyte, byref, c_size_t

from stuf.six import PY3, tobytes, tounicode, strings

from .constants import MORE
from . import lowest as xs
from stuf.deep import getcls
from test.test_multiprocessing import c_int


class BaseMessage(object):

    def __init__(self):
        self.more = self.rc = self.dest = self.last_rc = None

    def __bytes__(self):
        if self.dest is None:
            return b''
        return tobytes(string_at(byref(self.dest), self.size))

    def __unicode__(self):
        return tounicode(self)

    __str__ = __unicode__ if PY3 else __bytes__


class Message(BaseMessage):

    __slots__ = 'src dest rc more size last_rc'.split()

    def __init__(self, size, source=None):
        super(Message, self).__init__()
        self.src = source
        if source is None:
            self.dest = xs.array(c_ubyte, size)
            self.size = size
        else:
            if isinstance(source, (getcls(self), strings)):
                self.src = source = bytes(source)
            self.size = len(source) if size is None else size
            self.dest = None

    def __len__(self):
        return self.size


class MessageXS(BaseMessage):

    __slots__ = 'src dest rc more last_rc'.split()

    def __init__(self, source=None):
        super(MessageXS, self).__init__()
        self.dest = xs.msg_t()
        if isinstance(source, getcls(self)):
            self.src = source.dest
            self.rc = xs.msg_init(self.src)
            self.size = sizeof(self.src)
        elif source is None:
            self.src = self.dest
            self.rc = xs.msg_init(self.src)
            self.size = sizeof(self.src)
        else:
            self.src = bytes(source)
            length = self.size = len(self.src)
            self.rc = xs.msg_init_size(self.dest, length)
            xs.memmove(xs.msg_data(self.dest), self.src, length)

    def __len__(self):
        return self.size

    @property
    def moremsg(self):
        more = c_int()
        more_size = c_size_t(sizeof(more))
        self.rc = xs.getmsgopt(self.dest, MORE, more, more_size)
        value = more.value
        del more_size, more
        return value

    def close(self):
        self.rc = xs.msg_close(self.dest)