summaryrefslogtreecommitdiffstats
path: root/src/test/ui/issues/issue-3563-3.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /src/test/ui/issues/issue-3563-3.rs
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/test/ui/issues/issue-3563-3.rs')
-rw-r--r--src/test/ui/issues/issue-3563-3.rs180
1 files changed, 180 insertions, 0 deletions
diff --git a/src/test/ui/issues/issue-3563-3.rs b/src/test/ui/issues/issue-3563-3.rs
new file mode 100644
index 000000000..bedfdab97
--- /dev/null
+++ b/src/test/ui/issues/issue-3563-3.rs
@@ -0,0 +1,180 @@
+// run-pass
+#![allow(unused_imports)]
+#![allow(non_snake_case)]
+
+// ASCII art shape renderer. Demonstrates traits, impls, operator overloading,
+// non-copyable struct, unit testing. To run execute: rustc --test shapes.rs &&
+// ./shapes
+
+// Rust's std library is tightly bound to the language itself so it is
+// automatically linked in. However the extra library is designed to be
+// optional (for code that must run on constrained environments like embedded
+// devices or special environments like kernel code) so it must be explicitly
+// linked in.
+
+// Extern mod controls linkage. Use controls the visibility of names to modules
+// that are already linked in. Using WriterUtil allows us to use the write_line
+// method.
+
+use std::fmt;
+use std::iter::repeat;
+use std::slice;
+
+// Represents a position on a canvas.
+#[derive(Copy, Clone)]
+struct Point {
+ x: isize,
+ y: isize,
+}
+
+// Represents an offset on a canvas. (This has the same structure as a Point.
+// but different semantics).
+#[derive(Copy, Clone)]
+struct Size {
+ width: isize,
+ height: isize,
+}
+
+#[derive(Copy, Clone)]
+struct Rect {
+ top_left: Point,
+ size: Size,
+}
+
+// Contains the information needed to do shape rendering via ASCII art.
+struct AsciiArt {
+ width: usize,
+ height: usize,
+ fill: char,
+ lines: Vec<Vec<char> > ,
+
+ // This struct can be quite large so we'll disable copying: developers need
+ // to either pass these structs around via references or move them.
+}
+
+impl Drop for AsciiArt {
+ fn drop(&mut self) {}
+}
+
+// It's common to define a constructor sort of function to create struct instances.
+// If there is a canonical constructor it is typically named the same as the type.
+// Other constructor sort of functions are typically named from_foo, from_bar, etc.
+fn AsciiArt(width: usize, height: usize, fill: char) -> AsciiArt {
+ // Build a vector of vectors containing blank characters for each position in
+ // our canvas.
+ let lines = vec![vec!['.'; width]; height];
+
+ // Rust code often returns values by omitting the trailing semi-colon
+ // instead of using an explicit return statement.
+ AsciiArt {width: width, height: height, fill: fill, lines: lines}
+}
+
+// Methods particular to the AsciiArt struct.
+impl AsciiArt {
+ fn add_pt(&mut self, x: isize, y: isize) {
+ if x >= 0 && x < self.width as isize {
+ if y >= 0 && y < self.height as isize {
+ // Note that numeric types don't implicitly convert to each other.
+ let v = y as usize;
+ let h = x as usize;
+
+ // Vector subscripting will normally copy the element, but &v[i]
+ // will return a reference which is what we need because the
+ // element is:
+ // 1) potentially large
+ // 2) needs to be modified
+ let row = &mut self.lines[v];
+ row[h] = self.fill;
+ }
+ }
+ }
+}
+
+// Allows AsciiArt to be converted to a string using the libcore ToString trait.
+// Note that the %s fmt! specifier will not call this automatically.
+impl fmt::Display for AsciiArt {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ // Convert each line into a string.
+ let lines = self.lines.iter()
+ .map(|line| line.iter().cloned().collect())
+ .collect::<Vec<String>>();
+
+ // Concatenate the lines together using a new-line.
+ write!(f, "{}", lines.join("\n"))
+ }
+}
+
+// This is similar to an interface in other languages: it defines a protocol which
+// developers can implement for arbitrary concrete types.
+trait Canvas {
+ fn add_point(&mut self, shape: Point);
+ fn add_rect(&mut self, shape: Rect);
+
+ // Unlike interfaces traits support default implementations.
+ // Got an ICE as soon as I added this method.
+ fn add_points(&mut self, shapes: &[Point]) {
+ for pt in shapes {self.add_point(*pt)};
+ }
+}
+
+// Here we provide an implementation of the Canvas methods for AsciiArt.
+// Other implementations could also be provided (e.g., for PDF or Apple's Quartz)
+// and code can use them polymorphically via the Canvas trait.
+impl Canvas for AsciiArt {
+ fn add_point(&mut self, shape: Point) {
+ self.add_pt(shape.x, shape.y);
+ }
+
+ fn add_rect(&mut self, shape: Rect) {
+ // Add the top and bottom lines.
+ for x in shape.top_left.x..shape.top_left.x + shape.size.width {
+ self.add_pt(x, shape.top_left.y);
+ self.add_pt(x, shape.top_left.y + shape.size.height - 1);
+ }
+
+ // Add the left and right lines.
+ for y in shape.top_left.y..shape.top_left.y + shape.size.height {
+ self.add_pt(shape.top_left.x, y);
+ self.add_pt(shape.top_left.x + shape.size.width - 1, y);
+ }
+ }
+}
+
+// Rust's unit testing framework is currently a bit under-developed so we'll use
+// this little helper.
+pub fn check_strs(actual: &str, expected: &str) -> bool {
+ if actual != expected {
+ println!("Found:\n{}\nbut expected\n{}", actual, expected);
+ return false;
+ }
+ return true;
+}
+
+
+fn test_ascii_art_ctor() {
+ let art = AsciiArt(3, 3, '*');
+ assert!(check_strs(&art.to_string(), "...\n...\n..."));
+}
+
+
+fn test_add_pt() {
+ let mut art = AsciiArt(3, 3, '*');
+ art.add_pt(0, 0);
+ art.add_pt(0, -10);
+ art.add_pt(1, 2);
+ assert!(check_strs(&art.to_string(), "*..\n...\n.*."));
+}
+
+
+fn test_shapes() {
+ let mut art = AsciiArt(4, 4, '*');
+ art.add_rect(Rect {top_left: Point {x: 0, y: 0}, size: Size {width: 4, height: 4}});
+ art.add_point(Point {x: 2, y: 2});
+ assert!(check_strs(&art.to_string(), "****\n*..*\n*.**\n****"));
+}
+
+pub fn main() {
+ test_ascii_art_ctor();
+ test_add_pt();
+ test_shapes();
+}