Obsah
1. Základní a alternativní formátování celočíselných hodnot
3. Zarovnání hodnot: doleva, doprava, vycentrování
4. Výplň místa specifikovaným znakem
5. Vytištění znaménka a tisk počátečních nul
6. Nastavení přesnosti výpisu hodnot s plovoucí řádovou čárkou
7. Řízení šířky a přesnosti s využitím nepovinných argumentů
8. Celočíselné primitivní datové typy – základní funkce a metody
9. Prohození bajtů ve slovech, konverze mezi little a big endian
10. Bitové rotace a posuny celočíselných hodnot
11. Zjištění atributů hodnot s plovoucí řádovou čárkou
12. Proměnné prostředí vyhodnocované v době překladu
13. Proměnné prostředí vyhodnocované při běhu aplikace
14. Přečtení argumentů předaných na příkazové řádce
15. Repositář s demonstračními příklady
1. Základní formátování celočíselných hodnot
V programovacím jazyku Rust mají vývojáři k dispozici velmi užitečné makro nazvané format!, které je možné použít pro převod prakticky libovolných hodnot na řetězec s možností specifikace způsobu formátování. Toto makro lze použít buď přímo nebo nepřímo v dalším makru pojmenovaném println!, které již důvěrně známe z předchozích částí tohoto seriálu. Toto makro používá stejný způsob zápisu formátovacího řetězce, pouze se po výpisu výsledného textu na standardní výstup navíc provede přidání znaku pro konec řádku (provede se odřádkování).
Formátovací řetězec se zapisuje způsobem, který se poněkud odlišuje od céčkovské funkce printf. Nejprve si ukažme, jakým způsobem je možné zvolit základ číselné soustavy při převodu celého čísla (se znaménkem či bez znaménka) na řetězec. Ve výchozím nastavení se použije desítková soustava, lze však zvolit i soustavu osmičkovou, hexadecimální (s malými či velkými písmeny pro cifry A až F) a nově taktéž soustavu binární. Každému číslu, které se má objevit ve výstupním řetězci/formátované zprávě, odpovídá obsah jedné dvojice složených závorek {} (pokud jsou závorky prázdné, odpovídá to výchozímu formátování a použití desítkové soustavy):
fn main() { let value = 42; println!("{}", value); println!("0{:o}", value); println!("0x{:x}", value); println!("0x{:X}", value); println!("0b{:b}", value); }
Zpráva vypsaná po překladu a spuštění příkladu:
42 052 0x2a 0x2A 0b101010
Existuje i alternativní forma výpisu, v níž se do výsledného řetězce automaticky přidají i prefixy číselné soustavy (0o, 0×, 0b). Alternativní forma vyžaduje použití znaku # před specifikací číselné soustavy:
fn main() { let value = 42; println!("{}", value); println!("{:#o}", value); println!("{:#x}", value); println!("{:#X}", value); println!("{:#b}", value); }
Zpráva vypsaná po překladu a spuštění příkladu:
42 0o52 0x2a 0x2A 0b101010
2. Šířka vypisovaných hodnot
Specifikovat je samozřejmě možné i šířku vypisovaných hodnot, ovšem s tím, že pokud je nutné hodnotu reprezentovat větším počtem znaků, než je zadaná šířka, bude se šířka ignorovat; viz druhý řádek (znak roury je zde použit jen pro vizuální zvýraznění šířky řetězce a nemá zde žádný specifický význam):
fn main() { let value = 42; println!("|{}|", value); println!("|{:1}|", value); println!("|{:10}|", value); println!("|{:20}|", value); }
Zpráva vypsaná po překladu a spuštění příkladu:
|42| |42| | 42| | 42|
Šířku lze samozřejmě kombinovat se specifikací základu číselné soustavy, a to takto:
fn main() { let value = 42; println!("|{}|", value); println!("|{:1b}|", value); println!("|{:10b}|", value); println!("|{:20b}|", value); }
Zpráva vypsaná po překladu a spuštění příkladu:
|42| |101010| | 101010| | 101010|
Makrem println! je samozřejmě možné naformátovat a vypsat více hodnot:
fn main() { let value1 = 42; let value2 = 8080; println!("|{:10}|{:10}|", value1, value2); }
Zpráva vypsaná po překladu a spuštění příkladu:
| 42| 8080|
3. Zarovnání hodnot: doleva, doprava, vycentrování
V případě, že je hodnota naformátována na menší počet znaků, než by odpovídalo specifikaci šířky, lze zvolit způsob zarovnání. Podporováno je zarovnání doprava (znak >), doleva (znak <) a na střed (znak ^), samozřejmě s tím, že zarovnání na střed nemusí být přesné (lichý počet znaků versus sudá hodnota zarovnání a naopak):
fn main() { let value = 42; println!("|{}|", value); println!("|{:20}|", value); println!("|{:>20}|", value); println!("|{:<20}|", value); println!("|{:^20}|", value); }
Zpráva vypsaná po překladu a spuštění příkladu:
|42| | 42| | 42| |42 | | 42 |
Povšimněte si, že výchozí zarovnání numerických hodnot je doprava (druhý zvýrazněný řádek výpisu). Zkusme si však příklad upravit tak, že se namísto celočíselné hodnoty bude formátovat řetězec:
fn main() { let str = "hello"; println!("|{}|", str); println!("|{:20}|", str); println!("|{:>20}|", str); println!("|{:<20}|", str); println!("|{:^20}|", str); }
Na druhém řádku je patrné, že implicitní zarovnání řetězců je na levý okraj:
|hello| |hello | | hello| |hello | | hello |
Explicitní určení zarovnání samozřejmě funguje stejně v obou případech, viz poslední tři řádky výpisu.
4. Výplň místa specifikovaným znakem
V některých případech může být užitečné použít při formátování výstupu namísto mezer odlišné znaky. I tato možnost je v programovacím jazyku Rust podporována, což je patrné z následujícího příkladu, v němž u numerických hodnot používáme pro výplň tečky a u řetězců podtržítka:
fn main() { let value = 42; println!("|{}|", value); println!("|{:10}|", value); println!("|{:.>10}|", value); println!("|{:.<10}|", value); println!("|{:.^10}|", value); println!("") let str = "hello"; println!("|{}|", str); println!("|{:20}|", str); println!("|{:_>20}|", str); println!("|{:_<20}|", str); println!("|{:_^20}|", str); }
Zpráva vypsaná po překladu a spuštění příkladu:
|42| | 42| |........42| |42........| |....42....| |hello| |hello | |_______________hello| |hello_______________| |_______hello________|
Další způsob použití:
fn main() { for i in 0..16 { println!("|{:.>10}|", 1 << i); } }
Zpráva vypsaná po překladu a spuštění příkladu:
|.........1| |.........2| |.........4| |.........8| |........16| |........32| |........64| |.......128| |.......256| |.......512| |......1024| |......2048| |......4096| |......8192| |.....16384| |.....32768|
5. Vytištění znaménka a tisk počátečních nul
Makra format! a println! rozeznávají ve formátovacím řetězci i znak +, kterým se vyžaduje explicitní výpis znaménka celočíselné hodnoty, a to i ve chvíli, kdy je hodnota kladná. Znak – je taktéž možné použít, ale prozatím se ignoruje, tj. nemá žádný speciální význam (na rozdíl od printf v céčku). Použití znaků + a – je jednoduché:
fn main() { let value1 = 42; let value2 = -42; println!("|{}|", value1); println!("|{:-10}|", value1); println!("|{:+10}|", value1); println!("|{}|", value2); println!("|{:-10}|", value2); println!("|{:+10}|", value2); }
Zpráva vypsaná po překladu a spuštění příkladu:
|42| | 42| | +42| |-42| | -42| | -42|
Pokud je nutné do výpisu naformátovaných celočíselných hodnot doplnit nuly (ty nemění význam vypsané hodnoty), není nic jednoduššího než použít znak 0 před uvedením požadované šířky výpisu:
fn main() { let value1 = 42; let value2 = -42; println!("|{:-010}|", value1); println!("|{:+010}|", value1); println!("|{:-010}|", value2); println!("|{:+010}|", value2); }
Zpráva vypsaná po překladu a spuštění příkladu:
|0000000042| |+000000042| |-000000042| |-000000042|
Totéž platí i pro další základy číselných soustav:
fn main() { for i in 0..16 { println!("{:08b}", i); } }
Zpráva vypsaná po překladu a spuštění příkladu:
00000000 00000001 00000010 00000011 00000100 00000101 00000110 00000111 00001000 00001001 00001010 00001011 00001100 00001101 00001110 00001111
6. Nastavení přesnosti výpisu hodnot s plovoucí řádovou čárkou
U hodnot s plovoucí řádovou čárkou je možné explicitně zvolit počet číslic za čárkou/tečkou, a to způsobem, který se používal již v céčku, tj. uvede se celková šířka čísla ve znacích a za tečkou pak počet desetinných míst. Opět je možná kombinace se specifikací zarovnání:
fn main() { let value = 42.5; println!("{}", value); println!("{:10}", value); println!("{:10.4}", value); println!("{:+10}", value); println!("{:+10.4}", value); println!("{:^+10}", value); println!("{:^+10.4}", value); }
Zpráva vypsaná po překladu a spuštění příkladu:
42.5 42.5 42.5000 +42.5 +42.5000 +42.5 +42.5000
7. Řízení šířky a přesnosti s využitím nepovinných argumentů
Požadovaná šířka ve formátovacím řetězci se alternativně zadává i specifikací jména nepovinného parametru makra format! a println!. V následujícím příkladu je za znakem : namísto číselné hodnoty šířky specifikováno jméno width (ukončené dolarem), které musí odpovídat pojmenovanému parametru. Pokud je nutné použít zarovnání, zapíše se znak pro zarovnání před jméno parametru:
fn main() { let value = 42.5; for i in 1..20 { println!("|{:width$}|", value, width=i); } for i in 1..20 { println!("|{:^width$}|", value, width=i); } }
Zpráva vypsaná po překladu a spuštění příkladu:
|42.5| |42.5| |42.5| |42.5| | 42.5| | 42.5| | 42.5| | 42.5| | 42.5| | 42.5| | 42.5| | 42.5| | 42.5| | 42.5| | 42.5| | 42.5| | 42.5| | 42.5| | 42.5| |42.5| |42.5| |42.5| |42.5| |42.5 | | 42.5 | | 42.5 | | 42.5 | | 42.5 | | 42.5 | | 42.5 | | 42.5 | | 42.5 | | 42.5 | | 42.5 | | 42.5 | | 42.5 | | 42.5 | | 42.5 |
Zkusme si vytvořit složitější příklad, v němž se mění jak šířka výsledného čísla v řetězci, tak i počet desetinných míst. Povšimněte si, že ve formátovacím řetězci se jména nepovinných parametrů vždy ukončují znakem dolaru:
fn main() { let value = 0.5; for w in 1 .. 11 { println!("width={}", w); for p in 1 .. (w-1) { println!("|{:width$.precision$}|", value, width=w, precision=p); } println!(""); } }
Zpráva vypsaná po překladu a spuštění příkladu:
width=1 width=2 width=3 |0.5| width=4 | 0.5| |0.50| width=5 | 0.5| | 0.50| |0.500| width=6 | 0.5| | 0.50| | 0.500| |0.5000| width=7 | 0.5| | 0.50| | 0.500| | 0.5000| |0.50000| width=8 | 0.5| | 0.50| | 0.500| | 0.5000| | 0.50000| |0.500000| width=9 | 0.5| | 0.50| | 0.500| | 0.5000| | 0.50000| | 0.500000| |0.5000000| width=10 | 0.5| | 0.50| | 0.500| | 0.5000| | 0.50000| | 0.500000| | 0.5000000| |0.50000000|
8. Celočíselné primitivní datové typy – základní funkce a metody
Další oblastí, kterou se dnes budeme zabývat, jsou metody dostupné pro vybrané primitivní datové typy. Začneme celočíselnými hodnotami, pro něž existují metody nazvané min_value() a max_value() vracející minimální a maximální hodnotu reprezentovatelnou daným celočíselným datovým typem. V následujícím příkladu se minimální a maximální hodnoty vypíšou pro všech osm celočíselných typů:
fn main() { println!("Type: {:>22} {:>22} {:>22} {:>22} {:>22} {:>22} {:>22} {:>22}", "i8", "i16", "i32", "i64", "u8", "u16", "u32", "u64"); println!("min_value: {:>22} {:>22} {:>22} {:>22} {:>22} {:>22} {:>22} {:>22}", i8::min_value(), i16::min_value(), i32::min_value(), i64::min_value(), u8::min_value(), u16::min_value(), u32::min_value(), u64::min_value()); println!("max_value: {:>22} {:>22} {:>22} {:>22} {:>22} {:>22} {:>22} {:>22}", i8::max_value(), i16::max_value(), i32::max_value(), i64::max_value(), u8::max_value(), u16::max_value(), u32::max_value(), u64::max_value()); }
Vypsaná tabulka odpovídá předpokládanému výsledku:
Type: i8 i16 i32 i64 u8 u16 u32 u64 min_value: -128 -32768 -2147483648 -9223372036854775808 0 0 0 0 max_value: 127 32767 2147483647 9223372036854775807 255 65535 4294967295 18446744073709551615
(některé sloupce jsou pro přehlednost zmenšeny)
9. Prohození bajtů ve slovech, konverze mezi little a big endian
Mezi další užitečné metody u primitivních datových typů patří metoda swap_bytes() sloužící pro prohození všech bajtů ve slově (kromě u8 a i8) a dále metody from_le(), from_be(), to_le() a to_be(), které lze použít pro konverzi mezi nativní reprezentací čísla a formátem little endian a big endiann. Podle použité platformy mohou dvě z těchto funkcí vracet původní hodnotu. Příkladem může být platforma i386, u níž funkce from_le() vrátí původní číslo. Ostatně můžeme si to vyzkoušet:
fn main() { let value:u32 = 0xcafebabe; println!("{:x}", value); println!("{:x}", value.swap_bytes()); println!("{:x}", u32::from_le(value)); println!("{:x}", u32::from_be(value)); }
Na platformě i386 či x86–64 by se mělo vypsat:
cafebabe bebafeca cafebabe bebafeca
10. Bitové rotace a posuny celočíselných hodnot
Zatímco bitové posuny jsou podporovány samotným jazykem díky operátorům << a >>, bitové rotace je nutné provést metodami nazvanými rotate_left() a rotate_right(). Pro lepší ilustraci budeme původní hodnotu, posunutou hodnotu i zrotovanou hodnotu vypisovat s formátováním 032b, tedy 32 bitů zarovnaných zleva nulami:
fn main() { let value:u32 = 3; println!("{:032b}", value); println!(""); for rot in 0..10 { println!("{:032b}", value.rotate_left(rot)); } println!(""); for rot in 0..10 { println!("{:032b}", value.rotate_right(rot)); } println!(""); for rot in 0..10 { println!("{:032b}", value << rot); } println!(""); for rot in 0..10 { println!("{:032b}", value >> rot); } }
Zpráva vypsaná po překladu a spuštění příkladu:
00000000000000000000000000000011 00000000000000000000000000000011 00000000000000000000000000000110 00000000000000000000000000001100 00000000000000000000000000011000 00000000000000000000000000110000 00000000000000000000000001100000 00000000000000000000000011000000 00000000000000000000000110000000 00000000000000000000001100000000 00000000000000000000011000000000 00000000000000000000000000000011 10000000000000000000000000000001 11000000000000000000000000000000 01100000000000000000000000000000 00110000000000000000000000000000 00011000000000000000000000000000 00001100000000000000000000000000 00000110000000000000000000000000 00000011000000000000000000000000 00000001100000000000000000000000 00000000000000000000000000000011 00000000000000000000000000000110 00000000000000000000000000001100 00000000000000000000000000011000 00000000000000000000000000110000 00000000000000000000000001100000 00000000000000000000000011000000 00000000000000000000000110000000 00000000000000000000001100000000 00000000000000000000011000000000 00000000000000000000000000000011 00000000000000000000000000000001 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000
11. Zjištění atributů hodnot s plovoucí řádovou čárkou
Mnoho potenciálně důležitých informací je možné získat i pro primitivní datové typy s plovoucí řádovou čárkou, konkrétně pro typy „f32“ a „f64“. Především jsou dostupné informace o maximální hodnotě (která ještě není považována za nekonečno), o minimální hodnotě, o nejmenší kladné nenulové hodnotě a taktéž o způsobu reprezentace čísla (počet číslic, počet bitů pro uložení mantisy, největší a nejmenší exponent při dvojkovém i desítkovém vyjádření, radix atd.). Nesmíme zapomenout ani na speciální hodnoty: kladné a záporné nekonečno a NaN:
use std::f32; fn main() { println!("Max {}", f32::MAX); println!("Min {}", f32::MIN); println!("Min pos {}", f32::MIN_POSITIVE); println!(""); println!("+Infinity {}", f32::INFINITY); println!("-Infinity {}", f32::NEG_INFINITY); println!("NaN {}", f32::NAN); println!(""); println!("Digits {}", f32::DIGITS); println!("Max exponent 10^{}", f32::MAX_10_EXP); println!("Min exponent 10^{}", f32::MIN_10_EXP); println!("Epsilon {}", f32::EPSILON); println!(""); println!("Radix {}", f32::RADIX); println!("Digits {}", f32::MANTISSA_DIGITS); println!("Max exponent 2^{}", f32::MAX_EXP); println!("Min exponent 2^{}", f32::MIN_EXP); }
Zpráva vypsaná po překladu a spuštění příkladu:
Max 340282350000000000000000000000000000000 Min -340282350000000000000000000000000000000 Min pos 0.000000000000000000000000000000000000011754944 +Infinity inf -Infinity -inf NaN NaN Digits 6 Max exponent 10^38 Min exponent 10^-37 Epsilon 0.00000011920929 Radix 2 Digits 24 Max exponent 2^128 Min exponent 2^-125
Stejný příklad lze upravit pro typ „f64“:
use std::f64; fn main() { println!("Max {}", f64::MAX); println!("Min {}", f64::MIN); println!("Min pos {}", f64::MIN_POSITIVE); println!(""); println!("+Infinity {}", f64::INFINITY); println!("-Infinity {}", f64::NEG_INFINITY); println!("NaN {}", f64::NAN); println!(""); println!("Digits {}", f64::DIGITS); println!("Max exponent 10^{}", f64::MAX_10_EXP); println!("Min exponent 10^{}", f64::MIN_10_EXP); println!("Epsilon {}", f64::EPSILON); println!(""); println!("Radix {}", f64::RADIX); println!("Digits {}", f64::MANTISSA_DIGITS); println!("Max exponent 2^{}", f64::MAX_EXP); println!("Min exponent 2^{}", f64::MIN_EXP); }
Zpráva vypsaná po překladu a spuštění příkladu:
Max 179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 Min -179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 Min pos 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022250738585072014 +Infinity inf -Infinity -inf NaN NaN Digits 15 Max exponent 10^308 Min exponent 10^-307 Epsilon 0.0000000000000002220446049250313 Radix 2 Digits 53 Max exponent 2^1024 Min exponent 2^-1021
12. Proměnné prostředí vyhodnocované v době překladu
V době překladu lze přistupovat k proměnným prostředí použitím makra env!. Překladač si v tomto případě hlídá, zda proměnná prostředí existuje a pokud tomu tak není, vypíše chybové hlášení. Hodnota proměnné je přečtena a zapsána do výsledného souboru, tj. namísto volání makra env! se bude ve výsledném kódu nacházet konstantní řetězec:
fn main() { println!("PATH: {}", env!("PATH")); println!("HOME: {}", env!("HOME")); println!("DISPLAY: {}", env!("DISPLAY")); }
Zpráva vypsaná po překladu a spuštění příkladu:
PATH: /home/tester/.npm/bin:/home/tester/.npm/bin:/home/tester/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/tester/bin:/home/tester/bin HOME: /home/tester DISPLAY: :0.0
13. Proměnné prostředí vyhodnocované při běhu aplikace
Při běhu programu (runtime) je samozřejmě taktéž možné přistupovat k proměnným prostředí, dokonce je to ještě užitečnější, než v příkladu předchozím. Ovšem v tomto případě se nepoužívá makro, ale funkce env::var(). Tato funkce vrací typ Result popsaný minule, takže lze snadno zjistit, zda proměnná existuje či nikoli:
use std::env; fn print_env_var(name:&str) { match env::var(name) { Ok(val) => println!("{}: {:?}", name, val), Err(e) => println!("couldn't interpret {}: {}", name, e), } } fn main() { print_env_var("PATH"); print_env_var("HOME"); print_env_var("DISPLAY"); print_env_var("SPECIAL"); }
Zpráva vypsaná po překladu a spuštění příkladu:
PATH: "/home/tester/.npm/bin:/home/tester/.npm/bin:/home/tester/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/tester/bin:/home/tester/bin" HOME: "/home/tester" DISPLAY: ":0.0" couldn't interpret SPECIAL: environment variable not found
Snadno lze získat i iterátor se všemi proměnnými prostředí. Iterace nad jmény i hodnotami proměnných probíhá takto:
use std::env; fn main() { for (key, value) in env::vars() { println!("{}: {}", key, value); } }
14. Přečtení argumentů předaných na příkazové řádce
Do funkce main se v programovacím jazyku Rust nepředávají žádné parametry, takže pokud je zapotřebí přistupovat k argumentům příkazové řádky, je nutné použít odlišný přístup. Ten spočívá v použití iterátoru vráceného po zavolání env::args(). Tento iterátor obsahuje všechny předané parametry a na prvním místě i jméno souboru, který byl spuštěn:
use std::env; fn main() { for arg in env::args() { println!("{}", arg); } }
Předchozí příklad po svém spuštění (se zadáním tří parametrů) vypíše:
./239_env_all_args foo bar baz ./239_env_all_args foo bar baz
V operačním systému Linux obsahuje první prvek iterátoru cestu ke spouštěnému souboru. Tu získáme velmi snadno, jen nesmíme zapomenout na to, že prvky vrácené iterátorem jsou typu Option, takže je nutné použít metodu .unwrap():
use std::env; fn main() { let exename = env::args().nth(0); let arguments = env::args().count(); println!("exename: {}", exename.unwrap()); println!("arguments: {}", arguments); }
Předchozí příklad po svém spuštění (se zadáním tří parametrů) vypíše:
./240_env_exe_name foo bar baz exename: ./240_env_exe_name arguments: 4
15. Repositář s demonstračními příklady
Všechny dnes popisované demonstrační příklady byly, podobně jako ve všech předchozích částech tohoto seriálu, uloženy do Git repositáře dostupného na adrese https://github.com/tisnik/presentations. Příklady si můžete v případě potřeby stáhnout i jednotlivě bez nutnosti klonovat celý repositář:
16. Odkazy na Internetu
- Module std::fmt
https://doc.rust-lang.org/std/fmt/ - Macro std::println
https://doc.rust-lang.org/std/macro.println.html - Enum std::result::Result
https://doc.rust-lang.org/std/result/enum.Result.html - Module std::result
https://doc.rust-lang.org/std/result/ - Result
http://rustbyexample.com/std/result.html - Rust stdlib: Option
https://doc.rust-lang.org/std/option/enum.Option.html - Module std::option
https://doc.rust-lang.org/std/option/index.html - Rust by example: option
http://rustbyexample.com/std/option.html - Rust by example: if-let
http://rustbyexample.com/flow_control/if_let.html - Rust by example: while let
http://rustbyexample.com/flow_control/while_let.html - Rust by example: Option<i32>
http://rustbyexample.com/std/option.html - An Overview of Macros in Rust
http://words.steveklabnik.com/an-overview-of-macros-in-rust - A Practical Intro to Macros in Rust 1.0
https://danielkeep.github.io/practical-intro-to-macros.html - The Rust Programming Language: macros
https://doc.rust-lang.org/beta/book/macros.html - Rust by example: 15 macro_rules!
http://rustbyexample.com/macros.html - Module std::vec
https://doc.rust-lang.org/nightly/std/vec/index.html - Primitive Type isize
https://doc.rust-lang.org/nightly/std/primitive.isize.html - Primitive Type usize
https://doc.rust-lang.org/nightly/std/primitive.usize.html - Primitive Type array
https://doc.rust-lang.org/nightly/std/primitive.array.html - Module std::slice
https://doc.rust-lang.org/nightly/std/slice/ - Rust by Example: 2.3 Arrays and Slices
http://rustbyexample.com/primitives/array.html - What is the difference between Slice and Array (stackoverflow)
http://stackoverflow.com/questions/30794235/what-is-the-difference-between-slice-and-array - Learning Rust With Entirely Too Many Linked Lists
http://cglab.ca/~abeinges/blah/too-many-lists/book/ - Testcase: linked list
http://rustbyexample.com/custom_types/enum/testcase_linked_list.html - Operators and Overloading
https://doc.rust-lang.org/book/operators-and-overloading.html - Module std::ops
https://doc.rust-lang.org/std/ops/index.html - Module std::cmp
https://doc.rust-lang.org/std/cmp/index.html - Trait std::ops::Add
https://doc.rust-lang.org/stable/std/ops/trait.Add.html - Trait std::ops::AddAssign
https://doc.rust-lang.org/std/ops/trait.AddAssign.html - Trait std::ops::Drop
https://doc.rust-lang.org/std/ops/trait.Drop.html - Trait std::cmp::Eq
https://doc.rust-lang.org/std/cmp/trait.Eq.html - Struct std::boxed::Box
https://doc.rust-lang.org/std/boxed/struct.Box.html - Explore the ownership system in Rust
https://nercury.github.io/rust/guide/2015/01/19/ownership.html - Rust's ownership and move semantic
http://www.slideshare.net/saneyuki/rusts-ownership-and-move-semantics - Trait std::marker::Copy
https://doc.rust-lang.org/stable/std/marker/trait.Copy.html - Trait std::clone::Clone
https://doc.rust-lang.org/stable/std/clone/trait.Clone.html - The Stack and the Heap
https://doc.rust-lang.org/book/the-stack-and-the-heap.html - Rust Compare: Pointers & References
http://www.rust-compare.com/site/pointers.html - Rust Compare: Parameters
http://www.rust-compare.com/site/params.html - Why does this compile? Automatic dereferencing?
https://users.rust-lang.org/t/why-does-this-compile-automatic-dereferencing/2183 - Understanding Pointers, Ownership, and Lifetimes in Rust
http://koerbitz.me/posts/Understanding-Pointers-Ownership-and-Lifetimes-in-Rust.html - Rust lang series episode #25 — pointers (#rust-series)
https://steemit.com/rust-series/@jimmco/rust-lang-series-episode-25-pointers-rust-series - Rust – home page
https://www.rust-lang.org/en-US/ - Rust – Frequently Asked Questions
https://www.rust-lang.org/en-US/faq.html - Destructuring and Pattern Matching
https://pzol.github.io/getting_rusty/posts/20140417_destructuring_in_rust/ - The Rust Programming Language
https://doc.rust-lang.org/book/ - Rust (programming language)
https://en.wikipedia.org/wiki/Rust_%28programming_language%29 - Go – home page
https://golang.org/ - Stack Overflow – Most Loved, Dreaded, and Wanted language
https://stackoverflow.com/research/developer-survey-2016#technology-most-loved-dreaded-and-wanted - Rust vs Go (dva roky staré hodnocení, od té doby došlo k posunům v obou jazycích)
http://jaredforsyth.com/2014/03/22/rust-vs-go/ - Rust vs Go: My experience
https://www.reddit.com/r/golang/comments/21m6jq/rust_vs_go_my_experience/ - Friends of Rust (Organizations running Rust in production)
https://www.rust-lang.org/en-US/friends.html - Rust programs versus C++ g++
https://benchmarksgame.alioth.debian.org/u64q/compare.php?lang=rust&lang2=gpp - Další benchmarky (nejedná se o reálné příklady „ze života“)
https://github.com/kostya/benchmarks - Go na Redditu
https://www.reddit.com/r/golang/ - Rust vs. Go
http://vschart.com/compare/rust/vs/go-language - Abstraction without overhead: traits in Rust
https://blog.rust-lang.org/2015/05/11/traits.html - Method Syntax
https://doc.rust-lang.org/book/method-syntax.html - Traits in Rust
https://doc.rust-lang.org/book/traits.html - Functional Programming in Rust – Part 1 : Function Abstraction
http://blog.madhukaraphatak.com/functional-programming-in-rust-part-1/ - Of the emerging systems languages Rust, D, Go and Nim, which is the strongest language and why?
https://www.quora.com/Of-the-emerging-systems-languages-Rust-D-Go-and-Nim-which-is-the-strongest-language-and-why - Chytré ukazatele (moderní verze jazyka C++) [MSDN]
https://msdn.microsoft.com/cs-cz/library/hh279674.aspx - UTF-8 Everywhere
http://utf8everywhere.org/ - Rust by Example
http://rustbyexample.com/ - Rust oficiálně ve Fedoře
https://mojefedora.cz/rust-oficialne-ve-fedore/ - Resource acquisition is initialization
https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization - TIOBE index (October 2016)
http://www.tiobe.com/tiobe-index/ - Porovnání Go, D a Rustu na OpenHubu:
https://www.openhub.net/languages/compare?language_name[]=-1&language_name[]=-1&language_name[]=dmd&language_name[]=golang&language_name[]=rust&language_name[]=-1&measure=commits - String Types in Rust
http://www.suspectsemantics.com/blog/2016/03/27/string-types-in-rust/ - Trait (computer programming)
https://en.wikipedia.org/wiki/Trait_%28computer_programming%29 - Type inference
https://en.wikipedia.org/wiki/Type_inference