minishell-rs
A gradual rewrite of a c2rust transpiled codebase.
Discover how C language programming constructs can be implemented in a more concise way.
- see where rust syntax and std containers can enable better readability or code structure
- discover where
CString
,CStr
and&[u8]
(u8) can find usage and reduce interactions withchar *
- replace
extern "C"
and libc usage with nix wrappers, enabling more idiomatic (and less error prone?) usage of unix system functions. - provide me with an excuse to write rust code
The original implementation used loads of custom glue that could have been replaced with libc functions (strtok, strcoll, scanf/sprintf, fprintf).
This was fine as a school project and provided me with ample opportunities for refactoring in the rust version.
- since rust is not c, interacting with raw pointers is more error prone due to its memory model and my assumptions about memory derived from c
- signal handling was easier to do in c, I ended up removing it as it caused weird bugs
- even though rust has
Command
, it was not used. I adapted my execution logic to be more idiomatic by using nix wrappers (the reason for mostunsafe
usage) - taking advantage of rust's rich type system can improve readability and facilitate quick iteration - choosing the correct tool is key
- transpile, then simplify some operations, mostly aligning types (e.g.
libc::size_t
foru64
/usize
), removing non-needed casts and replacing.offset()
with.add()
- multiple failed rewrites of core functionality caused by newly introduced logic bugs - mitigated by comprehensive test cases
- issues with readability, naming - resolved by using more idiomatic constructs:
Option
,Result
, tuples, slices instead of references,impl
for structs - remove duplicate or dead code replaced by std (
format!
,vec![]
, ...)
- document & simplify original logic
- create adaptable tests, wrappers fitting both c-like and idiomatic rust outputs
- apply TDD feedback loop while simplifying logic and reducing
unsafe