blob: 44b76a5e2829edcd274c12efa46ce1d54302d6d6 [file]
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/subresource_filter/core/common/unindexed_ruleset.h"
#include "base/check.h"
#include "base/check_op.h"
#include "base/numerics/safe_conversions.h"
#include "components/url_pattern_index/proto/rules.pb.h"
#include "third_party/protobuf/src/google/protobuf/io/coded_stream.h"
#include "third_party/protobuf/src/google/protobuf/io/zero_copy_stream.h"
namespace subresource_filter {
namespace proto = url_pattern_index::proto;
// UnindexedRulesetReader ------------------------------------------------------
UnindexedRulesetReader::UnindexedRulesetReader(
google::protobuf::io::ZeroCopyInputStream* stream)
: coded_stream_(stream) {}
UnindexedRulesetReader::~UnindexedRulesetReader() = default;
bool UnindexedRulesetReader::ReadNextChunk(proto::FilteringRules* chunk) {
uint32_t chunk_size = 0;
if (!coded_stream_.ReadVarint32(&chunk_size)) {
return false;
}
auto limit = coded_stream_.PushLimit(chunk_size);
if (!chunk->ParseFromCodedStream(&coded_stream_)) {
return false;
}
coded_stream_.PopLimit(limit);
return true;
}
// UnindexedRulesetWriter ------------------------------------------------------
UnindexedRulesetWriter::UnindexedRulesetWriter(
google::protobuf::io::ZeroCopyOutputStream* stream,
int max_rules_per_chunk)
: coded_stream_(stream), max_rules_per_chunk_(max_rules_per_chunk) {}
UnindexedRulesetWriter::~UnindexedRulesetWriter() {
CHECK(IsPendingChunkEmpty());
}
bool UnindexedRulesetWriter::AddUrlRule(const proto::UrlRule& rule) {
CHECK(!had_error());
pending_chunk_.add_url_rules()->CopyFrom(rule);
return WriteChunkIfFull();
}
bool UnindexedRulesetWriter::AddStyleRule(const proto::StyleRule& rule) {
CHECK(!had_error());
pending_chunk_.add_style_rules()->CopyFrom(rule);
return WriteChunkIfFull();
}
bool UnindexedRulesetWriter::WriteChunkIfFull() {
if (pending_chunk_.url_rules_size() + pending_chunk_.style_rules_size() >=
max_rules_per_chunk_) {
return WritePendingChunk();
}
return true;
}
bool UnindexedRulesetWriter::IsPendingChunkEmpty() const {
return pending_chunk_.url_rules_size() == 0 &&
pending_chunk_.style_rules_size() == 0;
}
bool UnindexedRulesetWriter::Finish() {
CHECK(!had_error());
const bool success = IsPendingChunkEmpty() || WritePendingChunk();
if (success) {
coded_stream_.Trim();
}
return success;
}
bool UnindexedRulesetWriter::WritePendingChunk() {
CHECK(!had_error());
CHECK(!IsPendingChunkEmpty());
proto::FilteringRules chunk;
chunk.Swap(&pending_chunk_);
coded_stream_.WriteVarint32(
base::checked_cast<uint32_t>(chunk.ByteSizeLong()));
return !had_error() && chunk.SerializeToCodedStream(&coded_stream_);
}
} // namespace subresource_filter