|
| 1 | +% Rust Cheatsheet |
| 2 | + |
| 3 | +# How do I convert *X* to *Y*? |
| 4 | + |
| 5 | +**Int to string** |
| 6 | + |
| 7 | +Use [`ToStr`](std/to_str/trait.ToStr.html). |
| 8 | + |
| 9 | +~~~ |
| 10 | +let x: int = 42; |
| 11 | +let y: String = x.to_str(); |
| 12 | +~~~ |
| 13 | + |
| 14 | +**String to int** |
| 15 | + |
| 16 | +Use [`FromStr`](std/from_str/trait.FromStr.html), and its helper function, |
| 17 | +[`from_str`](std/from_str/fn.from_str.html). |
| 18 | + |
| 19 | +~~~ |
| 20 | +let x: Option<int> = from_str("42"); |
| 21 | +let y: int = x.unwrap(); |
| 22 | +~~~ |
| 23 | + |
| 24 | +**Int to string, in non-base-10** |
| 25 | + |
| 26 | +Use the `format!` syntax extension. |
| 27 | + |
| 28 | +~~~ |
| 29 | +let x: int = 42; |
| 30 | +let y: String = format!("{:t}", x); // binary |
| 31 | +let y: String = format!("{:o}", x); // octal |
| 32 | +let y: String = format!("{:x}", x); // lowercase hexadecimal |
| 33 | +let y: String = format!("{:X}", x); // uppercase hexadecimal |
| 34 | +~~~ |
| 35 | + |
| 36 | +**String to int, in non-base-10** |
| 37 | + |
| 38 | +Use [`FromStrRadix`](std/num/trait.FromStrRadix.html), and its helper |
| 39 | +function, [`from_str_radix`](std/num/fn.from_str_radix.html). |
| 40 | + |
| 41 | +~~~ |
| 42 | +use std::num; |
| 43 | +
|
| 44 | +let x: Option<i64> = num::from_str_radix("deadbeef", 16); |
| 45 | +let y: i64 = x.unwrap(); |
| 46 | +~~~ |
| 47 | + |
| 48 | +**Vector of Bytes to String** |
| 49 | + |
| 50 | +To return a Borrowed String Slice (&str) use the str helper function |
| 51 | +[`from_utf8`](std/str/fn.from_utf8.html). |
| 52 | + |
| 53 | +~~~ |
| 54 | +use std::str; |
| 55 | +
|
| 56 | +let bytes = &[104u8,105u8]; |
| 57 | +let x: &str = str::from_utf8(bytes).unwrap(); |
| 58 | +~~~ |
| 59 | + |
| 60 | +To return an Owned String use the str helper function |
| 61 | +[`from_utf8_owned`](std/str/fn.from_utf8_owned.html). |
| 62 | + |
| 63 | +~~~ |
| 64 | +use std::str; |
| 65 | +
|
| 66 | +let x: Option<String> = |
| 67 | + str::from_utf8([ 104u8, 105u8 ]).map(|x| x.to_string()); |
| 68 | +let y: String = x.unwrap(); |
| 69 | +~~~ |
| 70 | + |
| 71 | +To return a [`MaybeOwned`](std/str/type.MaybeOwned.html) use the str helper |
| 72 | +function [`from_utf8_lossy`](std/str/fn.from_utf8_owned.html). |
| 73 | +This function also replaces non-valid utf-8 sequences with U+FFFD replacement |
| 74 | +character. |
| 75 | + |
| 76 | +~~~ |
| 77 | +use std::str; |
| 78 | +
|
| 79 | +let x = b"Hello \xF0\x90\x80World!"; |
| 80 | +let y = str::from_utf8_lossy(x); |
| 81 | +~~~ |
| 82 | + |
| 83 | +**`Vec<T>`/`String` to `&[T]`/`&str`** |
| 84 | + |
| 85 | +The `.as_slice` method on each type provides a borrowed slice pointing |
| 86 | +to the contents of a `Vec` or `String`. The slice points directly to |
| 87 | +the data already stored in the vector or string, and so is a very |
| 88 | +cheap operation (no allocations or complicated computations required). |
| 89 | + |
| 90 | +~~~ |
| 91 | +let vec: Vec<u32> = vec![1, 2, 3]; |
| 92 | +let slice: &[u32] = vec.as_slice(); |
| 93 | +
|
| 94 | +let string: String = "foo bar".to_string(); |
| 95 | +let str_slice: &str = string.as_slice(); |
| 96 | +~~~ |
| 97 | + |
| 98 | +`Vec` also provides the `.as_mut_slice` method for viewing the |
| 99 | +contained data as a `&mut [T]`. |
| 100 | + |
| 101 | +# File operations |
| 102 | + |
| 103 | +## How do I read from a file? |
| 104 | + |
| 105 | +Use |
| 106 | +[`File::open`](std/io/fs/struct.File.html#method.open) |
| 107 | +to create a |
| 108 | +[`File`](std/io/fs/struct.File.html) |
| 109 | +struct, which implements the |
| 110 | +[`Reader`](std/io/trait.Reader.html) |
| 111 | +trait. |
| 112 | + |
| 113 | +~~~ {.ignore} |
| 114 | +use std::path::Path; |
| 115 | +use std::io::fs::File; |
| 116 | +
|
| 117 | +let path : Path = Path::new("Doc-FAQ-Cheatsheet.md"); |
| 118 | +let on_error = || fail!("open of {:?} failed", path); |
| 119 | +let reader : File = File::open(&path).unwrap_or_else(on_error); |
| 120 | +~~~ |
| 121 | + |
| 122 | +## How do I iterate over the lines in a file? |
| 123 | + |
| 124 | +Use the [`lines`](std/io/trait.Buffer.html#method.lines) method on a |
| 125 | +[`BufferedReader`](std/io/struct.BufferedReader.html). |
| 126 | + |
| 127 | +~~~ |
| 128 | +use std::io::BufferedReader; |
| 129 | +# use std::io::MemReader; |
| 130 | +
|
| 131 | +# let reader = MemReader::new(vec!()); |
| 132 | +
|
| 133 | +let mut reader = BufferedReader::new(reader); |
| 134 | +for line in reader.lines() { |
| 135 | + print!("line: {}", line); |
| 136 | +} |
| 137 | +~~~ |
| 138 | + |
| 139 | +# String operations |
| 140 | + |
| 141 | +## How do I search for a substring? |
| 142 | + |
| 143 | +Use the [`find_str`](std/str/trait.StrSlice.html#tymethod.find_str) method. |
| 144 | + |
| 145 | +~~~ |
| 146 | +let str = "Hello, this is some random string"; |
| 147 | +let index: Option<uint> = str.find_str("rand"); |
| 148 | +~~~ |
| 149 | + |
| 150 | +# Containers |
| 151 | + |
| 152 | +## How do I get the length of a vector? |
| 153 | + |
| 154 | +The [`Container`](std/container/trait.Container.html) trait provides the `len` method. |
| 155 | + |
| 156 | +~~~ |
| 157 | +let u: Vec<u32> = vec![0, 1, 2]; |
| 158 | +let v: &[u32] = &[0, 1, 2, 3]; |
| 159 | +let w: [u32, .. 5] = [0, 1, 2, 3, 4]; |
| 160 | +
|
| 161 | +println!("u: {}, v: {}, w: {}", u.len(), v.len(), w.len()); // 3, 4, 5 |
| 162 | +~~~ |
| 163 | + |
| 164 | +## How do I iterate over a vector? |
| 165 | + |
| 166 | +Use the [`iter`](std/slice/trait.ImmutableVector.html#tymethod.iter) method. |
| 167 | + |
| 168 | +~~~ |
| 169 | +let values: Vec<int> = vec![1, 2, 3, 4, 5]; |
| 170 | +for value in values.iter() { // value: &int |
| 171 | + println!("{}", *value); |
| 172 | +} |
| 173 | +~~~ |
| 174 | + |
| 175 | +(See also [`mut_iter`](std/slice/trait.MutableVector.html#tymethod.mut_iter) |
| 176 | +which yields `&mut int` and |
| 177 | +[`move_iter`](std/slice/trait.OwnedVector.html#tymethod.move_iter) which yields |
| 178 | +`int` while consuming the `values` vector.) |
| 179 | + |
| 180 | +# Type system |
| 181 | + |
| 182 | +## How do I store a function in a struct? |
| 183 | + |
| 184 | +~~~ |
| 185 | +struct Foo { |
| 186 | + myfunc: fn(int, uint) -> i32 |
| 187 | +} |
| 188 | +
|
| 189 | +struct FooClosure<'a> { |
| 190 | + myfunc: |int, uint|: 'a -> i32 |
| 191 | +} |
| 192 | +
|
| 193 | +fn a(a: int, b: uint) -> i32 { |
| 194 | + (a as uint + b) as i32 |
| 195 | +} |
| 196 | +
|
| 197 | +fn main() { |
| 198 | + let f = Foo { myfunc: a }; |
| 199 | + let g = FooClosure { myfunc: |a, b| { (a - b as int) as i32 } }; |
| 200 | + println!("{}", (f.myfunc)(1, 2)); |
| 201 | + println!("{}", (g.myfunc)(3, 4)); |
| 202 | +} |
| 203 | +~~~ |
| 204 | + |
| 205 | +Note that the parenthesis surrounding `f.myfunc` are necessary: they are how Rust disambiguates field lookup and method call. The `'a` on `FooClosure` is the lifetime of the closure's environment pointer. |
| 206 | + |
| 207 | +## How do I express phantom types? |
| 208 | + |
| 209 | +[Phantom types](http://www.haskell.org/haskellwiki/Phantom_type) are those that cannot be constructed at compile time. To express these in Rust, zero-variant `enum`s can be used: |
| 210 | + |
| 211 | +~~~ |
| 212 | +enum Open {} |
| 213 | +enum Closed {} |
| 214 | +~~~ |
| 215 | + |
| 216 | +Phantom types are useful for enforcing state at compile time. For example: |
| 217 | + |
| 218 | +~~~ |
| 219 | +struct Door<State>(String); |
| 220 | +
|
| 221 | +struct Open; |
| 222 | +struct Closed; |
| 223 | +
|
| 224 | +fn close(Door(name): Door<Open>) -> Door<Closed> { |
| 225 | + Door::<Closed>(name) |
| 226 | +} |
| 227 | +
|
| 228 | +fn open(Door(name): Door<Closed>) -> Door<Open> { |
| 229 | + Door::<Open>(name) |
| 230 | +} |
| 231 | +
|
| 232 | +let _ = close(Door::<Open>("front".to_string())); |
| 233 | +~~~ |
| 234 | + |
| 235 | +Attempting to close a closed door is prevented statically: |
| 236 | + |
| 237 | +~~~ {.ignore} |
| 238 | +let _ = close(Door::<Closed>("front".to_string())); // error: mismatched types: expected `main::Door<main::Open>` but found `main::Door<main::Closed>` |
| 239 | +~~~ |
| 240 | + |
| 241 | +# FFI (Foreign Function Interface) |
| 242 | + |
| 243 | +## C function signature conversions |
| 244 | + |
| 245 | +| Description | C signature | Equivalent Rust signature | |
| 246 | +|---------------------|-----------------------------------------------|------------------------------------------------| |
| 247 | +| no parameters | `void foo(void);` | `fn foo();` | |
| 248 | +| return value | `int foo(void);` | `fn foo() -> c_int;` | |
| 249 | +| function parameters | `void foo(int x, int y);` | `fn foo(x: c_int, y: c_int);` | |
| 250 | +| in-out pointers | `void foo(const int* in_ptr, int* out_ptr);` | `fn foo(in_ptr: *c_int, out_ptr: *mut c_int);` | |
| 251 | + |
| 252 | +Note: The Rust signatures should be wrapped in an `extern "ABI" { ... }` block. |
| 253 | + |
| 254 | +### Representing opaque handles |
| 255 | + |
| 256 | +You might see things like this in C APIs: |
| 257 | + |
| 258 | +~~~c |
| 259 | +typedef struct Window Window; |
| 260 | +Window* createWindow(int width, int height); |
| 261 | +~~~ |
| 262 | +
|
| 263 | +You can use a zero-element `enum` ([phantom type](#how-do-i-express-phantom-types)) to represent the opaque object handle. The FFI would look like this: |
| 264 | +
|
| 265 | +~~~ {.ignore} |
| 266 | +enum Window {} |
| 267 | +extern "C" { |
| 268 | + fn createWindow(width: c_int, height: c_int) -> *Window; |
| 269 | +} |
| 270 | +~~~ |
| 271 | + |
| 272 | +Using a phantom type ensures that the handles cannot be (safely) constructed in client code. |
| 273 | + |
| 274 | +# Contributing to this page |
| 275 | + |
| 276 | +For small examples, have full type annotations, as much as is reasonable, to keep it clear what, exactly, everything is doing. Try to link to the API docs, as well. |
| 277 | + |
| 278 | +Similar documents for other programming languages: |
| 279 | + |
| 280 | + * [http://pleac.sourceforge.net/](http://pleac.sourceforge.net) |
0 commit comments