def field_spec_getter(msg_reg, chan): # we have already read the header containing the field number # read the byte count, the length of the spec byte_count = read_raw_varint(chan) end = chan.position + byte_count # read field 0 hdr = read_raw_varint(chan) # SHOULD COMPLAIN IF WRONG HEADER string = read_raw_len_plus(chan) name = string.decode('utf-8') # convert bytes to str # read field 1 hdr = read_raw_varint(chan) # SHOULD COMPLAIN IF WRONG HEADER field_type = VENUM_GET(chan) # read field 2 hdr = read_raw_varint(chan) # SHOULD COMPLAIN IF WRONG HEADER quant = VENUM_GET(chan) # read field 3 hdr = read_raw_varint(chan) # SHOULD COMPLAIN IF WRONG HEADER f_nbr = VENUM_GET(chan) # XXX IGNORING DEFAULT default = None val = FieldSpec(msg_reg, name, field_type, quant, f_nbr, default) return val
def lstring_get(chan): b_array = read_raw_len_plus(chan) value = b_array.decode('utf-8') # DEBUG print("lStringGet '%s' => '%s'" % (b_array, value)) # END return value
def enum_spec_getter(dummy_reg, chan): # we have already read the header containing the field number # read the byte count, the length of the spec byte_count = read_raw_varint(chan) end = chan.position + byte_count # XXX should use for validation # read field 0 hdr = read_raw_varint(chan) # SHOULD COMPLAIN IF WRONG HEADER string = read_raw_len_plus(chan) name = string.decode('utf-8') # convert bytes to str # read instances of field 1: should enforce the + quantifier here pairs = [] while chan.position < end: hdr = read_raw_varint(chan) if hdr_field_nbr(hdr) != 1: # XXX SHOULD COMPLAIN IF WRONG HEADER # XXX This is a a peek: pos only gets advanced if OK print("EXPECTED FIELD 1, FOUND %s" % hdr_field_nbr(hdr)) break exc = enum_pair_spec_getter(dummy_reg, chan) pairs.append(exc) # create EnumSpec instance, which gets returned val = EnumSpec(name, pairs) return val
def enum_pair_spec_getter(dummy_reg, chan): # we have already read the header containing the field number # read the byte count, the length of the spec byte_count = read_raw_varint(chan) end = chan.position + byte_count # XXX should use for validation # read field 0 hdr = read_raw_varint(chan) # SHOULD COMPLAIN IF WRONG HEADER string = read_raw_len_plus(chan) sym = string.decode('utf-8') # convert bytes to str # read field 1 hdr = read_raw_varint(chan) # SHOULD COMPLAIN IF WRONG HEADER val = read_raw_varint(chan) # construct the EnumPairSpec object from field values obj = EnumPairSpec(sym, val) return obj
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 msg_spec_getter(msg_reg, chan): # read the byte count, the length of the spec byte_count = read_raw_varint(chan) end = chan.position + byte_count # read field 0 hdr = read_raw_varint(chan) # SHOULD COMPLAIN IF WRONG HEADER string = read_raw_len_plus(chan) name = string.decode('utf8') # convert byte to str # read instances of field 1: should enforce the + quantifier here fields = [] while chan.position < end: hdr = read_raw_varint(chan) if hdr_field_nbr(hdr) != 1: # XXX SHOULD COMPLAIN IF WRONG HEADER # XXX This is a a peek: pos only gets advanced if OK print("EXPECTED FIELD 1, FOUND %s" % hdr_field_nbr(hdr)) break # XXX params should be (msgReg, chan) file = field_spec_getter(msg_reg, chan) # was chan0 fields.append(file) # we may have multiple enums enums = [] while chan.position < end: hdr = read_raw_varint(chan) if hdr_field_nbr(hdr) != 2: print("EXPECTED FIELD 2, FOUND %s" % hdr_field_nbr(hdr)) break enum = enum_spec_getter(chan) # was chan0 enums.append(enum) # XXX WRONG PARAMETER LIST # val = MsgSpec(name, fields, enums) dummy_parent = MsgSpec('dummy', msg_reg, None) val = MsgSpec(name, msg_reg, dummy_parent) return val
def lmsg_get(chan): # caller must interpret the raw byte array return read_raw_len_plus(chan)
def lbytes_get(chan): return read_raw_len_plus(chan)
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)