def _get_c_string(data): try: end = data.index("\x00") except ValueError: raise InvalidBSON() return (unicode(data[:end], "utf-8"), data[end + 1:])
def _get_int(data): try: value = struct.unpack("<i", data[:4])[0] except struct.error: raise InvalidBSON() return (value, data[4:])
def _get_binary(data): (length, data) = _get_int(data) subtype = ord(data[0]) data = data[1:] if subtype == 2: (length2, data) = _get_int(data) if length2 != length - 4: raise InvalidBSON("invalid binary (st 2) - lengths don't match!") length = length2 if subtype == 3 and _use_uuid: return (uuid.UUID(bytes=data[:length]), data[length:]) return (Binary(data[:length], subtype), data[length:])
def _validate_document(data, valid_name=None): try: obj_size = struct.unpack("<i", data[:4])[0] except struct.error: raise InvalidBSON() assert obj_size <= len(data) obj = data[4:obj_size] assert len(obj) eoo = obj[-1] assert eoo == "\x00" elements = obj[:-1] _validate_elements(elements, valid_name) return data[obj_size:]
def is_valid(bson): """Validate that the given string represents valid BSON data. Raises TypeError if the data is not an instance of a subclass of str. Returns True if the data represents a valid BSON object, False otherwise. :Parameters: - `bson`: the data to be validated """ if not isinstance(bson, types.StringType): raise TypeError("BSON data must be an instance of a subclass of str") # 4 MB limit if len(bson) > 4 * 1024 * 1024: raise InvalidBSON("BSON documents are limited to 4MB") try: remainder = _validate_document(bson) return remainder == "" except (AssertionError, InvalidBSON): return False
def _validate_element_data(type, data): try: return _element_validator[type](data) except KeyError: raise InvalidBSON("unrecognized type: %s" % type)