The Rust Programming Language

 
The Rust Programming
Language
 
Loukia Christina Ioannou
 Georgios Evangelou
 Winter 2023
 
1
 
Ιστορική αναδρομή
 
Ξεκίνησε το 2006 από τον Graydon Hoare με πρώτη σταθερή
έκδοση Rust 1.0 το 2015
Είναι διαθέσιμη σε πολλαπλές αρχιτεκτονικές και λειτουργικά
συστήματα (με χρήση του LLVM)
Ως γλώσσα προγραμματισμού συστημάτων και εφαρμογών με
έμφαση στην απόδοση, προσφέρεται ως εναλλακτική σε C/C++
Τα τελευταία 8 χρόνια ανακηρύσσεται από την ετήσια έρευνα
του Stack Overflow, ως η πιο αγαπητή γλώσσα
προγραμματισμού
 
2
 
Πλεονεκτήματα
 
Αποδοτικός κώδικας με τη βοήθεια του συστήματος τύπων και
του 'State of the Art' μεταγλωττιστή και του LLVM
Εγγυήσεις ασφάλειας μνήμης και ταυτοχρονίας μέσω του
συστήματος τύπων και του borrow checker χωρίς garbage
collection
Εξαιρετική τεκμηρίωση και πολύ καθοδηγητικά μηνύματα
σφαλμάτων από τον μεταγλωττιστή
 
3
 
Μειονεκτήματα
 
Δύσκολη εκμάθηση
Δύσκολη προσαρμογή από αντίστοιχα περιβάλλοντα
προγραμματισμού
Περίπλοκο σύστημα τύπων (borrow checking, generics)
 
4
 
Εγκατάσταση
 
Σε συστήματα Unix:
 
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
 
Σε Windows:
Εκτέλεση του 
rustup-init.exe
 
Υπάρχουν εναλλακτικές μεθόδοι στην ιστοσελίδα 
https://rust-
lang.org
 
5
 
Hello, world!
 
// main.rs
fn main() {
    println!("Hello, world!");
}
 
Μεταγλώττιση και εκτέλεση:
 
$ rustc main.rs
$ ./main
> Hello, world!
 
6
 
Υλοποίηση του stat(1) σε Rust
 
use std::env;
use std::fs;
use std::io::{Error, ErrorKind};
use std::os::unix::fs::{FileTypeExt, MetadataExt};
 
fn main() -> std::io::Result<()> {
    let args: Vec<String> = env::args().collect();
    if args.len() != 2 {
        let errmsg = format!("usage: {} filename", args[0]);
        return Err(Error::new(ErrorKind::Other, errmsg));
    }
    stat_print(&args[1])?
    Ok(())
}
 
7
 
fn stat_print(filename: &String) -> std::io::Result<()> {
    let md = fs::metadata(filename)?;
    println!("File: {}", filename);
    println!("Size: {}", md.len());
    println!("Blocks: {}", md.blocks());
    println!("IO Block: {}", md.blksize());
    println!("{}", file_type_str(md.file_type()));
    println!("Device: {:x}h/{}d", md.dev(), md.dev());
    println!("Inode: {}", md.ino());
    println!("Links: {}", md.nlink());
    println!("Access: {:04o}", md.mode() & 0o7777);
    println!("Uid: {}", md.uid());
    println!("Gid: {}", md.gid());
    println!("Access: {}", md.atime());
    println!("Modify: {}", md.mtime());
    println!("Change: {}", md.ctime());
    Ok(())
}
 
8
 
fn file_type_str(ft: fs::FileType) -> &'static str {
    if ft.is_dir() {
        return "directory";
    } else if ft.is_file() {
        return "regular file";
    } else if ft.is_symlink() {
        return "symbolic link";
    } else if ft.is_block_device() {
        return "block special file";
    } else if ft.is_char_device() {
        return "character special file";
    } else if ft.is_fifo() {
        return "fifo";
    } else if ft.is_socket() {
        return "socket";
    } else {
        return "unknown file type";
    }
}
 
9
 
Εκτέλεση του './
stat'
 
$ ./stat ./stat
File: ./stat
Size: 4718584
Blocks: 9216
IO Block: 4096
regular file
Device: 820h/2080d
Inode: 23279
Links: 1
Access: 0755
Uid: 1000
Gid: 1000
Access: 1701016966
Modify: 1701016961
Change: 1701016961
 
10
 
SMTP client 
σε 
Rust
 
