]> git.proxmox.com Git - rustc.git/blob - src/test/ui/issues/issue-3563-3.rs
New upstream version 1.60.0+dfsg1
[rustc.git] / src / test / ui / issues / issue-3563-3.rs
1 // run-pass
2 #![allow(unused_imports)]
3 #![allow(non_snake_case)]
4
5 // ASCII art shape renderer. Demonstrates traits, impls, operator overloading,
6 // non-copyable struct, unit testing. To run execute: rustc --test shapes.rs &&
7 // ./shapes
8
9 // Rust's std library is tightly bound to the language itself so it is
10 // automatically linked in. However the extra library is designed to be
11 // optional (for code that must run on constrained environments like embedded
12 // devices or special environments like kernel code) so it must be explicitly
13 // linked in.
14
15 // Extern mod controls linkage. Use controls the visibility of names to modules
16 // that are already linked in. Using WriterUtil allows us to use the write_line
17 // method.
18
19 use std::fmt;
20 use std::iter::repeat;
21 use std::slice;
22
23 // Represents a position on a canvas.
24 #[derive(Copy, Clone)]
25 struct Point {
26 x: isize,
27 y: isize,
28 }
29
30 // Represents an offset on a canvas. (This has the same structure as a Point.
31 // but different semantics).
32 #[derive(Copy, Clone)]
33 struct Size {
34 width: isize,
35 height: isize,
36 }
37
38 #[derive(Copy, Clone)]
39 struct Rect {
40 top_left: Point,
41 size: Size,
42 }
43
44 // Contains the information needed to do shape rendering via ASCII art.
45 struct AsciiArt {
46 width: usize,
47 height: usize,
48 fill: char,
49 lines: Vec<Vec<char> > ,
50
51 // This struct can be quite large so we'll disable copying: developers need
52 // to either pass these structs around via references or move them.
53 }
54
55 impl Drop for AsciiArt {
56 fn drop(&mut self) {}
57 }
58
59 // It's common to define a constructor sort of function to create struct instances.
60 // If there is a canonical constructor it is typically named the same as the type.
61 // Other constructor sort of functions are typically named from_foo, from_bar, etc.
62 fn AsciiArt(width: usize, height: usize, fill: char) -> AsciiArt {
63 // Build a vector of vectors containing blank characters for each position in
64 // our canvas.
65 let lines = vec![vec!['.'; width]; height];
66
67 // Rust code often returns values by omitting the trailing semi-colon
68 // instead of using an explicit return statement.
69 AsciiArt {width: width, height: height, fill: fill, lines: lines}
70 }
71
72 // Methods particular to the AsciiArt struct.
73 impl AsciiArt {
74 fn add_pt(&mut self, x: isize, y: isize) {
75 if x >= 0 && x < self.width as isize {
76 if y >= 0 && y < self.height as isize {
77 // Note that numeric types don't implicitly convert to each other.
78 let v = y as usize;
79 let h = x as usize;
80
81 // Vector subscripting will normally copy the element, but &v[i]
82 // will return a reference which is what we need because the
83 // element is:
84 // 1) potentially large
85 // 2) needs to be modified
86 let row = &mut self.lines[v];
87 row[h] = self.fill;
88 }
89 }
90 }
91 }
92
93 // Allows AsciiArt to be converted to a string using the libcore ToString trait.
94 // Note that the %s fmt! specifier will not call this automatically.
95 impl fmt::Display for AsciiArt {
96 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
97 // Convert each line into a string.
98 let lines = self.lines.iter()
99 .map(|line| line.iter().cloned().collect())
100 .collect::<Vec<String>>();
101
102 // Concatenate the lines together using a new-line.
103 write!(f, "{}", lines.join("\n"))
104 }
105 }
106
107 // This is similar to an interface in other languages: it defines a protocol which
108 // developers can implement for arbitrary concrete types.
109 trait Canvas {
110 fn add_point(&mut self, shape: Point);
111 fn add_rect(&mut self, shape: Rect);
112
113 // Unlike interfaces traits support default implementations.
114 // Got an ICE as soon as I added this method.
115 fn add_points(&mut self, shapes: &[Point]) {
116 for pt in shapes {self.add_point(*pt)};
117 }
118 }
119
120 // Here we provide an implementation of the Canvas methods for AsciiArt.
121 // Other implementations could also be provided (e.g., for PDF or Apple's Quartz)
122 // and code can use them polymorphically via the Canvas trait.
123 impl Canvas for AsciiArt {
124 fn add_point(&mut self, shape: Point) {
125 self.add_pt(shape.x, shape.y);
126 }
127
128 fn add_rect(&mut self, shape: Rect) {
129 // Add the top and bottom lines.
130 for x in shape.top_left.x..shape.top_left.x + shape.size.width {
131 self.add_pt(x, shape.top_left.y);
132 self.add_pt(x, shape.top_left.y + shape.size.height - 1);
133 }
134
135 // Add the left and right lines.
136 for y in shape.top_left.y..shape.top_left.y + shape.size.height {
137 self.add_pt(shape.top_left.x, y);
138 self.add_pt(shape.top_left.x + shape.size.width - 1, y);
139 }
140 }
141 }
142
143 // Rust's unit testing framework is currently a bit under-developed so we'll use
144 // this little helper.
145 pub fn check_strs(actual: &str, expected: &str) -> bool {
146 if actual != expected {
147 println!("Found:\n{}\nbut expected\n{}", actual, expected);
148 return false;
149 }
150 return true;
151 }
152
153
154 fn test_ascii_art_ctor() {
155 let art = AsciiArt(3, 3, '*');
156 assert!(check_strs(&art.to_string(), "...\n...\n..."));
157 }
158
159
160 fn test_add_pt() {
161 let mut art = AsciiArt(3, 3, '*');
162 art.add_pt(0, 0);
163 art.add_pt(0, -10);
164 art.add_pt(1, 2);
165 assert!(check_strs(&art.to_string(), "*..\n...\n.*."));
166 }
167
168
169 fn test_shapes() {
170 let mut art = AsciiArt(4, 4, '*');
171 art.add_rect(Rect {top_left: Point {x: 0, y: 0}, size: Size {width: 4, height: 4}});
172 art.add_point(Point {x: 2, y: 2});
173 assert!(check_strs(&art.to_string(), "****\n*..*\n*.**\n****"));
174 }
175
176 pub fn main() {
177 test_ascii_art_ctor();
178 test_add_pt();
179 test_shapes();
180 }