78 lines
2.6 KiB
Rust
78 lines
2.6 KiB
Rust
use std::ffi::{CStr, CString};
|
|
|
|
use thiserror::Error;
|
|
|
|
mod black_box;
|
|
|
|
#[derive(Error, Debug, PartialEq, Eq)]
|
|
pub enum ConfirmationIdError {
|
|
#[error("Installation ID is too short.")]
|
|
TooShort,
|
|
#[error("Installation ID is too long.")]
|
|
TooLarge,
|
|
#[error("Invalid character in installation ID.")]
|
|
InvalidCharacter,
|
|
#[error("Installation ID checksum failed. Please check that it is typed correctly.")]
|
|
InvalidCheckDigit,
|
|
#[error("Unknown installation ID version.")]
|
|
UnknownVersion,
|
|
#[error("Unable to generate valid confirmation ID.")]
|
|
Unlucky,
|
|
}
|
|
|
|
pub fn generate(installation_id: &str) -> Result<String, ConfirmationIdError> {
|
|
if installation_id.len() < 54 {
|
|
return Err(ConfirmationIdError::TooShort);
|
|
}
|
|
if installation_id.len() > 54 {
|
|
return Err(ConfirmationIdError::TooLarge);
|
|
}
|
|
let inst_id = CString::new(installation_id).unwrap();
|
|
let conf_id = [0u8; 49];
|
|
let result = unsafe { black_box::generate(inst_id.as_ptr(), conf_id.as_ptr() as *mut i8) };
|
|
match result {
|
|
0 => {}
|
|
1 => return Err(ConfirmationIdError::TooShort),
|
|
2 => return Err(ConfirmationIdError::TooLarge),
|
|
3 => return Err(ConfirmationIdError::InvalidCharacter),
|
|
4 => return Err(ConfirmationIdError::InvalidCheckDigit),
|
|
5 => return Err(ConfirmationIdError::UnknownVersion),
|
|
6 => return Err(ConfirmationIdError::Unlucky),
|
|
_ => panic!("Unknown error code: {}", result),
|
|
}
|
|
unsafe {
|
|
Ok(CStr::from_ptr(conf_id.as_ptr() as *const i8)
|
|
.to_str()
|
|
.unwrap()
|
|
.to_string())
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_generate() {
|
|
assert_eq!(
|
|
generate("334481558826870862843844566221823392794862457401103810").unwrap(),
|
|
"110281-200130-887120-647974-697175-027544-252733"
|
|
);
|
|
assert!(
|
|
generate("33448155882687086284384456622182339279486245740110381")
|
|
.is_err_and(|err| err == ConfirmationIdError::TooShort),
|
|
);
|
|
assert!(
|
|
generate("3344815588268708628438445662218233927948624574011038100")
|
|
.is_err_and(|err| err == ConfirmationIdError::TooLarge),
|
|
);
|
|
assert!(
|
|
generate("33448155882687086284384456622182339279486245740110381!")
|
|
.is_err_and(|err| err == ConfirmationIdError::InvalidCharacter),
|
|
);
|
|
assert!(
|
|
generate("334481558826870862843844566221823392794862457401103811")
|
|
.is_err_and(|err| err == ConfirmationIdError::InvalidCheckDigit),
|
|
);
|
|
}
|
|
}
|