]> git.lizzy.rs Git - rust.git/blob - src/utils.rs
Merge pull request #114 from marcusklaas/rustup
[rust.git] / src / utils.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use syntax::ast::Visibility;
12
13 pub trait FindUncommented {
14     fn find_uncommented(&self, pat: &str) -> Option<usize>;
15 }
16
17 impl FindUncommented for str {
18     fn find_uncommented(&self, pat: &str) -> Option<usize> {
19         let mut needle_iter = pat.chars();
20         let mut possible_comment = false;
21
22         for (i, b) in self.char_indices() {
23             match needle_iter.next() {
24                 Some(c) => {
25                     if b != c {
26                         needle_iter = pat.chars();
27                     }
28                 },
29                 None => return Some(i - pat.len())
30             }
31
32             if possible_comment {
33                 if b == '/' {
34                     return self[(i+1)..].find('\n')
35                                         .and_then(|end| {
36                                             self[(end + i + 2)..].find_uncommented(pat)
37                                                                  .map(|idx| idx + end + i + 2)
38                                         });
39                 } else if b == '*' {
40                     return self[(i+1)..].find("*/")
41                                         .and_then(|end| {
42                                             self[(end + i + 3)..].find_uncommented(pat)
43                                                                  .map(|idx| idx + end + i + 3)
44                                         });
45                 } else {
46                     possible_comment = false;
47                 }
48             } else {
49                 possible_comment = b == '/';
50             }
51         }
52
53         // Handle case where the pattern is a suffix of the search string
54         match needle_iter.next() {
55             Some(_) => None,
56             None => Some(self.len() - pat.len())
57         }
58     }
59 }
60
61 #[test]
62 fn test_find_uncommented() {
63     fn check(haystack: &str, needle: &str, expected: Option<usize>) {
64         assert_eq!(expected, haystack.find_uncommented(needle));
65     }
66
67     check("/*//*/test", "test", Some(6));
68     check("//test\ntest", "test", Some(7));
69     check("/* comment only */", "whatever", None);
70     check("/* comment */ some text /* more commentary */ result", "result", Some(46));
71     check("sup // sup", "p", Some(2));
72     check("sup", "x", None);
73     check("π? /**/ π is nice!", "π is nice", Some(9));
74     check("/*sup yo? \n sup*/ sup", "p", Some(20));
75     check("hel/*lohello*/lo", "hello", None);
76     check("acb", "ab", None);
77 }
78
79 #[inline]
80 pub fn prev_char(s: &str, mut i: usize) -> usize {
81     if i == 0 { return 0; }
82
83     i -= 1;
84     while !s.is_char_boundary(i) {
85         i -= 1;
86     }
87     i
88 }
89
90 #[inline]
91 pub fn next_char(s: &str, mut i: usize) -> usize {
92     if i >= s.len() { return s.len(); }
93
94     while !s.is_char_boundary(i) {
95         i += 1;
96     }
97     i
98 }
99
100 #[inline]
101 pub fn make_indent(width: usize) -> String {
102     let mut indent = String::with_capacity(width);
103     for _ in 0..width {
104         indent.push(' ')
105     }
106     indent
107 }
108
109 #[inline]
110 pub fn format_visibility(vis: Visibility) -> &'static str {
111     match vis {
112         Visibility::Public => "pub ",
113         Visibility::Inherited => ""
114     }
115 }
116
117 #[inline]
118 #[cfg(target_pointer_width="64")]
119 // Based on the trick layed out at
120 // http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
121 pub fn round_up_to_power_of_two(mut x: usize) -> usize {
122     x = x.wrapping_sub(1);
123     x |= x >> 1;
124     x |= x >> 2;
125     x |= x >> 4;
126     x |= x >> 8;
127     x |= x >> 16;
128     x |= x >> 32;
129     x.wrapping_add(1)
130 }
131
132 #[inline]
133 #[cfg(target_pointer_width="32")]
134 pub fn round_up_to_power_of_two(mut x: usize) -> usize {
135     x = x.wrapping_sub(1);
136     x |= x >> 1;
137     x |= x >> 2;
138     x |= x >> 4;
139     x |= x >> 8;
140     x |= x >> 16;
141     x.wrapping_add(1)
142 }
143
144 // Macro for deriving implementations of Decodable for enums
145 #[macro_export]
146 macro_rules! impl_enum_decodable {
147     ( $e:ident, $( $x:ident ),* ) => {
148         impl ::rustc_serialize::Decodable for $e {
149             fn decode<D: ::rustc_serialize::Decoder>(d: &mut D) -> Result<Self, D::Error> {
150                 let s = try!(d.read_str());
151                 match &*s {
152                     $(
153                         stringify!($x) => Ok($e::$x),
154                     )*
155                     _ => Err(d.error("Bad variant")),
156                 }
157             }
158         }
159     };
160 }
161
162 #[test]
163 fn power_rounding() {
164     assert_eq!(0, round_up_to_power_of_two(0));
165     assert_eq!(1, round_up_to_power_of_two(1));
166     assert_eq!(64, round_up_to_power_of_two(33));
167     assert_eq!(256, round_up_to_power_of_two(256));
168 }