fn main() -> Result<(), std::io::Error> {
    let args: Vec<String> = std::env::args().collect();
    if args.len() != 4 {
        eprintln!("Usage: {} emaildir smtpserver username", args[0]);
        return Ok(());
    }
    let mut args = args.into_iter();
    let _prog_name = args.next().unwrap();
    let email_str = args.next().unwrap();
    let email_dir = Path::new(&email_str);
 
11
 
 let mut smtp_conn = {
        let smtp_server = args.next().unwrap();
        let username = args.next().unwrap();
        SMTPConnection::new(smtp_server, username)?
    };
    for entry in fs::read_dir(&email_dir)? {
        let email = entry?.path();
        if email.is_file() {
            smtp_conn.send_email(&email)?;
        }
    }
    smtp_conn.close()?;
    Ok(())
}
 
12
 
use std::fs::{self, File};
use std::io::{BufRead, BufReader, Error, ErrorKind, Write};
use std::net::TcpStream;
use std::path::Path;
 
struct SMTPConnection {
    stream: TcpStream,
    reader: BufReader<TcpStream>,
    username: String,
    response: String,
}
 
13
 
impl SMTPConnection {
    pub const SMTP_PORT: u16 = 25;
 
    pub fn new(server: String, username: String) -> Result<Self, std::io::Error> {
        let stream = TcpStream::connect((server, Self::SMTP_PORT))?;
        let reader = BufReader::new(stream.try_clone()?);
        let mut conn = SMTPConnection {
            stream,
            reader,
            username,
            response: String::new(),
        };
        conn.check_response(220)?;
        conn.write(format!("HELO {}\r\n", conn.username))?;
        conn.check_response(250)?;
        Ok(conn)
    }
 
14
 
 fn check_response(&mut self, code: u32) -> Result<(), std::io::Error> {
        self.response.clear();
        self.reader.read_line(&mut self.response)?;
        let actual = self
            .response
            .split(' ')
            .next()
            .and_then(|c| c.parse::<u32>().ok())
            .unwrap();
        if actual != code {
            Err(Error::new(ErrorKind::Other, self.response.clone()))
        } else {
            Ok(())
        }
    }
 
15
 
 pub fn send_email(&mut self, email: &Path) -> Result<(),
std::io::Error> {
        self.write(format!("MAIL FROM: <{}>\r\n", &self.username))?;
        self.check_response(250)?;
        self.write(format!("RCPT TO: <{}>\r\n", &self.username))?;
        self.check_response(250)?;
        self.write("DATA\r\n")?;
        self.check_response(354)?;
        let lines = BufReader::new(File::open(email)?).lines();
 
16
 
 let mut header = true;
        for line in lines {
            let line = line?;
            if line == "\r\n" {
                header = false;
            }
            if !header && line.starts_with('.') {
                self.write(".")?;
            }
            self.write(line.replace('\n', "\r\n"))?;
        }
        self.write("\r\n.\r\n")?;
        self.check_response(250)?;
        Ok(())
    }
 
17
 
 fn write(&mut self, str: impl ToString) -> Result<(), std::io::Error> {
        self.stream.write(str.to_string().as_bytes())?;
        Ok(())
    }
 
    pub fn close(mut self) -> Result<(), std::io::Error> {
        self.write("QUIT\r\n")?;
        self.check_response(221)?;
        self.stream.shutdown(std::net::Shutdown::Both)?;
        Ok(())
    }
}
 
18
 
Γενικές Παρατηρήσεις
 
Ο μεταγλωττιστής είναι πλήρως καθοδηγητικός και
επεξηγηματικός με μηνύματα σε προγραμματιστικά λάθη
Η ανάπτυξη ήταν σχετικά χρονοβόρα λόγω της αυστηρότητας
της γλώσσας
Όμως δεν χρειάστηκε περαιτέρω αποσφαλμάτωση (if it
compiles, it works)
Η σύνταξη είναι ελαφρώς περίπλοκη αν και γνώριμη (C-like)
 
19
 
Αδυναμίες του 
standard library
 
Το 
standard library 
δεν περιείχε πολλές λειτουργίες που
παρέχονται απο πιο ώριμες γλώσσες (
signal handling, time
conversion/formatting)
Κάποιες πιο συγκεκριμένες 
unix 
λειτουργίες μπορούν να
υλοποιηθούν μονο μέσω 
ffi 
και της 
libc
Στη 
C 
και στο 
bash 
τέτοιες λειτουργίες παρέχονται 
natively,
όπως `
struct passwd *getpwuid(uid_t uid)` 
και `
struct group
*getgrgid(gid_t gid)`
 
20
 
Σύγκριση με άλλα εργαλεία
 
