Since Rust and C can agree on ABI and memory layout issues, you can move the code over function-by-function if you were so inclined, right? Declare the structs in the headers and auto-gen the Rust versions (is there a tool for the inverse?).
int get_a_string(char **out) // returns error code
could be translated literally as fn get_a_string(out: *mut *mut c_char) -> c_int
but much preferable would be fn get_a_string() -> Result<String, Errcode>
[where Result and String are standard library types; Errcode would be a custom enum.]I suppose you could go from the first to the second incrementally, then refactor to the third. But I'm not sure it'd work well.
.and_then calls themselves aren't too bad, with the right whitespace.
https://github.com/rust-lang/rfcs/pull/243 (note that what was actually accepted differs from the text of the RFC, you need to scroll to the bottom)
As steveklabnik says, there's nothing resembling generalized monadic do notation for now.