SlideShare a Scribd company logo
1 of 25
Download to read offline
overexact.com
Rustforprofessionals
Introduction
Naming
Syntax
Variables
Types
Mutability
Destructuring
Functions
Innerfunctions
Extensionmethods
Closures(lambdas)
Expressions
Structs(classes)
Traits(interfaces)
Defaultmethods
Associatedfunctions
Enums
Associatedvalues
Concepts
Ownership
Strings
Nullvalues
Errorhandling
Input
Attributes(annotations)
Miscellaneous
Packagemanagement
Projectsetup
Usefullinks
Introduction ↑
ThisisashortintroductiontoRust,intendedfordevelopersthatalreadyknowanother
language.Intheexamples,RustiscomparedwithTypeScript,JavaScriptorJava,sometimes
withC++orKotlin.
ForadeepdiveintothesyntaxandRust’sconcepts,havealookatTheRustProgramming
Language,butforaquickoverview,readon.
Naming
Regardingnames,Rustpreferssnakecaseforvariablesandfunctions,soamethodwould
becalled read_str insteadof readStr.Forstructs,traitsandenums,camelcase(orPascal
case)isused,forexample HttpClient.
Syntax
Rust’ssyntaxisamixofexistinglanguages(curlybraces,functionsandreferenceslikeinC,
typeafteridentifierlikeinGoorKotlin,genericsandtypeparameterslikeinC++orJava)
withsomeRust-specificelements(lifetimenames,patterns,macros,attributes).Foraquick
overviewofthesyntax,seetheRustLanguageCheatSheetoranoverviewofRust’s
keywords.
Variables
RustvariabledeclarationsareverysimilartoTypeScriptorKotlin,butlookabitdifferentfrom
JavaorC.
const s: string = "";
let n: number = 0.9;
let i = 123; // Type inferred
let s: &str = "";
let mut n: f64 = 0.9;
let mut i = 123; // Type inferred
Mostofthetime,thetypecanbeommittedinRustandthecompilerwillinferthecorrecttype
Types
InRust,therearemorespecificprimitivedatatypes.
Thevoidtypeiscalledunitandisindicatedby (),seefunctionsforanexample.
int i = 123;
long l = 456L;
float f = 0.5f;
double d = 0.5;
TypeScript
Rust
Java
↑
String string = "Hello";
int[] arr = {1, 2, 3};
List<Integer> list = Arrays.asList(1, 2, 3);
let i: i32 = 123;
let l: i64 = 456;
let f: f32 = 0.5;
let d: f64 = 0.5f64;
let string: &str = "Hello";
let arr: [i32; 3] = [1, 2, 3];
let list: Vec<i32> = vec![1, 2, 3];
InRust,numericliteralscanoptionallyhaveatypesuffix,forexample1000u32 or0.5f64.
Mutability
Variablesneedtobeexplicitlydeclaredmutable(let versus let mut),likeinJavaScript
(const and let)orKotlin(val and var).
ThemutabilitymodelinRustisnotlikeJavaScript,butabitmorelikeconstinC++,asRust
willnotletyoucallmodifyingmethodsonavariablewhichisnotdeclaredasmutable.
let arr1: string[] = [];
arr1.push("123"); // OK
arr1 = ["a", "b"]; // OK
const arr2: string[] = [];
arr2.push("123"); // OK, even though arr2 is const
arr2 = []; // error, arr2 is const
let mut arr1 = vec![];
arr1.push("123"); // OK
arr1 = vec!["a", "b"]; // OK
let arr2 = vec![];
arr2.push("123"); // error, arr2 is not mutable
arr2 = vec![]; // error, arr2 is not mutable
InTypeScript,declaringavariableasconst onlypreventsreassignment,notmodification.InRust,only
variablesdeclaredasmut canbemodified
Destructuring
Rust
TypeScript
Rust
↑
Rustsupportsdestructuring,likeJavaScriptorKotlin.
function distance(a, b) {
const { x: x1, y: y1 } = a;
const { x: x2, y: y2 } = b;
return Math.sqrt(
Math.pow(x2 - x1, 2) +
Math.pow(y2 - y1, 2)
);
}
fn distance(a: &Point, b: &Point) -> f32 {
let Point { x: x1, y: y1 } = a;
let Point { x: x2, y: y2 } = b;
((x2 - x1).powf(2.0) + (y2 - y1).powf(2.0)).sqrt()
}
struct Point {
x: f32,
y: f32,
}
MoreexamplescanbefoundinthissectionfromtheRustforC++programmersguide
Functions
FunctionsarebasicallythesameasinC,Java,GoorTypeScript:Theyhaveaname,zeroor
moreparametersandareturntype.
void log(char* message) {
printf("INFO %sn", message);
}
fn log(message: &str) -> () {
println!("INFO {}", message);
}
Theunittype() (voidinsomelanguages)isthedefaultreturntypewhennotypeisgivenforafunction.It
couldbeomittedinthisexample,likefn log(message: &str) { ... }
InRust,functionsareexpressions,whichmeansthelaststatementisalsothereturnvalue
(likeinRuby).Thisisabitlikeimplicitreturn,butnotexactly.Theofficialstyleistoonlyuse
return forearlyreturns.
public static int add(int a, int b) {
return a + b;
}
JavaScript
Rust
C
Rust
Java
↑
fn add(a: i32, b: i32) -> i32 {
a + b
}
NotethatthereisnosemicolonintheRustfunction,otherwiseitwouldreturnvoid
Rustcurrentlyhasnonamedargumentsordefaultarguments(likePythonandTypeScript)
anddoesnotallowmethodoverloading(likeC++,JavaorTypeScript).
Innerfunctions
Rustalsosupportsinnerfunctions.
const RE = /^[0-9]{4}-[0-9]{2}-[0-9]{2}$/;
function isValidRange(start, end) {
function isValid(date) {
return date && date.match(RE);
}
return isValid(start) && isValid(end);
}
use regex::Regex;
const RE: &str = r"^[0-9]{4}-[0-9]{2}-[0-9]{2}$";
fn is_valid_range(start: &str, end: &str) -> bool {
fn is_valid(date: &str) -> bool {
!date.is_empty()
&& Regex::new(RE)
.unwrap()
.is_match(date)
}
is_valid(start) && is_valid(end)
}
NotethatRegex isanexternalcrateandnotpartofRust’sstandardlibrary
Extensionmethods
Rust(likeKotlin)alsosupportsextensionmethods,sothepreviousexamplecouldbe
rewrittenusingextensions.
typealias Range = Pair<String, String>
fun Range.isValid(): Boolean {
val (start, end) = this
Rust
JavaScript
Rust
Kotlin
↑
return start.isNotEmpty() && end.isNotEmpty()
}
object Main {
@JvmStatic
fun main(args: Array<String>) {
val range = Range("2020-01-01", "2020-12-31")
if (range.isValid()) {
println("Range is valid!")
}
}
}
type Range<'r> = (&'r str, &'r str);
trait IsValid {
fn is_valid(&self) -> bool;
}
impl<'r> IsValid for Range<'r> {
fn is_valid(&self) -> bool {
let (start, end) = &self;
!start.is_empty() && !end.is_empty()
}
}
fn main() {
let range = ("2020-01-01", "2020-12-31");
if range.is_valid() {
println!("Range is valid!");
}
}
InRust,extensionmethodsareaddedbyimplementingatrait.Whenthereisonlyonemethod,it’scommon
tonamethetraitlikethemethod(IsValid).The'r denotesalifetime,formoreinformation,seethis
sectionfromtheRustbook
Closures(lambdas)
Rustsupportsclosures(alsocalledLambdas,arrowfunctionsoranonymousfunctionsin
otherlanguages).
Whenaccessingvariablesfromoutsidetheclosure,RustismorestrictthanJavaScriptor
Java,seecapturingformoredetails.
function findEmails(list) {
return list.filter(
s => s && s.includes("@")
Rust
JavaScript
↑
);
}
fn find_emails(list: Vec<String>) -> Vec<String> {
list.into_iter()
.filter(|s| s.contains("@"))
.collect()
}
Formorefilterexamples,seethissectionfromthedocumentation
Expressions
InRust,almosteverythingisanexpression,likeinKotlinanddifferentfromJavaScriptor
Java.Youcandirectlyassigntheresultofan if statementtoavariable,forexample.
function getLogLevel() {
let level = process.env.TRACE
? "trace"
: process.env.DEBUG
? "debug"
: "info";
level =
level === "trace"
? 0
: level === "debug"
? 1
: 2;
console.log("using log level", level);
return level;
}
fn get_log_level() -> u32 {
let level = if std::env::var("TRACE").is_ok() {
"trace"
} else if std::env::var("DEBUG").is_ok() {
"debug"
} else {
"info"
};
let level = match level {
"trace" => 0,
"debug" => 1,
_ => 2,
Rust
JavaScript
Rust
↑
};
println!("using log level {}", level);
level
}
TheRustcodeusesmatch,whichislikeswitch inJavaorJavaScriptexceptthatit’sanexpressionand
providesmoreflexibility.Unlessmanyotherlanguages,Rustallowsvariableshadowingforlocalvariables
(level inthisexample)
Structs(classes)
RustdoesnothavefullsupportforclasseslikeJavaorTypeScript,butinsteadoffersstructs
(similartostructsinC).Thesearelikedatacontainerswithmethods,buttheydon’tsupport
alloftheobjectorientedconcepts,likeinheritance.
public class HttpClient {
private final ClientImpl clientImpl;
public HttpClient() {
clientImpl = new ClientImpl();
}
public String get(String url) {
return clientImpl.newRequest()
.get(url).asString();
}
}
public static void main(String[] args) {
HttpClient httpClient = new HttpClient();
System.out.println(httpClient
.get("https://example.com/"));
}
pub struct HttpClient {
client_impl: ClientImpl,
}
impl HttpClient {
pub fn new() -> HttpClient {
HttpClient {
client_impl: ClientImpl {},
}
}
pub fn get(&self, url: &str) -> String {
self.client_impl.new_request()
Java
Rust
↑
.get(url)
.as_string()
}
}
fn main() {
let http_client = HttpClient::new();
println!("{}",
http_client.get("https://example.com/"));
}
InJava,mutabilityisgivenonafieldlevel,hereclientImpl isimmutable.InRust,themutabilitymodifieris
setontheinstancevariableandnotperfield,soyoucannothavemutableandimmutablefieldsinthe
samestruct(seetheInteriorMutabilityPattern)
Methodsdonothaveimplicitaccesstothis,asinJavaorJavaScript,soyouneedtopassan
explicitargumentnamed self,likeinPython.Methodswithoutthisparameterarecalled
associatedfunctions(theyarecalledstaticmethodsinsomelanguages).
InRust,thereisnoconstructor,structsarecreatedsimilarlytoobjectsinJavaScript.For
caseswhereconstructorlogicisrequired,thereisaconventiontocreateanassociated
function(staticmethod)named new,whichwillreturntheconstructedobjectinstance.
Traits(interfaces)
ThemostsimilarthingtointerfacesinRustaretraits.
interface Named {
fun name(): String
}
data class User(
val id: Int,
val name: String
) : Named {
override fun name(): String {
return this.name
}
}
pub trait Named {
fn name(&self) -> &String;
}
pub struct User {
pub id: i32,
pub name: String,
}
Kotlin
Rust
↑
impl Named for User {
fn name(&self) -> &String {
return &self.name;
}
}
Rustismostlyastaticlanguage,sosomethingsthatotherlanguagewilldoduringruntime,
Rustwilldoduringcompiletime,whenpossible.Interfacesareusuallyusedfordynamic
dispatchandifyouwanttousetraitsinasimilarway,seethischapteraboutstaticand
dynamicdispatchandthisblogpost.
Defaultmethods
Traitsalsosupportdefaultmethods,likeinterfacesinJavaorKotlin.
Associatedfunctions
InRust,traitscanalsohaveassociatedfunctions,forexample from_str in
std::str::FromStr (sectionstringparsingintheRustCookbook)
interface FromList<T> {
fun fromList(list: List<Int>): T?
}
data class MyPoint(val x: Int, val y: Int) {
companion object : FromList<MyPoint> {
override fun fromList(list: List<Int>):
MyPoint? {
return when (list.size) {
2 -> MyPoint(list[0], list[1])
else -> null
}
}
}
}
object Main {
@JvmStatic
fun main(args: Array<String>) {
val point = MyPoint.fromList(listOf(100, 200))
println(point)
}
}
trait FromList<T> {
fn from_list(list: &Vec<i32>) -> Option<T>;
}
struct MyPoint {
Kotlin
Rust
↑
x: i32,
y: i32,
}
impl FromList<Self> for MyPoint {
fn from_list(list: &Vec<i32>) -> Option<Self> {
match list.len() {
2 => Some(MyPoint {
x: list[0],
y: list[1],
}),
_ => None,
}
}
}
fn main() {
let point =
MyPoint::from_list(&vec![100, 200]).unwrap();
println!("({}, {})", point.x, point.y);
}
FormoreinformationabouttheOption type,seetheNullvaluessectionbelow.ThekeywordSelf (upper
case)canbeusedtoreferencethecurrenttype
Enums
Rustsupportsenums,likeJavaorKotlin,butwithmoreflexibility.TheRustenumsoffermore
thaninC++orTypeScript,astheyarenotmerelyalistofconstants,butmorelikeunions.
enum UserRole {
RO("read-only"), USER("user"),
ADMIN("administrator");
private final String name;
UserRole(String name) {
this.name = name;
}
String getName() {
return name;
}
boolean isAccessAllowed(String httpMethod) {
switch (httpMethod) {
case "HEAD":
case "GET":
return true;
Java
↑
case "POST":
case "PUT":
return this == USER || this == ADMIN;
case "DELETE":
return this == ADMIN;
default:
return false;
}
}
}
class Main {
public static void main(String[] args) {
UserRole role = UserRole.RO;
if (role.isAccessAllowed("POST")) {
System.out.println("OK: "
+ role.getName());
} else {
System.out.println("Access denied: "
+ role.getName());
}
}
}
#[derive(PartialEq)]
enum UserRole {
RO,
USER,
ADMIN,
}
impl UserRole {
fn name(&self) -> &str {
match *self {
UserRole::RO => "read-only",
UserRole::USER => "user",
UserRole::ADMIN => "administrator",
}
}
fn is_access_allowed(
&self,
http_method: &str,
) -> bool {
match http_method {
"HEAD" | "GET" => true,
"POST" | "PUT" => {
*self == UserRole::USER
Rust
↑
|| *self == UserRole::ADMIN
}
"DELETE" => *self == UserRole::ADMIN,
_ => false,
}
}
}
fn main() {
let role = UserRole::RO;
if role.is_access_allowed("POST") {
println!("OK: {}", role.name());
} else {
println!("Access denied: {}", role.name());
}
}
Rustdoesnotsupportconstantsinenums,soweneedtouseamatchinthename method.Theenum
matchesarecheckedatcompiletime,sowhenallenumvariantsareused,thereisnoneedtohavea
defaultbranch.
Formoreinformationaboutthe#[derive(PartialEq)] line,seethesectionaboutAttributes
Associatedvalues
Rustenumsalsosupportassociatedvalues,whichmeanstheyarenotconstant,butinstead
allowthecreationofenumvariantinstanceswithspecificvalues.
sealed class GitCommand {
abstract fun execute()
}
object Status : GitCommand() {
override fun execute() =
executeCommand(listOf("status"))
}
class Checkout(
private val branch: String
) : GitCommand() {
override fun execute() =
executeCommand(listOf("checkout", branch))
}
class Add(
private val files: List<String>
) : GitCommand() {
override fun execute() =
executeCommand(listOf("add") + files)
}
Kotlin
↑
class Log(
private val decorate: Boolean,
private val patch: Boolean
) : GitCommand() {
override fun execute() {
val args = mutableListOf("log")
if (decorate) {
args.add("--decorate")
}
if (patch) {
args.add("--patch")
}
executeCommand(args)
}
}
fun executeCommand(args: List<String>) {
val redirect = ProcessBuilder.Redirect.INHERIT
ProcessBuilder(listOf("git") + args)
.redirectInput(redirect)
.redirectOutput(redirect)
.redirectError(redirect)
.start()
.waitFor()
}
object Main {
@JvmStatic
fun main(args: Array<String>) {
val command =
Log(decorate = false, patch = true)
command.execute()
}
}
use std::process::Command;
pub enum GitCommand<'g> {
STATUS,
CHECKOUT(&'g str),
ADD(Vec<&'g str>),
LOG { decorate: bool, patch: bool },
}
impl<'g> GitCommand<'g> {
fn execute(self) {
let args: Vec<&str> = match self {
GitCommand::STATUS => vec!["status"],
GitCommand::CHECKOUT(branch) => {
vec!["checkout", branch]
Rust
↑
}
GitCommand::ADD(files) => {
[vec!["add"], files].concat()
},
GitCommand::LOG {
decorate,
patch,
} => {
let mut args = vec!["log"];
if decorate {
args.push("--decorate")
}
if patch {
args.push("--patch")
}
args
}
};
execute_command("git", &args);
}
}
fn execute_command(command: &str, args: &[&str]) {
Command::new(command)
.args(args)
.spawn()
.expect("spawn failed!")
.wait()
.expect("command failed!");
}
fn main() {
let command = GitCommand::LOG {
decorate: false,
patch: true,
};
command.execute();
}
SealedClassesinKotlinaresimilartoRust’senums,astheyallowthemodellingofaclosedtypehierarchy
Seethissectionaboutenumsformoreexamples.
Concepts
Ownership
OnethingthatisveryspecialaboutRustisthewayithandlesmemoryallocations:Itdoesn’t
haveagarbagecollector(likeJavaScript,JavaorGo),butthedeveloperdoesnotneedto ↑
freememoryexplicitly,either(likeinC).Instead,Rustautomaticallyfreesmemorywhenitis
nolongerinuse.Forthismechanismtowork,thedeveloperneedstoexplicitlythinkabout
ownershipofthevaluestheprogramisusing.
class User {
private String name;
public User(String name) {
this.name = name;
}
}
public static void main(String[] args) {
String name = "User";
User user1 = new User(name);
User user2 = new User(name);
}
struct User {
name: String,
}
fn main() {
let name = String::from("User");
let user1 = User { name };
let user2 = User { name }; // compile error
}
InJava,thegarbagecollectorwillregularlychecktheobjectreferencesandwhennothingreferencesthe
Userinstancesanymore,theywillbedeleted.Oncebothinstanceshavebeendetectedasunused,the
"User" stringcanalsobedeleted.
InRust,valuescanonlybeownedbyoneobjectatatime:theassignmenttouser1 isOK,becausethe
valuewillbemovedfromthename variabletouser1.Thecreationofuser2,however,willgiveacompile
error,becausethestring"User" isnowownedbyuser1,notbyname.
InC,thedeveloperhastomakesurethatallocatedmemoryisfreedwhenitisnolonger
needed.Thiscanleadtobugs(memoryleaks)andwasoneofthemotivationforRust’s
differentapproachtomanagingmemory.WhileRustoffersprotectionsagainstit,it’snot
impossibletohavememoryleaks.
#include <string>
std::string* get_string() {
std::string* string = new std::string("hello");
delete string;
Java
Rust
C++
↑
return string;
}
fn get_string() -> String {
let string = String::from("hello");
drop(string);
return string; // compile error!
}
Inthisexample,theC++codehasauseafterfreeerror.Notethatthisisonlyanexample,dropisrarely
usedinRustcode(valueswillbedroppedautomaticallywhentheygooutofscope)
Rust’sownershipmodelalsohelpswhendealingwithmulti-threadedcode.Thecompiler
keepstrackofthevaluestheprogramisusingandmakessurethatthesamevalueisnot
accessedfrommultiplethreadswithoutproperlockinglogicaroundit.
#include <vector>
#include <thread>
int main() {
std::vector<std::string> list;
auto f = [&list]() {
for (int i = 0; i < 10000; i++) {
list.push_back("item 123");
}
};
std::thread t1(f);
std::thread t2(f);
t1.join();
t2.join();
}
use std::thread;
fn main() {
let mut list = vec![];
let f = move || {
for _ in 0..10000 {
list.push("item 123");
}
};
Rust
C++
Rust
↑
let t1 = thread::spawn(f);
let t2 = thread::spawn(f); // compile error!
t1.join().unwrap();
t2.join().unwrap();
}
Thestd::vector classisnotthread-safeandtheC++programwillcompilewithouterrors,butwhen
running,itwillprobablycrashwithanerrorlikepointer being freed was not allocated orsimilar.In
Rust,theclosuref takesownershipoflist (indicatedbythemovekeyword),that’swhythecompilergives
anerrorwhenf isusedmorethanonce.
Strings
Rusthasmultiplestringtypes,themostimportantonesarestr(usuallyintheformof &str)
andString.
The &str typeonlyreferencesborrowedcontent,sothisisthetypethatisusedforstatic
stringsandwhenreferencingstringslices.Likeotherimmutablereferences, &str values
cannotbemodified.Use String ifyouneedamodifiablestring.
const FILE_DATE = "2020-01-01";
function printCopyright() {
const year = FILE_DATE.substr(0, 4);
const copyright = `(C) ${year}`;
console.log(copyright);
}
const FILE_DATE: &str = "2020-01-01";
fn print_copyright() {
let year: &str = &FILE_DATE[..4];
let copyright: String = format!("(C) {}", year);
println!("{}", copyright);
}
Seethissectionaboutstringsformoreexamples
The String typeisusedfordynamicallycreatedstrings,whichcanbemodifiedandwhere
thelengthisnotfixedatcompiletime.
Usually, &str willbeusedforfunctionparametersand String willbeusedasreturnvalue.
public static String repeat(String s, int count) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < count; i++) {
result.append(s);
}
JavaScript
Rust
Java
↑
return result.toString();
}
fn repeat(s: &str, count: u32) -> String {
let mut result = String::new();
for _ in 0..count {
result += s;
}
result
}
Thisisjustanexample,RustalreadyhasString.repeat
Forstructfields,usually String shouldbeused,asthevaluewillprobablybeownedbythat
struct,especiallywhendealingwithlongerlivingobjects.
Forstringconstants, &'static str canbeusedforfieldsinstead.
data class User(
private val source: String,
private val name: String,
private val address: String
) {
companion object {
fun fromString(string: String): User {
val lines = string.lines()
return User("kotlin-v1.0", lines[0],
lines[1])
}
}
}
pub struct User {
source: &'static str,
name: String,
address: String,
}
impl User {
pub fn new(s: &str) -> User {
let mut lines = s.lines();
User {
source: "rust-v1.0",
name: lines.next().unwrap().to_owned(),
address: lines.next().unwrap().to_owned(),
}
}
}
Rust
Kotlin
Rust
↑
Notethatdefaultfieldaccessisprivate inRust
Toconvertavariable s1 oftype String to &str,use &s1.
Toconvertavariable s2 oftype &str to String,use s2.to_owned() (thisallocatesnew
memoryandcreatesacopyofthestring).Sometimesthisconversionisalsonecessaryfor
literals,like "string literal".to_owned().
Nullvalues
Rustdoesnothaveaspecial null value(alsocalled None or nil insomelanguages).
Instead,thereistheOptionenum,whichisverysimilartotheOptionaltypeinJava.
public static Integer getYear(String date) {
if (date.length() >= 4) {
String s = date.substring(0, 4);
try {
return Integer.valueOf(s);
} catch (NumberFormatException e) {
return null;
}
} else {
return null;
}
}
public static void main(String[] args) {
Integer year = getYear("2020-01-01");
if (year != null) {
System.out.println(year);
}
}
fn get_year(date: &str) -> Option<u32> {
if date.len() >= 4 {
let s = date[..4];
match s.parse() {
Ok(year) => Some(year),
Err(_) => None
}
} else {
None
}
}
fn main() {
if let Some(year) = get_year("2020-01-01") {
println!("{}", year);
Java
Rust
↑
}
}
TheOption typeisjustaregularenumfromRust’sstandardlibrary,withthetwoentriesNone andSome.
WhenreturningOption,empty(null)valuescanbereturnedasNone andnon-emptyvaluesneedtobe
wrapped,likeSome(year)
Tosimplycheckifavalueis null,withoutneedingtogettheactualvalue, is_none() can
beused.
Integer year = getYear("");
if (year == null) {
System.err.println("Invalid date given!");
}
let year: Option<u32> = get_year("");
if year.is_none() {
println!("Invalid date given!");
}
Sometimesit’susefultorunsomecodeonlyifavalueis null,toensureavariablehasa
non-null value.TherearemanywaystodoitinRust,butusing match offersthemost
concisesyntax.
String url = "https://github.com";
String content = cache.get(url);
if (content == null) {
content = loadUrl(url);
}
let url = "https://github.com";
let content = match cache.get(url) {
Some(content) => content,
None => load_url(url),
};
NotethatintheRustcode,content isimmutable(toachievethesameinJava,wewouldneedtointroduce
anotherlocalvariableoranewmethod)
Errorhandling
RustdoesnotofferexceptionslikeC++,JavaorJavaScript.Instead,errorconditionsare
indicatedviathemethod’sregularreturnvalue,likeinCorGo.
Java
Rust
Java
Rust
↑
package main
import (
"fmt"
"log"
"strconv"
)
func ParsePort(port string) (uint16, error) {
p, err := strconv.ParseUint(port, 10, 16)
if err != nil {
return 0, err
}
if p == 0 {
return 0, fmt.Errorf("invalid: %d", p)
}
return uint16(p), nil
}
func main() {
port, err := ParsePort("123")
if err != nil {
log.Fatalf("failed to parse port: %v", err)
}
log.Printf("port: %d", port)
}
use std::error::Error;
fn parse_port(s: &str) -> Result<u16, Box<Error>> {
let port: u16 = s.parse()?;
if port == 0 {
Err(Box::from(format!("invalid: {}", port)))
} else {
Ok(port)
}
}
fn main() {
match parse_port("123") {
Ok(port) => println!("port: {}", port),
Err(err) => panic!("{}", err),
}
}
InRustit’scommontohavestatementswhichcoverallpossiblecases,eitherusingif/else ormatch,so
youarelesslikelytoencounteranearlyreturn inRustthaninGo
Go
Rust
↑
Inthepreviousexample,weneededtouse Box<Error>,becausethereturnederrortype
cannotbedeterminedduringcompiletime:Itwilleithercontainaninstanceof
std::num::ParseIntError (fromtheparsemethod,whenparsingfails),orastring(when
theportiszero).
The ? intheline let port: u16 = s.parse()? isthe?operator:when parse returnedan
error, parse_port willreturnthaterror,otherwisetheunwrappedresultof parse willbe
assignedto port.
Input
Rustisoftenusedforterminalapplications,soitalsosupportsreadinginput.Therelevant
codeisinthestd::iomodule.
const { stdin } = require("process");
function readStr() {
return new Promise((resolve, reject) => {
let result = "";
stdin.setEncoding("utf8");
stdin.on("readable", () => {
let chunk;
while ((chunk = stdin.read())) {
result += chunk;
}
});
stdin.once("error", err => reject(err));
stdin.once("end", () => resolve(result));
});
}
use std::io::{stdin, Read};
fn read_str() -> Option<String> {
let mut buffer = String::new();
match stdin().read_to_string(&mut buffer) {
Ok(_) => Some(buffer),
Err(err) => {
eprintln!(
"Error while reading input: {}",
err
);
None
}
JavaScript
Rust
↑
};
}
NotethattheJavaScriptcodereturnsaPromise,soit’sasynchronous,whiletheRustexamplecodeis
synchronous
Attributes(annotations)
Rustalsosupportsattributes(alsocalledannotationsinotherlanguages).Theyare
interpretedduringcompiletimeandarecomparabletopreprocessormacrosinCorC++.
#include <cstdint>
[[nodiscard]] int32_t add(int32_t a, int32_t b) {
return a + b;
}
int main() {
add(1, 2); // warning: unused return value
}
#[must_use]
fn add(a: i32, b: i32) -> i32 {
a + b
}
fn main() {
add(1, 2); // warning: unused return value
}
Averycommonattributeisderive,whichcanbeusedtoquicklyimplementtraits.Itisoften
usedlike #[derive(Debug, PartialEq)],toimplementtheDebugandPartialEqtraits.
Miscellaneous
Packagemanagement
RustusuallyusestheCargopackagemanager,whichislikenpmoryarnforJavaScriptor
MavenforJava.
Thepackageregistryisavailableatcrates.io.
Projectsetup
IfyouhaveusedESLintbeforeforJavaScriptorTypeScript,rust-clippyisasimilartoolfor
Rust,whichdetectscommonmistakesandbugs.
C++
Rust
↑
Theequivalentforprettierorgofmtisrustfmt,whichautomaticallyformatscodebasedon
theofficialRuststyleguide.
Usefullinks
TheexcellentRustbook:https://doc.rust-lang.org/book/
RustbyExample:https://doc.rust-lang.org/rust-by-example/
TheRustCookbook:https://rust-lang-nursery.github.io/rust-cookbook
RustLanguageCheatSheet:https://cheats.rs/
RustREPL:https://crates.io/crates/runner
CommentsaboutRust:https://brson.github.io/fireflowers/
Thanksforreading!Ifyouhaveanyquestions,remarks,orjustwanttosaythanks,feelfree
tocontactmeonTwitter
Home Twitter GitHub KeyBase
↑

