As you might probably know, a Caesar cipher involves shifting/unshifting and wrapping up characters when they overflow the first or last letter of the alphabet, it's useful to have a function to just handle character shifting. So I wrote a function that I intend to use in other places and was hoping to see if there are any edge cases or gotchas that I might be missing in my current implementation
fn char_shift(ch: char, shift: i8) -> char {
if shift == 0 || shift > 25 || shift < -25 {
return ch;
}
let mut res = ch;
let ch_i8 = ch as i8;
match shift {
// Positive Shift
shift @ 0..=i8::MAX => {
match ch_i8 {
65..=90 => {
if ch_i8.overflowing_add(shift).1
|| ch_i8.overflowing_add(shift).0 > 90
{
res = (ch_i8 + (shift - 90 + 64)) as u8 as char;
} else {
res = (ch_i8 + shift) as u8 as char;
}
}
97..=122 => {
if ch_i8.overflowing_add(shift).1
|| ch_i8.overflowing_add(shift).0 > 122
{
res = (ch_i8 + (shift - 122 + 96)) as u8 as char;
} else {
res = (ch_i8 + shift) as u8 as char;
}
}
_ => { /* return the same character that it receieved */ }
}
}
// Negative Shift
unshift @ i8::MIN..=-1 => {
let unshift = -unshift;
match ch_i8 {
65..=90 => {
if ch_i8 - unshift < 65 {
let diff = 65 - (ch_i8 - unshift);
res = ((90 - diff) + 1) as u8 as char;
} else {
res = (ch_i8 - unshift) as u8 as char;
}
}
97..=122 => {
if ch_i8 - unshift < 97 {
let diff = 97 - (ch_i8 - unshift);
res = ((122 - diff) + 1) as u8 as char;
} else {
res = (ch_i8 - unshift) as u8 as char;
}
}
_ => { /* return the same character that it receieved */ }
}
}
}
res
}