// Copyright (C) 2023-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
// .
#ifndef RUST_FMT_H
#define RUST_FMT_H
#include "rust-system.h"
// FIXME: How to encode Option?
namespace Rust {
namespace Fmt {
namespace ffi {
struct RustHamster
{
const char *ptr;
size_t len;
std::string to_string () const;
};
/// Enum of alignments which are supported.
enum class Alignment
{
/// The value will be aligned to the left.
AlignLeft,
/// The value will be aligned to the right.
AlignRight,
/// The value will be aligned in the center.
AlignCenter,
/// The value will take on a default alignment.
AlignUnknown,
};
/// Enum for the debug hex flags.
enum class DebugHex
{
/// The `x` flag in `{:x?}`.
Lower,
/// The `X` flag in `{:X?}`.
Upper,
};
/// Enum for the sign flags.
enum class Sign
{
/// The `+` flag.
Plus,
/// The `-` flag.
Minus,
};
/// Enum describing where an argument for a format can be located.
struct Position
{
enum class Tag
{
/// The argument is implied to be located at an index
ArgumentImplicitlyIs,
/// The argument is located at a specific index given in the format,
ArgumentIs,
/// The argument has a name.
ArgumentNamed,
};
struct ArgumentImplicitlyIs_Body
{
size_t _0;
};
struct ArgumentIs_Body
{
size_t _0;
};
struct ArgumentNamed_Body
{
RustHamster _0;
};
Tag tag;
union
{
ArgumentImplicitlyIs_Body argument_implicitly_is;
ArgumentIs_Body argument_is;
ArgumentNamed_Body argument_named;
};
};
/// Range inside of a `Span` used for diagnostics when we only have access to
/// relative positions.
struct InnerSpan
{
size_t start;
size_t end;
};
/// A count is used for the precision and width parameters of an integer, and
/// can reference either an argument or a literal integer.
struct Count
{
enum class Tag
{
/// The count is specified explicitly.
CountIs,
/// The count is specified by the argument with the given name.
CountIsName,
/// The count is specified by the argument at the given index.
CountIsParam,
/// The count is specified by a star (like in `{:.*}`) that refers to the
/// argument at the given index.
CountIsStar,
/// The count is implied and cannot be explicitly specified.
CountImplied,
};
struct CountIs_Body
{
size_t _0;
};
struct CountIsName_Body
{
RustHamster _0;
InnerSpan _1;
};
struct CountIsParam_Body
{
size_t _0;
};
struct CountIsStar_Body
{
size_t _0;
};
Tag tag;
union
{
CountIs_Body count_is;
CountIsName_Body count_is_name;
CountIsParam_Body count_is_param;
CountIsStar_Body count_is_star;
};
};
/// Specification for the formatting of an argument in the format string.
struct FormatSpec
{
/// Optionally specified character to fill alignment with.
const uint32_t *fill;
/// Span of the optionally specified fill character.
const InnerSpan *fill_span;
/// Optionally specified alignment.
Alignment align;
/// The `+` or `-` flag.
const Sign *sign;
/// The `#` flag.
bool alternate;
/// The `0` flag.
bool zero_pad;
/// The `x` or `X` flag. (Only for `Debug`.)
const DebugHex *debug_hex;
/// The integer precision to use.
Count precision;
/// The span of the precision formatting flag (for diagnostics).
const InnerSpan *precision_span;
/// The string width requested for the resulting format.
Count width;
/// The span of the width formatting flag (for diagnostics).
const InnerSpan *width_span;
/// The descriptor string representing the name of the format desired for
/// this argument, this can be empty or any number of characters, although
/// it is required to be one word.
RustHamster ty;
/// The span of the descriptor string (for diagnostics).
const InnerSpan *ty_span;
};
/// Representation of an argument specification.
struct Argument
{
/// Where to find this argument
Position position;
/// The span of the position indicator. Includes any whitespace in implicit
/// positions (`{ }`).
InnerSpan position_span;
/// How to format the argument
FormatSpec format;
};
/// A piece is a portion of the format string which represents the next part
/// to emit. These are emitted as a stream by the `Parser` class.
struct Piece
{
enum class Tag
{
/// A literal string which should directly be emitted
String,
/// This describes that formatting should process the next argument (as
/// specified inside) for emission.
NextArgument,
};
struct String_Body
{
RustHamster _0;
};
struct NextArgument_Body
{
Argument _0;
};
Tag tag;
union
{
String_Body string;
NextArgument_Body next_argument;
};
};
struct PieceSlice
{
const Piece *base_ptr;
size_t len;
size_t cap;
};
struct RustString
{
const unsigned char *ptr;
size_t len;
size_t cap;
};
struct FormatArgsHandle
{
PieceSlice piece_slice;
RustString rust_string;
};
enum ParseMode
{
Format = 0,
InlineAsm,
};
extern "C" {
FormatArgsHandle
collect_pieces (const char *input, bool append_newline, ParseMode parse_mode);
FormatArgsHandle
clone_pieces (const FormatArgsHandle &);
void destroy_pieces (FormatArgsHandle);
} // extern "C"
} // namespace ffi
struct Pieces
{
static Pieces collect (const std::string &to_parse, bool append_newline,
ffi::ParseMode parse_mode);
~Pieces ();
Pieces (const Pieces &other);
Pieces &operator= (const Pieces &other);
Pieces (Pieces &&other);
const std::vector &get_pieces () const { return pieces_vector; }
// {
// slice = clone_pieces (&other.slice);
// to_parse = other.to_parse;
// return *this;
// }
private:
Pieces (ffi::FormatArgsHandle handle, std::vector &&pieces_vector)
: pieces_vector (std::move (pieces_vector)), handle (handle)
{}
std::vector pieces_vector;
// this memory is held for FFI reasons - it needs to be released and cloned
// precisely, so try to not access it/modify it if possible. you should
// instead work with `pieces_vector`
ffi::FormatArgsHandle handle;
};
} // namespace Fmt
} // namespace Rust
#endif // !RUST_FMT_H