1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#![doc(html_root_url = "https://docs.rs/syn_str/0.1.58/")]
#![no_std]

/*! This crate is designed specially for those who want to create procedural macros thought string
manipulation,using `proc_macro::TokenStream::to_string` and `String::parse::<TokenStream>`,bringing
useful types that separe the importants parts of an item and provide display `impl`'s of they as if it
were never parsed.

When parsing a struct the fields are ordered from less to big alignment,better ideas for align them
are welcome.

This crate parses well stringified items that give no syntax errors,in the opposite the functions can
misbehave instead of throwing errors,as such this crate is intended for build procedural macros and
an item with invalid syntax throws a compiler error before a procedural macro attribute can do
anything.

Support for expressions,functions and traits will come in the future.

This crate is **no_std**. */

extern crate alloc;
use alloc::vec::Vec;
use alloc::string::{String, ToString};

use fixed_len_str::fixed_len_str;

fixed_len_str!(4);
fixed_len_str!(40);

/** Remove all the non-doc comments from an stringified item,for the doc ones use
[remove_item_attrs](./fn.remove_item_attrs.html) instead.

# Errors

This function will throw an error at an unmatched comment block delimiter `/**/`
thing that almost never occurs when writing procedural macros because this
throws a compiler error before a macro can do any.
*/
pub fn remove_comments(item: &str) -> Result<String, &'static str> {
    let mut item = item.to_string();

    while let Some(i) = item.find("//") {
        let temp = &item[i..];

        item = item.replace(&temp[..match temp.find("
") {
            Some(i) => i,
            None => temp.len(),
        } + 2], "");
    }

    while let Some(i) = item.find("/*") {
        let temp = &item[i..];

        item = item.replace(&temp[..match temp.find("*/") {
            Some(i) => i,
            None => return Err("Detected unmatched comment block init '/*'"),
        } + 2], "");
    }

    Ok(item)
}

/** Remove the attributes and doc comments of a stringified item,useful for write procedural macro
attributes.
 
# Errors

This function will throw an error if encounters any unmatched delimiter("[]", "{}", "()", "<>")
while trying to remove the attributes,in the attributes and their delimiters.

This function also remove comments so in the future the name can change.
*/
pub fn remove_item_attrs(item: &str) -> Result<String, &'static str> {
    let mut item = item.lines().filter(|s| !s.trim().starts_with("///")).collect::<Vec<&str>>().join("
");

    item = remove_comments(&item[..])?;

    while let Some(i) = item.find("*/") {
        item = (&item[i+2..]).to_string();
    } 

    while let Some(i) = item.find("#[") {
        let mut open_brace_count = -1;

        item = item.replace(&item[i..=match (&item[i..]).find(|c: char| {
            if c == '[' || c == '(' || c == '{' || c == '<' {
                open_brace_count += 1;
            }

            if c == ']' || c == ')' || c == '}' || c == '>' {
                open_brace_count -= 1;
            }

            if open_brace_count > 0 {
                return false;
            }

            c == ']'
        }) {
            Some(i) => i,
            None => return Err("Detected unmatched '[' in item."),
        }], "");

        if open_brace_count != -1 {
            return Err("Detected unmatched delimiter('[]', '{}', '()', '<>')");
        }
    }

    Ok(item)
}

pub mod custom_types;
pub mod statics;
/*
pub mod block;
pub mod function;
*/