Η διαχείριση της μνήμης είναι πολύ πιο απλή από όσο είναι στη
C καθώς μέσω του borrow checker είχαμε εγγυήσεις ασφάλειας
μνήμης (dangling pointers, memory leaks, invalid memory
accesses)
Επειδή η γλώσσα μεταγλωττίζεται στατικά ήταν πιο εύκολο να
αποτραπούν λάθη σε σχέση με το αντίστοιχο πρόγραμμα σε
bash
 
21
 
Διαχείριση σφαλμάτων
 
Μέσω του συστήματος τύπων επιβάλλεται ο έλεγχος
σφαλμάτων και μπορεί να αποτραπεί η διάδοση ελέγχων
σφαλμάτων (`Optional<T>` και `Result<T,E>` τύποι)
Παρέχεται σύνταξη η οποία απλοποιεί τη διάδοση σφαλμάτων
(question mark operator '?')
Αυτοί οι μηχανισμοί διευκολύνουν τη ροή ελέγχου σε σχέση με
άλλες μεθόδους διαχείρισης σφαλμάτων που υποστηρίζονται
από άλλες γλώσσες (try catch blocks, callbacks)
 
22
 
Συμπεράσματα
 
Πέρα της πολυπλοκότητας της γλώσσας, η ανάπτυξη μεγάλων
προγραμμάτων μπορεί να γίνει πιο απλή και πιο προβλέψιμη η
αποσφαλμάτωση τους
Η Rust είναι ένας δυνατός ανταγωνιστής έναντι παρόμοιων
εργαλείων προγραμματισμού συστημάτων (C/C++)
 
23
 
Βιβλιογραφία
 
https://survey.stackoverflow.co/2023/#section-admired-and-
desired-programming-scripting-and-markup-languages
https://www.rust-lang.org/
https://doc.rust-lang.org/std/index.html
https://en.wikipedia.org/wiki/Rust_(programming_language)
 
24
Slide Note
Embed
Share

This presentation provides an in-depth look at The Rust Programming Language, highlighting its evolution, key features like borrow checking and generics, installation steps, and code examples. It covers essential concepts such as state-of-the-art LLVM, Rust's powerful borrow checker, and usage of standard libraries for filesystem operations. The content also includes a detailed explanation of file metadata retrieval in Rust. Dive into the world of Rust programming with this comprehensive guide.

  • Rust Language
  • Programming Concepts
  • Installation Steps
  • Filesystem Operations
  • File Metadata

Uploaded on Feb 16, 2025 | 0 Views


Download Presentation

Please find below an Image/Link to download the presentation.

The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author.If you encounter any issues during the download, it is possible that the publisher has removed the file from their server.

You are allowed to download the files provided on this website for personal or commercial use, subject to the condition that they are used lawfully. All files are the property of their respective owners.

The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author.

E N D

