void DocumentImpl::fromBuffer()

in source/extensions/filters/network/mongo_proxy/bson_impl.cc [368:489]


void DocumentImpl::fromBuffer(Buffer::Instance& data) {
  uint64_t original_buffer_length = data.length();
  int32_t message_length = BufferHelper::removeInt32(data);
  if (static_cast<uint64_t>(message_length) > original_buffer_length) {
    throw EnvoyException("invalid BSON message length");
  }

  ENVOY_LOG(trace, "BSON document length: {} data length: {}", message_length,
            original_buffer_length);

  while (true) {
    uint64_t document_bytes_remaining = data.length() - (original_buffer_length - message_length);
    ENVOY_LOG(trace, "BSON document bytes remaining: {}", document_bytes_remaining);
    if (document_bytes_remaining == 1) {
      uint8_t last_byte = BufferHelper::removeByte(data);
      if (last_byte != 0) {
        throw EnvoyException("invalid document");
      }

      return;
    }

    uint8_t element_type = BufferHelper::removeByte(data);
    std::string key = BufferHelper::removeCString(data);
    ENVOY_LOG(trace, "BSON element type: {:#x} key: {}", element_type, key);
    switch (static_cast<Field::Type>(element_type)) {
    case Field::Type::DOUBLE: {
      double value = BufferHelper::removeDouble(data);
      ENVOY_LOG(trace, "BSON double: {}", value);
      addDouble(key, value);
      break;
    }

    case Field::Type::STRING: {
      std::string value = BufferHelper::removeString(data);
      ENVOY_LOG(trace, "BSON string: {}", value);
      addString(key, std::move(value));
      break;
    }

    case Field::Type::DOCUMENT: {
      ENVOY_LOG(trace, "BSON document");
      addDocument(key, DocumentImpl::create(data));
      break;
    }

    case Field::Type::ARRAY: {
      ENVOY_LOG(trace, "BSON array");
      addArray(key, DocumentImpl::create(data));
      break;
    }

    case Field::Type::BINARY: {
      std::string value = BufferHelper::removeBinary(data);
      ENVOY_LOG(trace, "BSON binary: {}", value);
      addBinary(key, std::move(value));
      break;
    }

    case Field::Type::OBJECT_ID: {
      Field::ObjectId value;
      BufferHelper::removeBytes(data, &value[0], value.size());
      addObjectId(key, std::move(value));
      break;
    }

    case Field::Type::BOOLEAN: {
      bool value = BufferHelper::removeByte(data) != 0;
      ENVOY_LOG(trace, "BSON boolean: {}", value);
      addBoolean(key, value);
      break;
    }

    case Field::Type::DATETIME: {
      int64_t value = BufferHelper::removeInt64(data);
      ENVOY_LOG(trace, "BSON datetime: {}", value);
      addDatetime(key, value);
      break;
    }

    case Field::Type::NULL_VALUE: {
      ENVOY_LOG(trace, "BSON null value");
      addNull(key);
      break;
    }

    case Field::Type::REGEX: {
      Field::Regex value;
      value.pattern_ = BufferHelper::removeCString(data);
      value.options_ = BufferHelper::removeCString(data);
      ENVOY_LOG(trace, "BSON regex pattern: {} options: {}", value.pattern_, value.options_);
      addRegex(key, std::move(value));
      break;
    }

    case Field::Type::INT32: {
      int32_t value = BufferHelper::removeInt32(data);
      ENVOY_LOG(trace, "BSON int32: {}", value);
      addInt32(key, value);
      break;
    }

    case Field::Type::TIMESTAMP: {
      int64_t value = BufferHelper::removeInt64(data);
      ENVOY_LOG(trace, "BSON timestamp: {}", value);
      addTimestamp(key, value);
      break;
    }

    case Field::Type::INT64: {
      int64_t value = BufferHelper::removeInt64(data);
      ENVOY_LOG(trace, "BSON int64: {}", value);
      addInt64(key, value);
      break;
    }

    default:
      throw EnvoyException(
          fmt::format("invalid BSON element type: {:#x} key: {}", element_type, key));
    }
  }
}