1use std::io::Read;
2
3pub fn convert<R: Read>(mut reader: R) -> String {
4 let mut is_codeblock = false;
5 let mut is_hiperlink = false;
6 let mut collected_links: Vec<String> = vec![];
7 let mut links_stack: Vec<String> = vec![];
8 let mut last_byte = b'\0';
9 let mut bytes = vec![];
10 let mut byte = [0u8];
11
12 while reader.read(&mut byte).expect("failed to read file") != 0 {
13 let c = byte[0];
14 if c == b'`' && is_codeblock {
15 is_codeblock = false;
16 bytes.push(c);
17 } else if c == b'`' && !is_codeblock {
18 is_codeblock = true;
19 bytes.push(c);
20 } else if c == b'[' && !is_codeblock {
21 links_stack.push("".into());
22 bytes.push(c);
23 } else if c == b'(' && last_byte == b']' && !is_codeblock {
24 is_hiperlink = true;
25 } else if c == b')' && !is_codeblock && is_hiperlink {
26 is_hiperlink = false;
27 if let Some(link) = links_stack.pop() {
28 let pointer =
29 if let Some(position) = collected_links.iter().position(|l| l == &link) {
30 position + 1
31 } else {
32 collected_links.push(link);
33 collected_links.len()
34 };
35
36 bytes.push(b'[');
37 for b in pointer.to_string().bytes() {
38 bytes.push(b.clone());
39 }
40 bytes.push(b']');
41 } else {
42 bytes.push(c);
43 }
44 } else if !is_codeblock && is_hiperlink {
45 if let Some(link) = links_stack.last_mut() {
46 link.push(c as char);
47 } else {
48 bytes.push(c);
49 }
50 } else {
51 bytes.push(c);
52 };
53 last_byte = c;
54 }
55
56 if !collected_links.is_empty() {
57 bytes.push(b'\n');
58 bytes.push(b'\n');
59 for (i, link) in collected_links.iter().enumerate() {
60 for b in format!("[{}]:{}\n", i + 1, link).bytes() {
61 bytes.push(b);
62 }
63 }
64 }
65
66 String::from_utf8(bytes).expect("failed to render")
67}