More Related Content

Similar to Rust for professionals.pdf

Testing for share
Testing for share Testing for share
Testing for share Rajeev Mehta
 
ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015Michiel Borkent
 
Introduction to Scalding and Monoids
Introduction to Scalding and MonoidsIntroduction to Scalding and Monoids
Introduction to Scalding and MonoidsHugo Gävert
 
Making JavaScript Libraries More Approachable
Making JavaScript Libraries More ApproachableMaking JavaScript Libraries More Approachable
Making JavaScript Libraries More ApproachablePamela Fox
 
Go 1.10 Release Party - PDX Go
Go 1.10 Release Party - PDX GoGo 1.10 Release Party - PDX Go
Go 1.10 Release Party - PDX GoRodolfo Carvalho
 
Rapid Development with Ruby/JRuby and Rails
Rapid Development with Ruby/JRuby and RailsRapid Development with Ruby/JRuby and Rails
Rapid Development with Ruby/JRuby and Railselliando dias
 
Big Data Scala by the Bay: Interactive Spark in your Browser
Big Data Scala by the Bay: Interactive Spark in your BrowserBig Data Scala by the Bay: Interactive Spark in your Browser
Big Data Scala by the Bay: Interactive Spark in your Browsergethue
 
C programming language tutorial
C programming language tutorial C programming language tutorial
C programming language tutorial javaTpoint s
 
