// Copyright (C) 2020-2025 Free Software Foundation, Inc.

// This file is part of GCC.

// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.

// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.

// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3.  If not see
// <http://www.gnu.org/licenses/>.

#ifndef RUST_CANONICAL_PATH
#define RUST_CANONICAL_PATH

#include "rust-system.h"
#include "rust-mapping-common.h"

namespace Rust {
namespace Resolver {

// https://doc.rust-lang.org/reference/paths.html#canonical-paths
//
// struct X - path X
// impl X { fn test - path X::test }
//
// struct X<T> - path X
//
// impl X<T>   { fn test - path X::test}
// impl X<i32> { fn test - path X<i32>::test }
// impl X<f32> { fn test - path X<f32>::test }
//
// pub trait Trait { // ::a::Trait
//   fn f(&self); // ::a::Trait::f
// }
//
// impl Trait for Struct {
//    fn f(&self) {} // <::a::Struct as ::a::Trait>::f
// }
class CanonicalPath
{
public:
  CanonicalPath (const CanonicalPath &other)
    : segs (other.segs), crate_num (other.crate_num)
  {}

  CanonicalPath &operator= (const CanonicalPath &other)
  {
    segs = other.segs;
    crate_num = other.crate_num;
    return *this;
  }

  static CanonicalPath new_seg (NodeId id, std::string path)
  {
    rust_assert (!path.empty ());
    return CanonicalPath ({std::pair<NodeId, std::string> (id,
							   std::move (path))},
			  UNKNOWN_CRATENUM);
  }

  static CanonicalPath
  trait_impl_projection_seg (NodeId id, const CanonicalPath &trait_seg,
			     const CanonicalPath &impl_type_seg)
  {
    // https://doc.rust-lang.org/reference/paths.html#canonical-paths
    // should be "<X>"?
    return CanonicalPath::new_seg (id, "<impl " + impl_type_seg.get () + " as "
					 + trait_seg.get () + ">");
  }

  static CanonicalPath inherent_impl_seg (NodeId id,
					  const CanonicalPath &impl_type_seg)
  {
    // https://doc.rust-lang.org/reference/paths.html#canonical-paths
    // should be "<X as Y>"?
    return CanonicalPath::new_seg (id, "<impl " + impl_type_seg.get () + ">");
  }

  std::string get () const
  {
    std::string buf;
    for (size_t i = 0; i < segs.size (); i++)
      {
	bool have_more = (i + 1) < segs.size ();
	const std::string &seg = segs.at (i).second;
	buf += seg + (have_more ? "::" : "");
      }
    return buf;
  }

  static CanonicalPath get_big_self (NodeId id)
  {
    return CanonicalPath::new_seg (id, "Self");
  }

  static CanonicalPath create_empty ()
  {
    return CanonicalPath ({}, UNKNOWN_CRATENUM);
  }

  bool is_empty () const { return segs.size () == 0; }

  CanonicalPath append (const CanonicalPath &other) const
  {
    rust_assert (!other.is_empty ());
    if (is_empty ())
      return CanonicalPath (other.segs, crate_num);

    std::vector<std::pair<NodeId, std::string>> copy (segs);
    for (auto &s : other.segs)
      copy.push_back (s);

    return CanonicalPath (copy, crate_num);
  }

  // if we have the path A::B::C this will give a callback for each segment
  // including the prefix, example:
  //
  // path:
  //   A::B::C
  //
  // iterate:
  //   A
  //   A::B
  //   A::B::C
  void iterate (std::function<bool (const CanonicalPath &)> cb) const
  {
    std::vector<std::pair<NodeId, std::string>> buf;
    for (auto &seg : segs)
      {
	buf.push_back (seg);
	if (!cb (CanonicalPath (buf, crate_num)))
	  return;
      }
  }

  // if we have the path A::B::C this will give a callback for each segment
  // example:
  //
  // path:
  //   A::B::C
  //
  // iterate:
  //   A
  //      B
  //         C
  void iterate_segs (std::function<bool (const CanonicalPath &)> cb) const
  {
    for (auto &seg : segs)
      {
	std::vector<std::pair<NodeId, std::string>> buf;
	buf.push_back ({seg.first, seg.second});
	if (!cb (CanonicalPath (buf, crate_num)))
	  return;
      }
  }

  size_t size () const { return segs.size (); }

  NodeId get_node_id () const
  {
    rust_assert (!segs.empty ());
    return segs.back ().first;
  }

  const std::pair<NodeId, std::string> &get_seg_at (size_t index) const
  {
    rust_assert (index < size ());
    return segs.at (index);
  }

  bool is_equal (const CanonicalPath &b) const
  {
    return get ().compare (b.get ()) == 0;
  }

  void set_crate_num (CrateNum n) { crate_num = n; }

  CrateNum get_crate_num () const
  {
    rust_assert (crate_num != UNKNOWN_CRATENUM);
    return crate_num;
  }

  bool operator== (const CanonicalPath &b) const { return is_equal (b); }

  bool operator< (const CanonicalPath &b) const { return get () < b.get (); }

private:
  explicit CanonicalPath (std::vector<std::pair<NodeId, std::string>> path,
			  CrateNum crate_num)
    : segs (path), crate_num (crate_num)
  {}

  std::vector<std::pair<NodeId, std::string>> segs;
  CrateNum crate_num;
};

} // namespace Resolver
} // namespace Rust

#endif // RUST_CANONICAL_PATH
