Ejemplo n.º 1
0
def _float_adjust(v, encode):
    if encode and six.indexbytes(v, 0) & 0x80 != 0x00:
        return b''.join(map(lambda x: six.int2byte(x ^ 0xff), six.iterbytes(v)))
    elif not encode and six.indexbytes(v, 0) & 0x80 != 0x80:
        return b''.join(map(lambda x: six.int2byte(x ^ 0xff), six.iterbytes(v)))
    else:
        return six.int2byte(six.indexbytes(v, 0) ^ 0x80) + v[1:]
Ejemplo n.º 2
0
def _encode(value, nested=False):
    # returns [code][data] (code != 0xFF)
    # encoded values are self-terminating
    # sorting need to work too!
    if value == None:  # ==, not is, because some fdb.impl.Value are equal to None
        if nested:
            return b''.join([six.int2byte(NULL_CODE), six.int2byte(0xff)]), -1
        else:
            return b''.join([six.int2byte(NULL_CODE)]), -1
    elif isinstance(value, bytes):  # also gets non-None fdb.impl.Value
        return six.int2byte(BYTES_CODE) + value.replace(
            b'\x00', b'\x00\xFF') + b'\x00', -1
    elif isinstance(value, six.text_type):
        return six.int2byte(STRING_CODE) + value.encode('utf-8').replace(
            b'\x00', b'\x00\xFF') + b'\x00', -1
    elif isinstance(value, six.integer_types) and (
            not isinstance(value, bool) or
        (hasattr(fdb, '_version') and fdb._version < 500)):
        if value == 0:
            return b''.join([six.int2byte(INT_ZERO_CODE)]), -1
        elif value > 0:
            if value >= _size_limits[-1]:
                length = (_bit_length(value) + 7) // 8
                data = [six.int2byte(POS_INT_END), six.int2byte(length)]
                for i in _range(length - 1, -1, -1):
                    data.append(six.int2byte((value >> (8 * i)) & 0xff))
                return b''.join(data), -1

            n = bisect_left(_size_limits, value)
            return six.int2byte(INT_ZERO_CODE + n) + struct.pack(
                ">Q", value)[-n:], -1
        else:
            if -value >= _size_limits[-1]:
                length = (_bit_length(value) + 7) // 8
                value += (1 << (length * 8)) - 1
                data = [
                    six.int2byte(NEG_INT_START),
                    six.int2byte(length ^ 0xff)
                ]
                for i in _range(length - 1, -1, -1):
                    data.append(six.int2byte((value >> (8 * i)) & 0xff))
                return b''.join(data), -1

            n = bisect_left(_size_limits, -value)
            maxv = _size_limits[n]
            return six.int2byte(INT_ZERO_CODE - n) + struct.pack(
                ">Q", maxv + value)[-n:], -1
    elif isinstance(value, ctypes.c_float) or isinstance(value, SingleFloat):
        return six.int2byte(FLOAT_CODE) + _float_adjust(
            struct.pack(">f", value.value), True), -1
    elif isinstance(value, ctypes.c_double):
        return six.int2byte(DOUBLE_CODE) + _float_adjust(
            struct.pack(">d", value.value), True), -1
    elif isinstance(value, float):
        return six.int2byte(DOUBLE_CODE) + _float_adjust(
            struct.pack(">d", value), True), -1
    elif isinstance(value, uuid.UUID):
        return six.int2byte(UUID_CODE) + value.bytes, -1
    elif isinstance(value, bool):
        if value:
            return b''.join([six.int2byte(TRUE_CODE)]), -1
        else:
            return b''.join([six.int2byte(FALSE_CODE)]), -1
    elif isinstance(value, Versionstamp):
        version_pos = -1 if value.is_complete() else 1
        return six.int2byte(VERSIONSTAMP_CODE) + value.to_bytes(), version_pos
    elif isinstance(value, tuple) or isinstance(value, list):
        child_bytes, version_pos = _reduce_children(
            map(lambda x: _encode(x, True), value))
        new_version_pos = -1 if version_pos < 0 else version_pos + 1
        return b''.join([six.int2byte(NESTED_CODE)] + child_bytes +
                        [six.int2byte(0x00)]), new_version_pos
    else:
        raise ValueError("Unsupported data type: " + str(type(value)))
