- M.Sc. in Computational Biology
- Ph.D. in Microbiology
- Samba Team member
SambaXP 2018
2017-06-06
If someone claims to have the perfect programming language, he is either a fool or a salesman or both.
– Bjarne Stroustrup
"The [Samba] project does need to consider the use of other, safer languages."
– Jeremy Allison, SambaXP 2016
cargo
fn main() { println!("Hello, world!"); }
Explained in the Rust Book
[lib] name = "embed" crate-type = ["dylib"]
cargo
waf
Idea: Build a small demo first, then figure out how to link
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ID | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ |QR|BD|IT|UL|BL|Reserved| Red | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | Green | Blue | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | Query ... | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ... | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | Payload ... | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ... | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Server
$ cd server $ cargo run
Client
$ cd client $ cargo run 127.0.0.1 65432 greeting
In theory, there is no difference between theory and practice. But, in practice, there is.
– Jan L. A. van de Snepscheut
pub struct Package { pub id: u16, pub message_type: MessageType, pub bold: bool, pub italic: bool, pub underlined: bool, pub blink: bool, pub red: u8, pub green: u8, pub blue: u8, pub query: Option<String>, pub payload: Option<String>, } pub enum MessageType { Query, Response, }
let mut query = Package::new(); query.query = Some(config.query); let mut out_buf: Vec<u8> = Vec::new(); { let mut encoder = Encoder::new(&mut out_buf); query.write(&mut encoder).expect("Failed to encode query"); } // send query // get response let mut decoder = Decoder::new(&in_buf); let response = Package::read(&mut decoder).expect("Parsing the response failed"); // Format, colour and print response
loop { // Receive query into inbuf let mut decoder = Decoder::new(inbuf); let query = Package::read(&mut decoder).expect("Parsing query failed"); let response = lookup_message(&mut messages, &query); let mut outbuf: Vec<u8> = Vec::new(); { let mut encoder = Encoder::new(&mut outbuf); response.write(&mut encoder).expect("Encoding response failed"); } // Send response from outbuf }
while True { // Recieve query into in_buffer // Call into Rust for parsing in_buf into Package query = decode_package(in_buffer, len); // "Business logic" in C lookup_message(query, response); // Call into Rust again to create out_buf for Package encode_package(response, &out_buffer, &len); // Send response from out_buffer }
typedef struct package { //... } Package; Package *decode_package(const uint8_t* buffer, size_t len); int encode_package(const Package *package, uint8_t **buffer, size_t *len);
Who owns memory for the Package
struct in decode_package()
?
typedef struct package { //... } Package; Package *decode_package(const uint8_t* buffer, size_t len); int encode_package(const Package *package, uint8_t **buffer, size_t *len); void free_package(Package *package); void free_buffer(uint8_t *buffer);
$ cd c-server $ make run
talloc
to Rustlibtalloc
via FFItalloc_named_const()
and talloc_free()
callsuse libc::{size_t, c_int, c_char, c_void}; #[link(name="talloc")] extern { pub fn talloc_named_const(context: *const c_void, size: size_t, name: *const c_char) -> *mut c_void; pub fn _talloc_free(context: *mut c_void, location: *const c_char) -> c_int; }
talloc
is useable in RustBox<>
Box<>
-like TallocContext<>
that uses tallocimpl<T> TallocContext<T> { pub fn new<U>(parent: Option<TallocContext<U>>) -> TallocContext<T> { let size = size_of::<T>(); let name = CString::new("Memory context allocated from Rust.") .unwrap(); let parent_ptr = match parent { Some(tc) => tc.ptr, None => null(), }; unsafe { let ptr = ffi::talloc_named_const(parent_ptr as *const c_void, size as size_t, name.as_ptr()); TallocContext { ptr: ptr as *mut u8, phantom: PhantomData } } } }
impl<T> Drop for TallocContext<T> { fn drop(&mut self) { let name = CString::new("Free in the Rust deallocation logic.") .unwrap(); unsafe { let retcode = ffi::_talloc_free(self.ptr as *mut c_void, name.as_ptr()); if retcode != 0 { panic!("Failed to free memory!"); } }; } }
pub struct Package { pub id: u16, pub message_type: MessageType, pub bold: bool, pub italic: bool, pub underlined: bool, pub blink: bool, pub red: u8, pub green: u8, pub blue: u8, pub query: Option<String>, pub payload: Option<String>, }
pub struct TallocString { inner: TallocContext<[u8]>, } pub struct TallocVec<T> { context: TallocContext<T>, len: usize, }
talloc
versions of all heap-allocated structures >- Lots of boilerplatetalloc
useable as global allocator in RustAllocate
traitImplementing talloc in Rust
Truth is subjectivity.
–Søren Kierkegaard