Hone logo
Hone
Problems

Implementing a Simple Format Macro in Rust

This challenge asks you to implement a simplified version of Rust's powerful format! macro. The goal is to create a macro that takes a format string and a variable number of arguments, and returns a formatted string. This exercise will help you understand macro expansion, argument handling, and string manipulation in Rust.

Problem Description

You are to implement a macro named simple_format! that behaves similarly to Rust's built-in format! macro, but with a limited feature set. The macro should accept a format string as its first argument, followed by a variable number of arguments to be inserted into the format string. The format string will only contain numbered placeholders (e.g., {0}, {1}, {2}, etc.). The macro should replace these placeholders with the corresponding arguments.

Key Requirements:

  • The macro must accept a format string and a variable number of arguments.
  • The format string should contain numbered placeholders {n}, where n is a non-negative integer.
  • The macro should replace each placeholder {n} with the argument at index n.
  • If a placeholder's index is out of bounds (i.e., the index is greater than or equal to the number of arguments), the placeholder should be replaced with an empty string.
  • The macro should return a String containing the formatted result.

Expected Behavior:

The macro should expand to code that constructs a String by replacing the placeholders in the format string with the provided arguments. The resulting string should be returned.

Edge Cases to Consider:

  • Empty format string.
  • Format string with no placeholders.
  • Format string with invalid placeholder indices (e.g., negative indices, non-integer indices).
  • Format string with placeholders beyond the number of provided arguments.
  • Format string with multiple occurrences of the same placeholder index.
  • Arguments of different types (the macro should handle them generically as impl std::fmt::Display).

Examples

Example 1:

Input: simple_format!("Hello, {}!", "world");
Output: "Hello, world!"
Explanation: The placeholder `{0}` is replaced with the argument "world".

Example 2:

Input: simple_format!("The answer is {0} and {1}.", 42, "life");
Output: "The answer is 42 and life."
Explanation: The placeholder `{0}` is replaced with 42, and `{1}` is replaced with "life".

Example 3:

Input: simple_format!("Value: {0}, {1}, {2}", 10, 20, 30);
Output: "Value: 10, 20, 30"
Explanation: All placeholders are replaced with their corresponding arguments.

Example 4: (Edge Case)

Input: simple_format!("Too many placeholders: {0}, {1}, {2}, {3}", 1, 2);
Output: "Too many placeholders: 1, 2, , "
Explanation: The placeholders `{2}` and `{3}` are out of bounds and replaced with empty strings.

Constraints

  • The format string will be a valid string literal.
  • Placeholder indices will be non-negative integers.
  • The number of arguments can vary.
  • The macro should be efficient enough to handle reasonably sized format strings and argument lists (up to 10 arguments). Performance is not the primary focus, but avoid excessively inefficient implementations.
  • All arguments must implement the std::fmt::Display trait.

Notes

  • You will need to use Rust's macro system to implement this.
  • Consider using format_args! to create a formatted argument list, then converting it to a String.
  • Error handling is not required; invalid format strings or out-of-bounds indices should be handled gracefully (as described in the Expected Behavior).
  • Focus on the core functionality of replacing placeholders with arguments. Advanced features like field width, precision, or type specifiers are not required.
  • The std::fmt::Display trait is crucial for handling different argument types. Use it to ensure your macro can format any type that implements it.
Loading editor...
rust