Xdp and ebpf_maps
Xdp and ebpf_mapsXdp and ebpf_maps
Xdp and ebpf_mapslcplcp1
 
Scala presentation by Aleksandar Prokopec
Scala presentation by Aleksandar ProkopecScala presentation by Aleksandar Prokopec
Scala presentation by Aleksandar ProkopecLoïc Descotte
 
Opa presentation at GamesJs
Opa presentation at GamesJsOpa presentation at GamesJs
Opa presentation at GamesJsHenri Binsztok
 
A Sceptical Guide to Functional Programming
A Sceptical Guide to Functional ProgrammingA Sceptical Guide to Functional Programming
A Sceptical Guide to Functional ProgrammingGarth Gilmour
 
Let'swift "Concurrency in swift"
Let'swift "Concurrency in swift"Let'swift "Concurrency in swift"
Let'swift "Concurrency in swift"Hyuk Hur
 
Introduction To Groovy 2005
Introduction To Groovy 2005Introduction To Groovy 2005
Introduction To Groovy 2005Tugdual Grall
 
Lisp Macros in 20 Minutes (Featuring Clojure)
Lisp Macros in 20 Minutes (Featuring Clojure)Lisp Macros in 20 Minutes (Featuring Clojure)
Lisp Macros in 20 Minutes (Featuring Clojure)Phil Calçado
 

