// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Concrete implementations of `FilterBuilder` required by the parser.

#ifndef SRC_CONNECTIVITY_NETWORK_NETDUMP_FILTER_BUILDER_IMPL_H_
#define SRC_CONNECTIVITY_NETWORK_NETDUMP_FILTER_BUILDER_IMPL_H_

#include "filter.h"
#include "parser.h"

namespace netdump::parser {

// The reference implementation for constructing filter tree nodes.
// `FilterTreeBuilder` takes parameters in host byte order, and converts them in network byte order
// for the filter node constructors.
class FilterTreeBuilder : public FilterBuilder<FilterPtr> {
 public:
  explicit FilterTreeBuilder(const Tokenizer& tokenizer) : FilterBuilder<FilterPtr>(tokenizer) {}

  inline FilterPtr frame_length(uint16_t length, TokenPtr comparator) override {
    return FilterPtr(new FrameLengthFilter(htons(length), comparator->get_tag<LengthComparator>()));
  }

  inline FilterPtr ethertype(uint16_t type) override {
    return FilterPtr(new EthFilter(htons(type)));
  }

  inline FilterPtr mac(std::array<uint8_t, ETH_ALEN> address, TokenPtr addr_type) override {
    std::reverse(address.begin(), address.end());  // Constructor expects network byte order.
    return FilterPtr(new EthFilter(address, addr_type->get_tag<AddressFieldType>()));
  }

  inline FilterPtr ip_version(uint8_t version) override { return FilterPtr(new IpFilter(version)); }

  inline FilterPtr ip_pkt_length(uint8_t version, uint16_t length, TokenPtr comparator) override {
    return FilterPtr(new IpFilter(version, htons(length), comparator->get_tag<LengthComparator>()));
  }

  inline FilterPtr ip_protocol(uint8_t version, uint8_t protocol) override {
    return FilterPtr(new IpFilter(version, protocol));
  }

  inline FilterPtr ipv4_address(uint32_t address, TokenPtr type) override {
    return FilterPtr(new IpFilter(htonl(address), type->get_tag<AddressFieldType>()));
  }

  inline FilterPtr ipv6_address(std::array<uint8_t, IP6_ADDR_LEN> address,
                                TokenPtr addr_type) override {
    std::reverse(address.begin(), address.end());  // Constructor expects network byte order.
    return FilterPtr(new IpFilter(address, addr_type->get_tag<AddressFieldType>()));
  }

  FilterPtr ports(std::vector<PortRange> ranges, TokenPtr port_type) override {
    for (auto range_it = ranges.begin(); range_it < ranges.end(); ++range_it) {
      range_it->first = htons(range_it->first);
      range_it->second = htons(range_it->second);
    }
    if (port_type == tkz.SRC) {
      return FilterPtr(new PortFilter(std::move(ranges), SRC_PORT));
    }
    if (port_type == tkz.DST) {
      return FilterPtr(new PortFilter(std::move(ranges), DST_PORT));
    }
    if (port_type == tkz.PORT) {
      return FilterPtr(new PortFilter(std::move(ranges), EITHER_PORT));
    }
    ZX_DEBUG_ASSERT_MSG(port_type->one_of(tkz.SRC, tkz.DST, tkz.PORT),
                        "Invalid port type token: %s", port_type->get_term().c_str());
    return nullptr;
  }

  inline FilterPtr negation(FilterPtr filter) override {
    return FilterPtr(new NegFilter(std::move(filter)));
  }

  inline FilterPtr conjunction(FilterPtr left, FilterPtr right) override {
    return FilterPtr(new ConjFilter(std::move(left), std::move(right)));
  }

  inline FilterPtr disjunction(FilterPtr left, FilterPtr right) override {
    return FilterPtr(new DisjFilter(std::move(left), std::move(right)));
  }
};

}  // namespace netdump::parser

#endif  // SRC_CONNECTIVITY_NETWORK_NETDUMP_FILTER_BUILDER_IMPL_H_
