def round_trip64(self, nnn): """ Test writing and reading a 64-bit integer as the first and only field in a buffer """ chan = Channel(LEN_BUFF) # -- write 64-bit value ------------------------------------- field_nbr = 1 + self.rng.next_int16(1024) write_b64_field(chan, nnn, field_nbr) chan.flip() # # DEBUG # buf = chan.buffer # print "buffer after writing varint field: ", # dumpBuffer(buf) # # END # -- read 64-bit value -------------------------------------- # first the header (which is a varint) ------------ (field_type, field_nbr2) = read_field_hdr(chan) offset2 = chan.position self.assertEqual(PrimTypes.B64, field_type) self.assertEqual(field_nbr, field_nbr2) self.assertEqual( length_as_varint(field_hdr_val(field_nbr, PrimTypes.B64)), offset2) # then the varint proper -------------------------- varint_ = read_raw_b64(chan) offset3 = chan.position self.assertEqual(nnn, varint_) self.assertEqual(offset2 + 8, offset3)
def round_trip32(self, nnn): """ Test writing and reading a 32-bit integer as the first and only field in a buffer. """ chan = Channel(LEN_BUFF) # -- write 32-bit value ------------------------------------- field_nbr = 1 + self.rng.next_int16(1024) write_b32_field(chan, nnn, field_nbr) chan.flip() # -- read 32-bit value -------------------------------------- # first the header (which is a varint) ------------ (field_type, field_nbr2) = read_field_hdr(chan) offset2 = chan.position self.assertEqual(PrimTypes.B32, field_type) self.assertEqual(field_nbr, field_nbr2) self.assertEqual( length_as_varint(field_hdr_val(field_nbr, PrimTypes.B32)), offset2) # then the varint proper -------------------------- varint_ = read_raw_b32(chan) offset3 = chan.position self.assertEqual(nnn, varint_) self.assertEqual(offset2 + 4, offset3)
def round_trip(self, nnn): """ Test writing and reading a varint as the first and only field in a buffer. """ # -- write varint ------------------------------------------- field_nbr = 1 + self.rng.next_int16(1024) chan = Channel(LEN_BUFFER) write_varint_field(chan, nnn, field_nbr) chan.flip() # -- read varint -------------------------------------------- # first the header (which is a varint) ------------ (prim_type, field_nbr2) = read_field_hdr(chan) offset2 = chan.position self.assertEqual(PrimTypes.VARINT, prim_type) self.assertEqual(field_nbr, field_nbr2) self.assertEqual(length_as_varint(field_nbr << 3), offset2) # then the varint proper -------------------------- varint_ = read_raw_varint(chan) chan.flip() offset3 = chan.limit self.assertEqual(nnn, varint_) self.assertEqual(offset2 + length_as_varint(nnn), offset3)
def recv_from_cnx(cnx, chan): """ Receive a serialized message from a connection into a channel. On return the channel has been flipped (offset = 0, limit = data length). Returns the msgNbr. """ # --------------------------------------------------------------- # SEE fieldz.msgImpl for an example of this kind of Channel # manipulation. Use a Python buffer to select the region of the # buffer we want to write into. # --------------------------------------------------------------- # receive something from the connection chan.clear() count = cnx.recv_into(chan.buffer, BUFSIZE) if count <= 0: raise IOError('initial read of message gets zero bytes') # read the header to determine the message type and its length (p_type, msg_nbr) = read_field_hdr(chan) # DEBUG print("CHAN_IO: count = %d; pType = %s, msgNbr = %s" % (count, p_type, msg_nbr)) # END if p_type != PrimTypes.LEN_PLUS: raise IOError('message header type is %d, not PrimTypes.LEN_PLUS' % p_type) # XXX raise exception of msgNbr <0 or msgNbr > 2 msg_len = read_raw_varint(chan) # XXX ignoring pathological possibility that offset > count # if we don't have all of the data, loop getting the rest while count < msg_len: # vBuf = buffer(chan.buffer, count) v_buf = memoryview(chan.buffer)[count:] count += cnx.recv_into(v_buf, BUFSIZE - count) chan.position = count chan.flip() return msg_nbr
def round_trip(self, string): """ Verify that a unicode string converted to wire format and then back again is the same string. This tests writing and reading a string of bytes as the first and only field in a buffer. """ chan = Channel(LEN_BUFF) # -- write the bytearray ------------------------------------ field_nbr = 1 + self.rng.next_int16(1024) write_len_plus_field(chan, string, field_nbr) chan.flip() # # DEBUG # print("buffer after writing lenPlus field: " + str(chan.buffer)) # # END # -- read the value written --------------------------------- # first the header (which is a varint) ------------ (field_type, field_nbr2,) = read_field_hdr(chan) offset2 = chan.position self.assertEqual(PrimTypes.LEN_PLUS, field_type) self.assertEqual(field_nbr, field_nbr2) self.assertEqual( length_as_varint(field_hdr_val(field_nbr, PrimTypes.LEN_PLUS)), offset2) # then the actual value written ------------------- tstamp = read_raw_len_plus(chan) offset3 = chan.position self.assertEqual(string, tstamp) self.assertEqual( offset2 + length_as_varint( len(string)) + len(string), offset3)
def read(cls, chan, parent_spec): """msg refers to the msg, n is field number; returns msg, n""" (p_type, nnn) = read_field_hdr(chan) if nnn < 0 or nnn >= len(parent_spec.msgs): raise RuntimeError("msg ID '%s' out of range" % nnn) msg_spec = parent_spec.msgs[nnn] msg_len = read_raw_varint(chan) # DEBUG print("IMPL_GETTER, P_TYPE %d, MSG/FIELD NBR %d, MSG_LEN %d" % ( p_type, nnn, msg_len)) # END end = chan.position + msg_len cls = _make_msg_class(parent_spec, msg_spec) # generated class fields = [] # ??? values = [] # ??? # XXX THIS IS NOT GOING TO WORK, BECAUSE WE NEED TO PEEK XXX for f_class in cls._fieldClasses: field_type = f_class._field_type # a number f_quant = f_class._quantifier field_nbr = f_class._field_nbr # read the field header (p_type, nbr) = read_field_hdr(chan) # DEBUG print( " GET_FROM_CHAN, FIELD %u, TYPE %u" % (field_nbr, field_type)) # END if field_nbr != nbr: raise RuntimeError(" EXPECTED FIELD_NBR %d, GOT %d" % ( field_nbr, nbr)) if f_quant == Q_REQUIRED or f_quant == Q_OPTIONAL: if field_type > 23: reg = cls.msg_spec.reg # BEGIN JUNK ------------------------------------ # DEBUG print( "READING: FIELD TYPE IS %s" % reg.reg_id2name(field_type)) # END entry = reg.reg_id2entry(field_type) print("READING: FIELD TYPE bis IS %s" % entry.name) # END JUNK -------------------------------------- child_spec = entry.msg_spec child_class = _make_msg_class(msg_spec, child_spec) # RECURSE: read(childCls, chan, msgSpec) # msgSpec is parentSpec here value = T_GET_FUNCS[field_type](chan) # XXX WRONG else: value = T_GET_FUNCS[field_type](chan) _check_position(chan, end) values.append(value) elif f_quant == Q_PLUS or f_quant == Q_STAR: v_list = [] # we are reading a list of values # WORKING HERE else: raise RuntimeError("unknown quantifier, index '%u'" % f_quant) # DEBUG print("AFTER COLLECTING %u FIELDS, OFFSET IS %u" % ( len(fields), chan.position)) # END # XXX BLOWS UP: can't handle Q_PLUS or Q_STAR (about line 407) return (cls(values), nnn) # GEEP
def get_next(self): (self._p_type, self._field_nbr) = read_field_hdr(self) # getter has range check field_type = self._field_type = self._msg_spec.field_type_ndx( self._field_nbr) # gets through dispatch table ------------------------------- if field_type >= 0 and field_type <= ftypes.V_SINT64: self._value = T_GET_FUNCS[field_type](self) return # we use the field type to verify that have have read the right # primitive type # # - implemented using varints ------------------------------- # if self._fType <= ftypes._V_UINT64: # if self._pType != VARINT_TYPE: # raise RuntimeError("pType is %u but should be %u" % ( # self._pType, VARINT_TYPE)) # (self._value, self._position) = readRawVarint( # self) # # DEBUG # print "getNext: readRawVarint returns value = 0x%x" % self._value # # END # if self._fType == ftypes._V_SINT32: # self._value = decodeSint32(self._value) # # DEBUG # print " after decode self._value is 0x%x" % self._value # # # elif self._fType == ftypes._V_SINT64: # self._value = decodeSint64(self._value) # #END VARINT_GET # implemented using B32 ------------------------------------- if self._field_type <= ftypes.F_FLOAT: self._p_type = B32_TYPE # DEBUG varint_ = read_raw_b32(self) if self._field_type == ftypes.F_UINT32: self._value = ctypes.c_uint32(varint_).value elif self._field_type == ftypes.F_SINT32: self._value = ctypes.c_int32(varint_).value else: raise NotImplementedError('B32 handling for float') # implemented using B64 ------------------------------------- elif self._field_type <= ftypes.F_DOUBLE: self._p_type = B64_TYPE # DEBUG (varint_, self._position) = read_raw_b64(self) if self._field_type == ftypes.F_UINT64: self._value = ctypes.c_uint64(varint_).value elif self._field_type == ftypes.F_SINT64: self._value = ctypes.c_int64(varint_).value else: raise NotImplementedError('B64 handling for double') # implemented using LEN_PLUS -------------------------------- elif self._field_type <= ftypes.L_MSG: self._p_type = LEN_PLUS_TYPE # DEBUG varint_ = read_raw_len_plus(self) if self._field_type == ftypes.L_STRING: self._value = varint_.decode('utf-8') elif self._field_type == ftypes.L_BYTES: self._value = varint_ else: raise NotImplementedError('LEN_PLUS handled as L_MSG') # implemented using B128, B160, B256 ------------------------ elif self._field_type == ftypes.F_BYTES16: self._p_type = B128_TYPE # DEBUG self._value = read_raw_b128(self) elif self._field_type == ftypes.F_BYTES20: self._p_type = B160_TYPE # DEBUG self._value = read_raw_b160(self) elif self._field_type == ftypes.F_BYTES32: self._p_type = B256_TYPE # DEBUG self._value = read_raw_b256(self) else: raise NotImplementedError( "decode for type %d has not been implemented" % self._field_type)