Similar to Rust for professionals.pdf (20)

Testing for share
Testing for share Testing for share
Testing for share
 
ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015
 
Introduction to Scalding and Monoids
Introduction to Scalding and MonoidsIntroduction to Scalding and Monoids
Introduction to Scalding and Monoids
 
Making JavaScript Libraries More Approachable
Making JavaScript Libraries More ApproachableMaking JavaScript Libraries More Approachable
Making JavaScript Libraries More Approachable
 
Pune Clojure Course Outline
Pune Clojure Course OutlinePune Clojure Course Outline
Pune Clojure Course Outline
 
Go 1.10 Release Party - PDX Go
Go 1.10 Release Party - PDX GoGo 1.10 Release Party - PDX Go
Go 1.10 Release Party - PDX Go
 
Rapid Development with Ruby/JRuby and Rails
Rapid Development with Ruby/JRuby and RailsRapid Development with Ruby/JRuby and Rails
Rapid Development with Ruby/JRuby and Rails
 
Full Stack Clojure
Full Stack ClojureFull Stack Clojure
Full Stack Clojure
 
Big Data Scala by the Bay: Interactive Spark in your Browser
Big Data Scala by the Bay: Interactive Spark in your BrowserBig Data Scala by the Bay: Interactive Spark in your Browser
Big Data Scala by the Bay: Interactive Spark in your Browser
 
JavaScript.pptx
JavaScript.pptxJavaScript.pptx
JavaScript.pptx
 