Presentation Transcript


  1. The Rust Programming Language Loukia Christina Ioannou Georgios Evangelou Winter 2023 1

  2. 2006 Graydon Hoare Rust 1.0 2015 ( LLVM) , C/C++ 8 Stack Overflow, 2

  3. 'State of the Art' LLVM borrow checker garbage collection 3

  4. (borrow checking, generics) 4

  5. Unix: $ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh Windows: rustup-init.exe https://rust- lang.org 5

  6. Hello, world! // main.rs fn main() { println!("Hello, world!"); } : $ rustc main.rs $ ./main > Hello, world! 6

  7. stat(1) Rust use std::env; use std::fs; use std::io::{Error, ErrorKind}; use std::os::unix::fs::{FileTypeExt, MetadataExt}; fn main() -> std::io::Result<()> { let args: Vec<String> = env::args().collect(); if args.len() != 2 { let errmsg = format!("usage: {} filename", args[0]); return Err(Error::new(ErrorKind::Other, errmsg)); } stat_print(&args[1])? Ok(()) } 7

  8. fn stat_print(filename: &String) -> std::io::Result<()> { let md = fs::metadata(filename)?; println!("File: {}", filename); println!("Size: {}", md.len()); println!("Blocks: {}", md.blocks()); println!("IO Block: {}", md.blksize()); println!("{}", file_type_str(md.file_type())); println!("Device: {:x}h/{}d", md.dev(), md.dev()); println!("Inode: {}", md.ino()); println!("Links: {}", md.nlink()); println!("Access: {:04o}", md.mode() & 0o7777); println!("Uid: {}", md.uid()); println!("Gid: {}", md.gid()); println!("Access: {}", md.atime()); println!("Modify: {}", md.mtime()); println!("Change: {}", md.ctime()); Ok(()) } 8

  9. fn file_type_str(ft: fs::FileType) -> &'static str { if ft.is_dir() { return "directory"; } else if ft.is_file() { return "regular file"; } else if ft.is_symlink() { return "symbolic link"; } else if ft.is_block_device() { return "block special file"; } else if ft.is_char_device() { return "character special file"; } else if ft.is_fifo() { return "fifo"; } else if ft.is_socket() { return "socket"; } else { return "unknown file type"; } } 9

  10. './stat' $ ./stat ./stat File: ./stat Size: 4718584 Blocks: 9216 IO Block: 4096 regular file Device: 820h/2080d Inode: 23279 Links: 1 Access: 0755 Uid: 1000 Gid: 1000 Access: 1701016966 Modify: 1701016961 Change: 1701016961 10

  11. SMTP client Rust fn main() -> Result<(), std::io::Error> { let args: Vec<String> = std::env::args().collect(); if args.len() != 4 { eprintln!("Usage: {} emaildir smtpserver username", args[0]); return Ok(()); } let mut args = args.into_iter(); let _prog_name = args.next().unwrap(); let email_str = args.next().unwrap(); let email_dir = Path::new(&email_str); 11

  12. let mut smtp_conn = { let smtp_server = args.next().unwrap(); let username = args.next().unwrap(); SMTPConnection::new(smtp_server, username)? }; for entry in fs::read_dir(&email_dir)? { let email = entry?.path(); if email.is_file() { smtp_conn.send_email(&email)?; } } smtp_conn.close()?; Ok(()) } 12

  13. use std::fs::{self, File}; use std::io::{BufRead, BufReader, Error, ErrorKind, Write}; use std::net::TcpStream; use std::path::Path; struct SMTPConnection { stream: TcpStream, reader: BufReader<TcpStream>, username: String, response: String, } 13

  14. impl SMTPConnection { pub const SMTP_PORT: u16 = 25; pub fn new(server: String, username: String) -> Result<Self, std::io::Error> { let stream = TcpStream::connect((server, Self::SMTP_PORT))?; let reader = BufReader::new(stream.try_clone()?); let mut conn = SMTPConnection { stream, reader, username, response: String::new(), }; conn.check_response(220)?; conn.write(format!("HELO {}\r\n", conn.username))?; conn.check_response(250)?; Ok(conn) } 14

  15. fn check_response(&mut self, code: u32) -> Result<(), std::io::Error> { self.response.clear(); self.reader.read_line(&mut self.response)?; let actual = self .response .split(' ') .next() .and_then(|c| c.parse::<u32>().ok()) .unwrap(); if actual != code { Err(Error::new(ErrorKind::Other, self.response.clone())) } else { Ok(()) } } 15

  16. pub fn send_email(&mut self, email: &Path) -> Result<(), std::io::Error> { self.write(format!("MAIL FROM: <{}>\r\n", &self.username))?; self.check_response(250)?; self.write(format!("RCPT TO: <{}>\r\n", &self.username))?; self.check_response(250)?; self.write("DATA\r\n")?; self.check_response(354)?; let lines = BufReader::new(File::open(email)?).lines(); 16

  17. let mut header = true; for line in lines { let line = line?; if line == "\r\n" { header = false; } if !header && line.starts_with('.') { self.write(".")?; } self.write(line.replace('\n', "\r\n"))?; } self.write("\r\n.\r\n")?; self.check_response(250)?; Ok(()) } 17

  18. fn write(&mut self, str: impl ToString) -> Result<(), std::io::Error> { self.stream.write(str.to_string().as_bytes())?; Ok(()) } pub fn close(mut self) -> Result<(), std::io::Error> { self.write("QUIT\r\n")?; self.check_response(221)?; self.stream.shutdown(std::net::Shutdown::Both)?; Ok(()) } } 18

  19. (if it compiles, it works) (C-like) 19

  20. standard library standard library (signal handling, time conversion/formatting) unix ffi libc C bash natively, `struct passwd *getpwuid(uid_t uid)` `struct group *getgrgid(gid_t gid)` 20

  21. C borrow checker (dangling pointers, memory leaks, invalid memory accesses) bash 21

  22. (`Optional<T>` `Result<T,E>` ) (question mark operator '?') (try catch blocks, callbacks) 22

  23. , Rust (C/C++) 23

  24. https://survey.stackoverflow.co/2023/#section-admired-and- desired-programming-scripting-and-markup-languages https://www.rust-lang.org/ https://doc.rust-lang.org/std/index.html https://en.wikipedia.org/wiki/Rust_(programming_language) 24

More Related Content

giItT1WQy@!-/#