Ejemplo n.º 3
0
class Versionstamp(object):
    LENGTH = 12
    _TR_VERSION_LEN = 10
    _MAX_USER_VERSION = (1 << 16) - 1
    _UNSET_TR_VERSION = 10 * six.int2byte(0xff)
    _STRUCT_FORMAT_STRING = '>' + str(_TR_VERSION_LEN) + 'sH'

    @classmethod
    def validate_tr_version(cls, tr_version):
        if tr_version is None:
            return
        if not isinstance(tr_version, bytes):
            raise TypeError("Global version has illegal type " +
                            str(type(tr_version)) + " (requires bytes)")
        elif len(tr_version) != cls._TR_VERSION_LEN:
            raise ValueError("Global version has incorrect length " +
                             str(len(tr_version)) + " (requires " +
                             str(cls._TR_VERSION_LEN) + ")")

    @classmethod
    def validate_user_version(cls, user_version):
        if not isinstance(user_version, six.integer_types):
            raise TypeError("Local version has illegal type " +
                            str(type(user_version)) +
                            " (requires integer type)")
        elif user_version < 0 or user_version > cls._MAX_USER_VERSION:
            raise ValueError("Local version has value " + str(user_version) +
                             " which is out of range")

    def __init__(self, tr_version=None, user_version=0):
        Versionstamp.validate_tr_version(tr_version)
        Versionstamp.validate_user_version(user_version)
        self.tr_version = tr_version
        self.user_version = user_version

    @staticmethod
    def incomplete(user_version=0):
        return Versionstamp(user_version=user_version)

    @classmethod
    def from_bytes(cls, v, start=0):
        if not isinstance(v, bytes):
            raise TypeError("Cannot parse versionstamp from non-byte string")
        elif len(v) - start < cls.LENGTH:
            raise ValueError("Versionstamp byte string is too short (only " +
                             str(len(v) - start) + " bytes to read from")
        else:
            tr_version = v[start:start + cls._TR_VERSION_LEN]
            if tr_version == cls._UNSET_TR_VERSION:
                tr_version = None
            user_version = six.indexbytes(v, start + cls._TR_VERSION_LEN) * (
                1 << 8) + six.indexbytes(v, start + cls._TR_VERSION_LEN + 1)
            return Versionstamp(tr_version, user_version)

    def is_complete(self):
        return self.tr_version is not None

    def __repr__(self):
        return "fdb.tuple.Versionstamp(" + repr(self.tr_version) + ", " + repr(
            self.user_version) + ")"

    def __str__(self):
        return "Versionstamp(" + repr(self.tr_version) + ", " + str(
            self.user_version) + ")"

    def to_bytes(self):
        return struct.pack(
            self._STRUCT_FORMAT_STRING,
            self.tr_version if self.is_complete() else self._UNSET_TR_VERSION,
            self.user_version)

    def completed(self, new_tr_version):
        if self.is_complete():
            raise RuntimeError("Versionstamp already completed")
        else:
            return Versionstamp(new_tr_version, self.user_version)

    # Comparisons
    def __eq__(self, other):
        if isinstance(other, Versionstamp):
            return self.tr_version == other.tr_version and self.user_version == other.user_version
        else:
            return False

    def __ne__(self, other):
        return not (self == other)

    def __cmp__(self, other):
        if self.is_complete():
            if other.is_complete():
                if self.tr_version == other.tr_version:
                    return cmp(self.user_version, other.user_version)
                else:
                    return cmp(self.tr_version, other.tr_version)
            else:
                # All complete are less than all incomplete.
                return -1
        else:
            if other.is_complete():
                # All incomplete are greater than all complete
                return 1
            else:
                return cmp(self.user_version, other.user_version)

    def __hash__(self):
        if self.tr_version is None:
            return hash(self.user_version)
        else:
            return hash(self.tr_version) * 37 ^ hash(self.user_version)

    def __nonzero__(self):
        return self.is_complete()
Ejemplo n.º 4
0
def randomElement():
    r = random.randint(0, 9)
    if r == 0:
        if random.random() < 0.5:
            chars = [b'\x00', b'\x01', b'a', b'7', b'\xfe', b'\ff']
            return b''.join(
                [random.choice(chars) for c in _range(random.randint(0, 5))])
        else:
            return b''.join([
                six.int2byte(random.randint(0, 255))
                for _ in _range(random.randint(0, 10))
            ])
    elif r == 1:
        if random.random() < 0.5:
            chars = [
                u('\x00'),
                u('\x01'),
                u('a'),
                u('7'),
                u('\xfe'),
                u('\ff'),
                u('\u0000'),
                u('\u0001'),
                u('\uffff'),
                u('\uff00'),
                u('\U0001f4a9')
            ]
            return u('').join(
                [random.choice(chars) for c in _range(random.randint(0, 10))])
        else:
            return u('').join(
                [randomUnicode() for _ in _range(random.randint(0, 10))])
    elif r == 2:
        return random.choice([-1, 1]) * min(
            2**random.randint(0, 2040) + random.randint(-10, 10), 2**2040 - 1)
    elif r == 3:
        return random.choice([-1, 1]) * 2**random.randint(
            0, 64) + random.randint(-10, 10)
    elif r == 4:
        return None
    elif r == 5:
        ret = random.choice([
            float('-nan'),
            float('-inf'), -0.0, 0.0,
            float('inf'),
            float('nan')
        ])
        if random.random() < 0.5:
            return SingleFloat(ret)
        else:
            return ret
    elif r == 6:
        is_double = random.random() < 0.5
        byte_str = b''.join([
            six.int2byte(random.randint(0, 255))
            for _ in _range(8 if is_double else 4)
        ])
        if is_double:
            return struct.unpack(">d", byte_str)[0]
        else:
            return SingleFloat(struct.unpack(">f", byte_str)[0])
    elif r == 7:
        return random.random() < 0.5
    elif r == 8:
        return uuid.uuid4()
    elif r == 9:
        return [randomElement() for _ in _range(random.randint(0, 5))]