C programming language tutorial
C programming language tutorial C programming language tutorial
C programming language tutorial
 
Xdp and ebpf_maps
Xdp and ebpf_mapsXdp and ebpf_maps
Xdp and ebpf_maps
 
C# programming
C# programming C# programming
C# programming
 
Scala presentation by Aleksandar Prokopec
Scala presentation by Aleksandar ProkopecScala presentation by Aleksandar Prokopec
Scala presentation by Aleksandar Prokopec
 
Let's Go-lang
Let's Go-langLet's Go-lang
Let's Go-lang
 
Opa presentation at GamesJs
Opa presentation at GamesJsOpa presentation at GamesJs
Opa presentation at GamesJs
 
A Sceptical Guide to Functional Programming
A Sceptical Guide to Functional ProgrammingA Sceptical Guide to Functional Programming
A Sceptical Guide to Functional Programming
 
Let'swift "Concurrency in swift"
Let'swift "Concurrency in swift"Let'swift "Concurrency in swift"
Let'swift "Concurrency in swift"
 
Introduction To Groovy 2005
Introduction To Groovy 2005Introduction To Groovy 2005
Introduction To Groovy 2005
 
Lisp Macros in 20 Minutes (Featuring Clojure)
Lisp Macros in 20 Minutes (Featuring Clojure)Lisp Macros in 20 Minutes (Featuring Clojure)
Lisp Macros in 20 Minutes (Featuring Clojure)
 

More from ssuser16d801

刘煜辉:通缩已开始,经济已经落入衰退象限.pdf
刘煜辉:通缩已开始,经济已经落入衰退象限.pdf刘煜辉:通缩已开始,经济已经落入衰退象限.pdf
刘煜辉:通缩已开始,经济已经落入衰退象限.pdfssuser16d801
 
出国篇-关于日本养老的问题(为什么很多人会把日本作为养老的归宿)!.pdf
出国篇-关于日本养老的问题(为什么很多人会把日本作为养老的归宿)!.pdf出国篇-关于日本养老的问题(为什么很多人会把日本作为养老的归宿)!.pdf
出国篇-关于日本养老的问题(为什么很多人会把日本作为养老的归宿)!.pdfssuser16d801
 
欧美银行暴雷后,中国银行业并非理想避风港
欧美银行暴雷后,中国银行业并非理想避风港 欧美银行暴雷后,中国银行业并非理想避风港
欧美银行暴雷后,中国银行业并非理想避风港 ssuser16d801
 
检查你的事实并再试一次:利用外部知识和自动反馈改进大型语言模型 - 微软研究院.pdf
检查你的事实并再试一次:利用外部知识和自动反馈改进大型语言模型 - 微软研究院.pdf检查你的事实并再试一次:利用外部知识和自动反馈改进大型语言模型 - 微软研究院.pdf
检查你的事实并再试一次:利用外部知识和自动反馈改进大型语言模型 - 微软研究院.pdfssuser16d801
 
留给普通人的最后一扇门,快要关闭了 __ Reader View.pdf
留给普通人的最后一扇门,快要关闭了 __ Reader View.pdf留给普通人的最后一扇门,快要关闭了 __ Reader View.pdf
留给普通人的最后一扇门,快要关闭了 __ Reader View.pdfssuser16d801
 
uob-bank-fees-and-charges.pdf
uob-bank-fees-and-charges.pdfuob-bank-fees-and-charges.pdf
uob-bank-fees-and-charges.pdfssuser16d801
 
rust-annual-report-2022-cn.pdf
rust-annual-report-2022-cn.pdfrust-annual-report-2022-cn.pdf
rust-annual-report-2022-cn.pdfssuser16d801
 

More from ssuser16d801 (7)

刘煜辉:通缩已开始,经济已经落入衰退象限.pdf
刘煜辉:通缩已开始,经济已经落入衰退象限.pdf刘煜辉:通缩已开始,经济已经落入衰退象限.pdf
刘煜辉:通缩已开始,经济已经落入衰退象限.pdf
 
出国篇-关于日本养老的问题(为什么很多人会把日本作为养老的归宿)!.pdf
出国篇-关于日本养老的问题(为什么很多人会把日本作为养老的归宿)!.pdf出国篇-关于日本养老的问题(为什么很多人会把日本作为养老的归宿)!.pdf
出国篇-关于日本养老的问题(为什么很多人会把日本作为养老的归宿)!.pdf
 
欧美银行暴雷后,中国银行业并非理想避风港
欧美银行暴雷后,中国银行业并非理想避风港 欧美银行暴雷后,中国银行业并非理想避风港
欧美银行暴雷后,中国银行业并非理想避风港
 
检查你的事实并再试一次:利用外部知识和自动反馈改进大型语言模型 - 微软研究院.pdf
检查你的事实并再试一次:利用外部知识和自动反馈改进大型语言模型 - 微软研究院.pdf检查你的事实并再试一次:利用外部知识和自动反馈改进大型语言模型 - 微软研究院.pdf
检查你的事实并再试一次:利用外部知识和自动反馈改进大型语言模型 - 微软研究院.pdf
 
留给普通人的最后一扇门,快要关闭了 __ Reader View.pdf
留给普通人的最后一扇门,快要关闭了 __ Reader View.pdf留给普通人的最后一扇门,快要关闭了 __ Reader View.pdf
留给普通人的最后一扇门,快要关闭了 __ Reader View.pdf
 
uob-bank-fees-and-charges.pdf
uob-bank-fees-and-charges.pdfuob-bank-fees-and-charges.pdf
uob-bank-fees-and-charges.pdf
 
rust-annual-report-2022-cn.pdf
rust-annual-report-2022-cn.pdfrust-annual-report-2022-cn.pdf
rust-annual-report-2022-cn.pdf
 

Recently uploaded

EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesŁukasz Chruściel
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样umasea
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...Technogeeks
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfAlina Yurenko
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)OPEN KNOWLEDGE GmbH
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Velvetech LLC
 
Buds n Tech IT Solutions: Top-Notch Web Services in Noida
Buds n Tech IT Solutions: Top-Notch Web Services in NoidaBuds n Tech IT Solutions: Top-Notch Web Services in Noida
Buds n Tech IT Solutions: Top-Notch Web Services in Noidabntitsolutionsrishis
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmSujith Sukumaran
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...Christina Lin
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odishasmiwainfosol
 
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)jennyeacort
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackVICTOR MAESTRE RAMIREZ
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEEVICTOR MAESTRE RAMIREZ
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfStefano Stabellini
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作qr0udbr0
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureDinusha Kumarasiri
 

Recently uploaded (20)

EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New Features
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
 
2.pdf Ejercicios de programación competitiva
2.pdf Ejercicios de programación competitiva2.pdf Ejercicios de programación competitiva
2.pdf Ejercicios de programación competitiva
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...
 
Buds n Tech IT Solutions: Top-Notch Web Services in Noida
Buds n Tech IT Solutions: Top-Notch Web Services in NoidaBuds n Tech IT Solutions: Top-Notch Web Services in Noida
Buds n Tech IT Solutions: Top-Notch Web Services in Noida
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalm
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
 
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStack
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEE
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdf
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
 

