AzLearn

تمرين إعادة البناء

Markdown Link Extractor

أعد كتابة مستخرج روابط Markdown يعرض النص والوجهة لكل رابط.

rust ~18 دقيقة متوسط
أعد بناء الكود Rebuild

هذا هو الكود. اكتبه بنفسك.

الكود المرجعي
use std::env;
use std::fs;
use std::io::{self, Read};

fn main() -> io::Result<()> {
    let markdown = match env::args().nth(1) {
        Some(path) => fs::read_to_string(path)?,
        None => {
            let mut input = String::new();
            io::stdin().read_to_string(&mut input)?;
            input
        }
    };

    for link in extract_links(&markdown) {
        println!("{} -> {}", link.text, link.url);
    }

    Ok(())
}

#[derive(Debug)]
struct Link {
    text: String,
    url: String,
}

fn extract_links(markdown: &str) -> Vec<Link> {
    let bytes = markdown.as_bytes();
    let mut links = Vec::new();
    let mut index = 0;

    while index + 3 < bytes.len() {
        if bytes[index] == b'[' {
            if let Some(close_text) = find_byte(bytes, index + 1, b']') {
                if bytes.get(close_text + 1) == Some(&b'(') {
                    if let Some(close_url) = find_byte(bytes, close_text + 2, b')') {
                        links.push(Link {
                            text: markdown[index + 1..close_text].to_string(),
                            url: markdown[close_text + 2..close_url].to_string(),
                        });
                        index = close_url + 1;
                        continue;
                    }
                }
            }
        }

        index += 1;
    }

    links
}

fn find_byte(bytes: &[u8], start: usize, needle: u8) -> Option<usize> {
    bytes
        .iter()
        .enumerate()
        .skip(start)
        .find_map(|(index, byte)| (*byte == needle).then_some(index))
}
اكتب هنا