rust-mc-status 3.0.0

High-performance asynchronous Rust library for querying Minecraft server status (Java & Bedrock)
Documentation
//! Minecraft text formatting utilities.
//!
//! Minecraft uses `§` (section sign, U+00A7) followed by a single character
//! to encode colours and text styles in MOTDs and other strings.  These helpers
//! strip those codes and provide Unicode-safe string truncation.
//!
//! Both functions are re-exported from the crate root via
//! [`rust_mc_status::strip_formatting`](crate::strip_formatting) and
//! [`rust_mc_status::truncate_str`](crate::truncate_str).
//!
//! # Colour / formatting code reference
//!
//! | Code | Meaning | Code | Meaning |
//! |------|---------|------|---------|
//! | `§0`–`§9` | Colours (black–blue) | `§a`–`§f` | Colours (green–white) |
//! | `§k` | Obfuscated | `§l` | Bold |
//! | `§m` | Strikethrough | `§n` | Underline |
//! | `§o` | Italic | `§r` | Reset |

/// Strip Minecraft colour and formatting codes (`§X`) from a string.
///
/// Removes every `§` character and the single character that follows it,
/// then collapses all remaining whitespace runs (spaces, tabs, newlines) into
/// single spaces and trims the result.
///
/// # Example
///
/// ```
/// use rust_mc_status::strip_formatting;
///
/// // Hypixel MOTD with colours, newline, and bold
/// let raw = "§f  §aHypixel Network §c[1.8/1.21]\n§b§lEASTER EVENT";
/// assert_eq!(strip_formatting(raw), "Hypixel Network [1.8/1.21] EASTER EVENT");
///
/// // Plain text passes through unchanged (minus any extra whitespace)
/// assert_eq!(strip_formatting("Hello World"), "Hello World");
///
/// // Only formatting codes → empty string
/// assert_eq!(strip_formatting("§a§b§l"), "");
/// ```
pub fn strip_formatting(s: &str) -> String {
    let mut out   = String::with_capacity(s.len());
    let mut chars = s.chars();
    while let Some(c) = chars.next() {
        if c == '§' {
            chars.next(); // consume the code character (0-9, a-f, k-o, r, …)
        } else {
            out.push(c);
        }
    }
    // Collapse whitespace runs (including \n from multi-line MOTDs) and trim
    out.split_whitespace().collect::<Vec<_>>().join(" ")
}

/// Truncate a string to at most `max_chars` Unicode scalar values.
///
/// Unlike a raw byte slice (`&s[..n]`), this function always cuts on a valid
/// character boundary — safe for multibyte characters such as Cyrillic, CJK,
/// and emoji.  Returns the original string unchanged if it is shorter than
/// `max_chars`.
///
/// # Example
///
/// ```
/// use rust_mc_status::truncate_str;
///
/// // ASCII
/// assert_eq!(truncate_str("Hello, world!", 5), "Hello");
///
/// // Cyrillic (2 bytes per char — raw byte slicing would panic or corrupt)
/// assert_eq!(truncate_str("Привет, мир!", 7), "Привет,");
///
/// // Emoji (4 bytes per char)
/// assert_eq!(truncate_str("hello 🌍 world", 7), "hello 🌍");
///
/// // Shorter than limit — returned unchanged
/// assert_eq!(truncate_str("hi", 100), "hi");
///
/// // Limit 0 — always empty
/// assert_eq!(truncate_str("hello", 0), "");
/// ```
pub fn truncate_str(s: &str, max_chars: usize) -> &str {
    match s.char_indices().nth(max_chars) {
        Some((byte_pos, _)) => &s[..byte_pos],
        None => s,
    }
}