It's like doing code golf if it were.. football? Codeball? I don't know, I've lost enough of my sanity as it is to name this monstrosity.
use std::arch::asm; // Yes, why not make it longer. I invite the next person to over-engineer it further. // (an INTERCAL interpreter implemented using Rust macros would be kinda funny) fn reverse(s: &str) -> String { let mut reversed = s.to_string(); unsafe fn reverse_string_asm(s: &mut str) { let strlen = s.len(); let strptr = s.as_ptr(); asm!( "mov rcx, {strlen}", "shr rcx, 1", "jz 2f", "mov rsi, {strptr}", "mov rdi, {strptr}", "add rdi, {strlen}", "dec rdi", "2:", "mov al, [rsi]", "mov bl, [rdi]", "mov [rsi], bl", "mov [rdi], al", "inc rsi", "dec rdi", "loop 2b", "2:", strlen = in(reg) strlen, strptr = in(reg) strptr, options(nostack, preserves_flags) ); } if reversed.len() != 0 { unsafe { reverse_string_asm(reversed.as_mut()) }; } reversed }
- use std::arch::asm;
- // Yes, why not make it longer. I invite the next person to over-engineer it further.
- // (an INTERCAL interpreter implemented using Rust macros would be kinda funny)
- fn reverse(s: &str) -> String {
s.chars().fold(String::new(), |acc, c| format!("{}{}", c, acc))- let mut reversed = s.to_string();
- unsafe fn reverse_string_asm(s: &mut str) {
- let strlen = s.len();
- let strptr = s.as_ptr();
- asm!(
- "mov rcx, {strlen}",
- "shr rcx, 1",
- "jz 2f",
- "mov rsi, {strptr}",
- "mov rdi, {strptr}",
- "add rdi, {strlen}",
- "dec rdi",
- "2:",
- "mov al, [rsi]",
- "mov bl, [rdi]",
- "mov [rsi], bl",
- "mov [rdi], al",
- "inc rsi",
- "dec rdi",
- "loop 2b",
- "2:",
- strlen = in(reg) strlen,
- strptr = in(reg) strptr,
- options(nostack, preserves_flags)
- );
- }
- if reversed.len() != 0 {
- unsafe { reverse_string_asm(reversed.as_mut()) };
- }
- reversed
- }
#[cfg(test)] mod tests { use super::*; #[test] fn test_add() { // I had to separate the string literals to be their own variables // or else the test cases would not pass. Because assembly. let case1 = ("", ""); let case2 = ("abc", "cba"); let case3 = ("ccabc", "cbacc"); let case4 = ("Reverse strings", "sgnirts esreveR"); let case5 = ("Codewars", "srawedoC"); assert_eq!(reverse(case1.0), case1.1); assert_eq!(reverse(case2.0), case2.1); assert_eq!(reverse(case3.0), case3.1); assert_eq!(reverse(case4.0), case4.1); } }
// Add your tests here.// See https://doc.rust-lang.org/stable/rust-by-example/testing/unit_testing.html- #[cfg(test)]
- mod tests {
- use super::*;
- #[test]
- fn test_add() {
assert_eq!(reverse(""), "");assert_eq!(reverse("abc"), "cba");assert_eq!(reverse("ccabc"), "cbacc");assert_eq!(reverse("Reverse strings"), "sgnirts esreveR");assert_eq!(reverse("Codewars"), "srawedoC");- // I had to separate the string literals to be their own variables
- // or else the test cases would not pass. Because assembly.
- let case1 = ("", "");
- let case2 = ("abc", "cba");
- let case3 = ("ccabc", "cbacc");
- let case4 = ("Reverse strings", "sgnirts esreveR");
- let case5 = ("Codewars", "srawedoC");
- assert_eq!(reverse(case1.0), case1.1);
- assert_eq!(reverse(case2.0), case2.1);
- assert_eq!(reverse(case3.0), case3.1);
- assert_eq!(reverse(case4.0), case4.1);
- }
- }