Rust for professionals.pdf

  • 2. ThisisashortintroductiontoRust,intendedfordevelopersthatalreadyknowanother language.Intheexamples,RustiscomparedwithTypeScript,JavaScriptorJava,sometimes withC++orKotlin. ForadeepdiveintothesyntaxandRust’sconcepts,havealookatTheRustProgramming Language,butforaquickoverview,readon. Naming Regardingnames,Rustpreferssnakecaseforvariablesandfunctions,soamethodwould becalled read_str insteadof readStr.Forstructs,traitsandenums,camelcase(orPascal case)isused,forexample HttpClient. Syntax Rust’ssyntaxisamixofexistinglanguages(curlybraces,functionsandreferenceslikeinC, typeafteridentifierlikeinGoorKotlin,genericsandtypeparameterslikeinC++orJava) withsomeRust-specificelements(lifetimenames,patterns,macros,attributes).Foraquick overviewofthesyntax,seetheRustLanguageCheatSheetoranoverviewofRust’s keywords. Variables RustvariabledeclarationsareverysimilartoTypeScriptorKotlin,butlookabitdifferentfrom JavaorC. const s: string = ""; let n: number = 0.9; let i = 123; // Type inferred let s: &str = ""; let mut n: f64 = 0.9; let mut i = 123; // Type inferred Mostofthetime,thetypecanbeommittedinRustandthecompilerwillinferthecorrecttype Types InRust,therearemorespecificprimitivedatatypes. Thevoidtypeiscalledunitandisindicatedby (),seefunctionsforanexample. int i = 123; long l = 456L; float f = 0.5f; double d = 0.5; TypeScript Rust Java ↑
  • 3. String string = "Hello"; int[] arr = {1, 2, 3}; List<Integer> list = Arrays.asList(1, 2, 3); let i: i32 = 123; let l: i64 = 456; let f: f32 = 0.5; let d: f64 = 0.5f64; let string: &str = "Hello"; let arr: [i32; 3] = [1, 2, 3]; let list: Vec<i32> = vec![1, 2, 3]; InRust,numericliteralscanoptionallyhaveatypesuffix,forexample1000u32 or0.5f64. Mutability Variablesneedtobeexplicitlydeclaredmutable(let versus let mut),likeinJavaScript (const and let)orKotlin(val and var). ThemutabilitymodelinRustisnotlikeJavaScript,butabitmorelikeconstinC++,asRust willnotletyoucallmodifyingmethodsonavariablewhichisnotdeclaredasmutable. let arr1: string[] = []; arr1.push("123"); // OK arr1 = ["a", "b"]; // OK const arr2: string[] = []; arr2.push("123"); // OK, even though arr2 is const arr2 = []; // error, arr2 is const let mut arr1 = vec![]; arr1.push("123"); // OK arr1 = vec!["a", "b"]; // OK let arr2 = vec![]; arr2.push("123"); // error, arr2 is not mutable arr2 = vec![]; // error, arr2 is not mutable InTypeScript,declaringavariableasconst onlypreventsreassignment,notmodification.InRust,only variablesdeclaredasmut canbemodified Destructuring Rust TypeScript Rust ↑
  • 4. Rustsupportsdestructuring,likeJavaScriptorKotlin. function distance(a, b) { const { x: x1, y: y1 } = a; const { x: x2, y: y2 } = b; return Math.sqrt( Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2) ); } fn distance(a: &Point, b: &Point) -> f32 { let Point { x: x1, y: y1 } = a; let Point { x: x2, y: y2 } = b; ((x2 - x1).powf(2.0) + (y2 - y1).powf(2.0)).sqrt() } struct Point { x: f32, y: f32, } MoreexamplescanbefoundinthissectionfromtheRustforC++programmersguide Functions FunctionsarebasicallythesameasinC,Java,GoorTypeScript:Theyhaveaname,zeroor moreparametersandareturntype. void log(char* message) { printf("INFO %sn", message); } fn log(message: &str) -> () { println!("INFO {}", message); } Theunittype() (voidinsomelanguages)isthedefaultreturntypewhennotypeisgivenforafunction.It couldbeomittedinthisexample,likefn log(message: &str) { ... } InRust,functionsareexpressions,whichmeansthelaststatementisalsothereturnvalue (likeinRuby).Thisisabitlikeimplicitreturn,butnotexactly.Theofficialstyleistoonlyuse return forearlyreturns. public static int add(int a, int b) { return a + b; } JavaScript Rust C Rust Java ↑
  • 5. fn add(a: i32, b: i32) -> i32 { a + b } NotethatthereisnosemicolonintheRustfunction,otherwiseitwouldreturnvoid Rustcurrentlyhasnonamedargumentsordefaultarguments(likePythonandTypeScript) anddoesnotallowmethodoverloading(likeC++,JavaorTypeScript). Innerfunctions Rustalsosupportsinnerfunctions. const RE = /^[0-9]{4}-[0-9]{2}-[0-9]{2}$/; function isValidRange(start, end) { function isValid(date) { return date && date.match(RE); } return isValid(start) && isValid(end); } use regex::Regex; const RE: &str = r"^[0-9]{4}-[0-9]{2}-[0-9]{2}$"; fn is_valid_range(start: &str, end: &str) -> bool { fn is_valid(date: &str) -> bool { !date.is_empty() && Regex::new(RE) .unwrap() .is_match(date) } is_valid(start) && is_valid(end) } NotethatRegex isanexternalcrateandnotpartofRust’sstandardlibrary Extensionmethods Rust(likeKotlin)alsosupportsextensionmethods,sothepreviousexamplecouldbe rewrittenusingextensions. typealias Range = Pair<String, String> fun Range.isValid(): Boolean { val (start, end) = this Rust JavaScript Rust Kotlin ↑
  • 6. return start.isNotEmpty() && end.isNotEmpty() } object Main { @JvmStatic fun main(args: Array<String>) { val range = Range("2020-01-01", "2020-12-31") if (range.isValid()) { println("Range is valid!") } } } type Range<'r> = (&'r str, &'r str); trait IsValid { fn is_valid(&self) -> bool; } impl<'r> IsValid for Range<'r> { fn is_valid(&self) -> bool { let (start, end) = &self; !start.is_empty() && !end.is_empty() } } fn main() { let range = ("2020-01-01", "2020-12-31"); if range.is_valid() { println!("Range is valid!"); } } InRust,extensionmethodsareaddedbyimplementingatrait.Whenthereisonlyonemethod,it’scommon tonamethetraitlikethemethod(IsValid).The'r denotesalifetime,formoreinformation,seethis sectionfromtheRustbook Closures(lambdas) Rustsupportsclosures(alsocalledLambdas,arrowfunctionsoranonymousfunctionsin otherlanguages). Whenaccessingvariablesfromoutsidetheclosure,RustismorestrictthanJavaScriptor Java,seecapturingformoredetails. function findEmails(list) { return list.filter( s => s && s.includes("@") Rust JavaScript ↑
  • 7. ); } fn find_emails(list: Vec<String>) -> Vec<String> { list.into_iter() .filter(|s| s.contains("@")) .collect() } Formorefilterexamples,seethissectionfromthedocumentation Expressions InRust,almosteverythingisanexpression,likeinKotlinanddifferentfromJavaScriptor Java.Youcandirectlyassigntheresultofan if statementtoavariable,forexample. function getLogLevel() { let level = process.env.TRACE ? "trace" : process.env.DEBUG ? "debug" : "info"; level = level === "trace" ? 0 : level === "debug" ? 1 : 2; console.log("using log level", level); return level; } fn get_log_level() -> u32 { let level = if std::env::var("TRACE").is_ok() { "trace" } else if std::env::var("DEBUG").is_ok() { "debug" } else { "info" }; let level = match level { "trace" => 0, "debug" => 1, _ => 2, Rust JavaScript Rust ↑
  • 8. }; println!("using log level {}", level); level } TheRustcodeusesmatch,whichislikeswitch inJavaorJavaScriptexceptthatit’sanexpressionand providesmoreflexibility.Unlessmanyotherlanguages,Rustallowsvariableshadowingforlocalvariables (level inthisexample) Structs(classes) RustdoesnothavefullsupportforclasseslikeJavaorTypeScript,butinsteadoffersstructs (similartostructsinC).Thesearelikedatacontainerswithmethods,buttheydon’tsupport alloftheobjectorientedconcepts,likeinheritance. public class HttpClient { private final ClientImpl clientImpl; public HttpClient() { clientImpl = new ClientImpl(); } public String get(String url) { return clientImpl.newRequest() .get(url).asString(); } } public static void main(String[] args) { HttpClient httpClient = new HttpClient(); System.out.println(httpClient .get("https://example.com/")); } pub struct HttpClient { client_impl: ClientImpl, } impl HttpClient { pub fn new() -> HttpClient { HttpClient { client_impl: ClientImpl {}, } } pub fn get(&self, url: &str) -> String { self.client_impl.new_request() Java Rust ↑
  • 9. .get(url) .as_string() } } fn main() { let http_client = HttpClient::new(); println!("{}", http_client.get("https://example.com/")); } InJava,mutabilityisgivenonafieldlevel,hereclientImpl isimmutable.InRust,themutabilitymodifieris setontheinstancevariableandnotperfield,soyoucannothavemutableandimmutablefieldsinthe samestruct(seetheInteriorMutabilityPattern) Methodsdonothaveimplicitaccesstothis,asinJavaorJavaScript,soyouneedtopassan explicitargumentnamed self,likeinPython.Methodswithoutthisparameterarecalled associatedfunctions(theyarecalledstaticmethodsinsomelanguages). InRust,thereisnoconstructor,structsarecreatedsimilarlytoobjectsinJavaScript.For caseswhereconstructorlogicisrequired,thereisaconventiontocreateanassociated function(staticmethod)named new,whichwillreturntheconstructedobjectinstance. Traits(interfaces) ThemostsimilarthingtointerfacesinRustaretraits. interface Named { fun name(): String } data class User( val id: Int, val name: String ) : Named { override fun name(): String { return this.name } } pub trait Named { fn name(&self) -> &String; } pub struct User { pub id: i32, pub name: String, } Kotlin Rust ↑
  • 10. impl Named for User { fn name(&self) -> &String { return &self.name; } } Rustismostlyastaticlanguage,sosomethingsthatotherlanguagewilldoduringruntime, Rustwilldoduringcompiletime,whenpossible.Interfacesareusuallyusedfordynamic dispatchandifyouwanttousetraitsinasimilarway,seethischapteraboutstaticand dynamicdispatchandthisblogpost. Defaultmethods Traitsalsosupportdefaultmethods,likeinterfacesinJavaorKotlin. Associatedfunctions InRust,traitscanalsohaveassociatedfunctions,forexample from_str in std::str::FromStr (sectionstringparsingintheRustCookbook) interface FromList<T> { fun fromList(list: List<Int>): T? } data class MyPoint(val x: Int, val y: Int) { companion object : FromList<MyPoint> { override fun fromList(list: List<Int>): MyPoint? { return when (list.size) { 2 -> MyPoint(list[0], list[1]) else -> null } } } } object Main { @JvmStatic fun main(args: Array<String>) { val point = MyPoint.fromList(listOf(100, 200)) println(point) } } trait FromList<T> { fn from_list(list: &Vec<i32>) -> Option<T>; } struct MyPoint { Kotlin Rust ↑
  • 11. x: i32, y: i32, } impl FromList<Self> for MyPoint { fn from_list(list: &Vec<i32>) -> Option<Self> { match list.len() { 2 => Some(MyPoint { x: list[0], y: list[1], }), _ => None, } } } fn main() { let point = MyPoint::from_list(&vec![100, 200]).unwrap(); println!("({}, {})", point.x, point.y); } FormoreinformationabouttheOption type,seetheNullvaluessectionbelow.ThekeywordSelf (upper case)canbeusedtoreferencethecurrenttype Enums Rustsupportsenums,likeJavaorKotlin,butwithmoreflexibility.TheRustenumsoffermore thaninC++orTypeScript,astheyarenotmerelyalistofconstants,butmorelikeunions. enum UserRole { RO("read-only"), USER("user"), ADMIN("administrator"); private final String name; UserRole(String name) { this.name = name; } String getName() { return name; } boolean isAccessAllowed(String httpMethod) { switch (httpMethod) { case "HEAD": case "GET": return true; Java ↑
  • 12. case "POST": case "PUT": return this == USER || this == ADMIN; case "DELETE": return this == ADMIN; default: return false; } } } class Main { public static void main(String[] args) { UserRole role = UserRole.RO; if (role.isAccessAllowed("POST")) { System.out.println("OK: " + role.getName()); } else { System.out.println("Access denied: " + role.getName()); } } } #[derive(PartialEq)] enum UserRole { RO, USER, ADMIN, } impl UserRole { fn name(&self) -> &str { match *self { UserRole::RO => "read-only", UserRole::USER => "user", UserRole::ADMIN => "administrator", } } fn is_access_allowed( &self, http_method: &str, ) -> bool { match http_method { "HEAD" | "GET" => true, "POST" | "PUT" => { *self == UserRole::USER Rust ↑
  • 13. || *self == UserRole::ADMIN } "DELETE" => *self == UserRole::ADMIN, _ => false, } } } fn main() { let role = UserRole::RO; if role.is_access_allowed("POST") { println!("OK: {}", role.name()); } else { println!("Access denied: {}", role.name()); } } Rustdoesnotsupportconstantsinenums,soweneedtouseamatchinthename method.Theenum matchesarecheckedatcompiletime,sowhenallenumvariantsareused,thereisnoneedtohavea defaultbranch. Formoreinformationaboutthe#[derive(PartialEq)] line,seethesectionaboutAttributes Associatedvalues Rustenumsalsosupportassociatedvalues,whichmeanstheyarenotconstant,butinstead allowthecreationofenumvariantinstanceswithspecificvalues. sealed class GitCommand { abstract fun execute() } object Status : GitCommand() { override fun execute() = executeCommand(listOf("status")) } class Checkout( private val branch: String ) : GitCommand() { override fun execute() = executeCommand(listOf("checkout", branch)) } class Add( private val files: List<String> ) : GitCommand() { override fun execute() = executeCommand(listOf("add") + files) } Kotlin ↑
  • 14. class Log( private val decorate: Boolean, private val patch: Boolean ) : GitCommand() { override fun execute() { val args = mutableListOf("log") if (decorate) { args.add("--decorate") } if (patch) { args.add("--patch") } executeCommand(args) } } fun executeCommand(args: List<String>) { val redirect = ProcessBuilder.Redirect.INHERIT ProcessBuilder(listOf("git") + args) .redirectInput(redirect) .redirectOutput(redirect) .redirectError(redirect) .start() .waitFor() } object Main { @JvmStatic fun main(args: Array<String>) { val command = Log(decorate = false, patch = true) command.execute() } } use std::process::Command; pub enum GitCommand<'g> { STATUS, CHECKOUT(&'g str), ADD(Vec<&'g str>), LOG { decorate: bool, patch: bool }, } impl<'g> GitCommand<'g> { fn execute(self) { let args: Vec<&str> = match self { GitCommand::STATUS => vec!["status"], GitCommand::CHECKOUT(branch) => { vec!["checkout", branch] Rust ↑
  • 15. } GitCommand::ADD(files) => { [vec!["add"], files].concat() }, GitCommand::LOG { decorate, patch, } => { let mut args = vec!["log"]; if decorate { args.push("--decorate") } if patch { args.push("--patch") } args } }; execute_command("git", &args); } } fn execute_command(command: &str, args: &[&str]) { Command::new(command) .args(args) .spawn() .expect("spawn failed!") .wait() .expect("command failed!"); } fn main() { let command = GitCommand::LOG { decorate: false, patch: true, }; command.execute(); } SealedClassesinKotlinaresimilartoRust’senums,astheyallowthemodellingofaclosedtypehierarchy Seethissectionaboutenumsformoreexamples. Concepts Ownership OnethingthatisveryspecialaboutRustisthewayithandlesmemoryallocations:Itdoesn’t haveagarbagecollector(likeJavaScript,JavaorGo),butthedeveloperdoesnotneedto ↑
  • 16. freememoryexplicitly,either(likeinC).Instead,Rustautomaticallyfreesmemorywhenitis nolongerinuse.Forthismechanismtowork,thedeveloperneedstoexplicitlythinkabout ownershipofthevaluestheprogramisusing. class User { private String name; public User(String name) { this.name = name; } } public static void main(String[] args) { String name = "User"; User user1 = new User(name); User user2 = new User(name); } struct User { name: String, } fn main() { let name = String::from("User"); let user1 = User { name }; let user2 = User { name }; // compile error } InJava,thegarbagecollectorwillregularlychecktheobjectreferencesandwhennothingreferencesthe Userinstancesanymore,theywillbedeleted.Oncebothinstanceshavebeendetectedasunused,the "User" stringcanalsobedeleted. InRust,valuescanonlybeownedbyoneobjectatatime:theassignmenttouser1 isOK,becausethe valuewillbemovedfromthename variabletouser1.Thecreationofuser2,however,willgiveacompile error,becausethestring"User" isnowownedbyuser1,notbyname. InC,thedeveloperhastomakesurethatallocatedmemoryisfreedwhenitisnolonger needed.Thiscanleadtobugs(memoryleaks)andwasoneofthemotivationforRust’s differentapproachtomanagingmemory.WhileRustoffersprotectionsagainstit,it’snot impossibletohavememoryleaks. #include <string> std::string* get_string() { std::string* string = new std::string("hello"); delete string; Java Rust C++ ↑
  • 17. return string; } fn get_string() -> String { let string = String::from("hello"); drop(string); return string; // compile error! } Inthisexample,theC++codehasauseafterfreeerror.Notethatthisisonlyanexample,dropisrarely usedinRustcode(valueswillbedroppedautomaticallywhentheygooutofscope) Rust’sownershipmodelalsohelpswhendealingwithmulti-threadedcode.Thecompiler keepstrackofthevaluestheprogramisusingandmakessurethatthesamevalueisnot accessedfrommultiplethreadswithoutproperlockinglogicaroundit. #include <vector> #include <thread> int main() { std::vector<std::string> list; auto f = [&list]() { for (int i = 0; i < 10000; i++) { list.push_back("item 123"); } }; std::thread t1(f); std::thread t2(f); t1.join(); t2.join(); } use std::thread; fn main() { let mut list = vec![]; let f = move || { for _ in 0..10000 { list.push("item 123"); } }; Rust C++ Rust ↑
  • 18. let t1 = thread::spawn(f); let t2 = thread::spawn(f); // compile error! t1.join().unwrap(); t2.join().unwrap(); } Thestd::vector classisnotthread-safeandtheC++programwillcompilewithouterrors,butwhen running,itwillprobablycrashwithanerrorlikepointer being freed was not allocated orsimilar.In Rust,theclosuref takesownershipoflist (indicatedbythemovekeyword),that’swhythecompilergives anerrorwhenf isusedmorethanonce. Strings Rusthasmultiplestringtypes,themostimportantonesarestr(usuallyintheformof &str) andString. The &str typeonlyreferencesborrowedcontent,sothisisthetypethatisusedforstatic stringsandwhenreferencingstringslices.Likeotherimmutablereferences, &str values cannotbemodified.Use String ifyouneedamodifiablestring. const FILE_DATE = "2020-01-01"; function printCopyright() { const year = FILE_DATE.substr(0, 4); const copyright = `(C) ${year}`; console.log(copyright); } const FILE_DATE: &str = "2020-01-01"; fn print_copyright() { let year: &str = &FILE_DATE[..4]; let copyright: String = format!("(C) {}", year); println!("{}", copyright); } Seethissectionaboutstringsformoreexamples The String typeisusedfordynamicallycreatedstrings,whichcanbemodifiedandwhere thelengthisnotfixedatcompiletime. Usually, &str willbeusedforfunctionparametersand String willbeusedasreturnvalue. public static String repeat(String s, int count) { StringBuilder result = new StringBuilder(); for (int i = 0; i < count; i++) { result.append(s); } JavaScript Rust Java ↑
  • 19. return result.toString(); } fn repeat(s: &str, count: u32) -> String { let mut result = String::new(); for _ in 0..count { result += s; } result } Thisisjustanexample,RustalreadyhasString.repeat Forstructfields,usually String shouldbeused,asthevaluewillprobablybeownedbythat struct,especiallywhendealingwithlongerlivingobjects. Forstringconstants, &'static str canbeusedforfieldsinstead. data class User( private val source: String, private val name: String, private val address: String ) { companion object { fun fromString(string: String): User { val lines = string.lines() return User("kotlin-v1.0", lines[0], lines[1]) } } } pub struct User { source: &'static str, name: String, address: String, } impl User { pub fn new(s: &str) -> User { let mut lines = s.lines(); User { source: "rust-v1.0", name: lines.next().unwrap().to_owned(), address: lines.next().unwrap().to_owned(), } } } Rust Kotlin Rust ↑
  • 20. Notethatdefaultfieldaccessisprivate inRust Toconvertavariable s1 oftype String to &str,use &s1. Toconvertavariable s2 oftype &str to String,use s2.to_owned() (thisallocatesnew memoryandcreatesacopyofthestring).Sometimesthisconversionisalsonecessaryfor literals,like "string literal".to_owned(). Nullvalues Rustdoesnothaveaspecial null value(alsocalled None or nil insomelanguages). Instead,thereistheOptionenum,whichisverysimilartotheOptionaltypeinJava. public static Integer getYear(String date) { if (date.length() >= 4) { String s = date.substring(0, 4); try { return Integer.valueOf(s); } catch (NumberFormatException e) { return null; } } else { return null; } } public static void main(String[] args) { Integer year = getYear("2020-01-01"); if (year != null) { System.out.println(year); } } fn get_year(date: &str) -> Option<u32> { if date.len() >= 4 { let s = date[..4]; match s.parse() { Ok(year) => Some(year), Err(_) => None } } else { None } } fn main() { if let Some(year) = get_year("2020-01-01") { println!("{}", year); Java Rust ↑
  • 21. } } TheOption typeisjustaregularenumfromRust’sstandardlibrary,withthetwoentriesNone andSome. WhenreturningOption,empty(null)valuescanbereturnedasNone andnon-emptyvaluesneedtobe wrapped,likeSome(year) Tosimplycheckifavalueis null,withoutneedingtogettheactualvalue, is_none() can beused. Integer year = getYear(""); if (year == null) { System.err.println("Invalid date given!"); } let year: Option<u32> = get_year(""); if year.is_none() { println!("Invalid date given!"); } Sometimesit’susefultorunsomecodeonlyifavalueis null,toensureavariablehasa non-null value.TherearemanywaystodoitinRust,butusing match offersthemost concisesyntax. String url = "https://github.com"; String content = cache.get(url); if (content == null) { content = loadUrl(url); } let url = "https://github.com"; let content = match cache.get(url) { Some(content) => content, None => load_url(url), }; NotethatintheRustcode,content isimmutable(toachievethesameinJava,wewouldneedtointroduce anotherlocalvariableoranewmethod) Errorhandling RustdoesnotofferexceptionslikeC++,JavaorJavaScript.Instead,errorconditionsare indicatedviathemethod’sregularreturnvalue,likeinCorGo. Java Rust Java Rust ↑
  • 22. package main import ( "fmt" "log" "strconv" ) func ParsePort(port string) (uint16, error) { p, err := strconv.ParseUint(port, 10, 16) if err != nil { return 0, err } if p == 0 { return 0, fmt.Errorf("invalid: %d", p) } return uint16(p), nil } func main() { port, err := ParsePort("123") if err != nil { log.Fatalf("failed to parse port: %v", err) } log.Printf("port: %d", port) } use std::error::Error; fn parse_port(s: &str) -> Result<u16, Box<Error>> { let port: u16 = s.parse()?; if port == 0 { Err(Box::from(format!("invalid: {}", port))) } else { Ok(port) } } fn main() { match parse_port("123") { Ok(port) => println!("port: {}", port), Err(err) => panic!("{}", err), } } InRustit’scommontohavestatementswhichcoverallpossiblecases,eitherusingif/else ormatch,so youarelesslikelytoencounteranearlyreturn inRustthaninGo Go Rust ↑
  • 23. Inthepreviousexample,weneededtouse Box<Error>,becausethereturnederrortype cannotbedeterminedduringcompiletime:Itwilleithercontainaninstanceof std::num::ParseIntError (fromtheparsemethod,whenparsingfails),orastring(when theportiszero). The ? intheline let port: u16 = s.parse()? isthe?operator:when parse returnedan error, parse_port willreturnthaterror,otherwisetheunwrappedresultof parse willbe assignedto port. Input Rustisoftenusedforterminalapplications,soitalsosupportsreadinginput.Therelevant codeisinthestd::iomodule. const { stdin } = require("process"); function readStr() { return new Promise((resolve, reject) => { let result = ""; stdin.setEncoding("utf8"); stdin.on("readable", () => { let chunk; while ((chunk = stdin.read())) { result += chunk; } }); stdin.once("error", err => reject(err)); stdin.once("end", () => resolve(result)); }); } use std::io::{stdin, Read}; fn read_str() -> Option<String> { let mut buffer = String::new(); match stdin().read_to_string(&mut buffer) { Ok(_) => Some(buffer), Err(err) => { eprintln!( "Error while reading input: {}", err ); None } JavaScript Rust ↑
  • 24. }; } NotethattheJavaScriptcodereturnsaPromise,soit’sasynchronous,whiletheRustexamplecodeis synchronous Attributes(annotations) Rustalsosupportsattributes(alsocalledannotationsinotherlanguages).Theyare interpretedduringcompiletimeandarecomparabletopreprocessormacrosinCorC++. #include <cstdint> [[nodiscard]] int32_t add(int32_t a, int32_t b) { return a + b; } int main() { add(1, 2); // warning: unused return value } #[must_use] fn add(a: i32, b: i32) -> i32 { a + b } fn main() { add(1, 2); // warning: unused return value } Averycommonattributeisderive,whichcanbeusedtoquicklyimplementtraits.Itisoften usedlike #[derive(Debug, PartialEq)],toimplementtheDebugandPartialEqtraits. Miscellaneous Packagemanagement RustusuallyusestheCargopackagemanager,whichislikenpmoryarnforJavaScriptor MavenforJava. Thepackageregistryisavailableatcrates.io. Projectsetup IfyouhaveusedESLintbeforeforJavaScriptorTypeScript,rust-clippyisasimilartoolfor Rust,whichdetectscommonmistakesandbugs. C++ Rust ↑