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