From 399d567c624752f22c4ac0ad71338eff8a6d0f6b Mon Sep 17 00:00:00 2001 From: Nathan Fisher Date: Mon, 22 May 2023 00:45:43 -0400 Subject: [PATCH] Implement to/from numerical status codes for Status enum and add tests --- .gitignore | 2 + README.md | 1 + src/status.rs | 161 +++++++++++++++++++++++++++++++++++++++++++++++--- tags | 92 ----------------------------- 4 files changed, 157 insertions(+), 99 deletions(-) create mode 100644 README.md delete mode 100644 tags diff --git a/.gitignore b/.gitignore index 4fffb2f..65a366f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ /target /Cargo.lock +tags +tags.lock diff --git a/README.md b/README.md new file mode 100644 index 0000000..43777f9 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +A [misfin](gemini://misfin.org/) library in Rust (WIP) diff --git a/src/status.rs b/src/status.rs index 58a2eca..5215ccf 100644 --- a/src/status.rs +++ b/src/status.rs @@ -33,17 +33,29 @@ pub enum Status { AuthenticationFailure(AuthenticationFailure) = 60, } +impl From for u8 { + fn from(value: Status) -> Self { + match value { + Status::Input | Status::Success => value.into(), + Status::Redirect(n) => 30 + n as u8, + Status::TemporaryFailure(n) => 40 + n as u8, + Status::PermanentFailure(n) => 50 + n as u8, + Status::AuthenticationFailure(n) => 60 + n as u8, + } + } +} + impl TryFrom for Status { type Error = StatusError; fn try_from(value: u8) -> Result { - match value { - n if n / 10 == 1 => Ok(Self::Input), - n if n / 20 == 1 => Ok(Self::Success), - n if n / 30 == 1 => Ok(Self::Redirect((value % 30).try_into()?)), - n if n / 40 == 1 => Ok(Self::TemporaryFailure((value % 40).try_into()?)), - n if n / 50 == 1 => Ok(Self::PermanentFailure((value % 50).try_into()?)), - n if n / 60 == 1 => Ok(Self::AuthenticationFailure((value % 60).try_into()?)), + match value / 10 { + 1 => Ok(Self::Input), + 2 => Ok(Self::Success), + 3 => Ok(Self::Redirect((value % 30).try_into()?)), + 4 => Ok(Self::TemporaryFailure((value % 40).try_into()?)), + 5 => Ok(Self::PermanentFailure((value % 50).try_into()?)), + 6 => Ok(Self::AuthenticationFailure((value % 60).try_into()?)), _ => Err(StatusError), } } @@ -160,3 +172,138 @@ impl TryFrom for AuthenticationFailure { } } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn parse_status_success() { + let status = Status::try_from(21).unwrap(); + assert_eq!(status, Status::Success); + } + + #[test] + fn parse_redirect_err() { + assert!(Redirect::try_from(42).is_err()); + } + + #[test] + fn parse_status_redirect() { + assert_eq!( + Status::try_from(30).unwrap(), + Status::Redirect(Redirect::Temporary) + ); + assert_eq!( + Status::try_from(31).unwrap(), + Status::Redirect(Redirect::Permanent) + ); + assert_eq!( + Status::try_from(32).unwrap(), + Status::Redirect(Redirect::Other) + ); + } + + #[test] + fn parse_temporary_err() { + assert!(TemporaryFailure::try_from(42).is_err()); + } + + #[test] + fn parse_status_temporary() { + assert_eq!( + Status::try_from(40).unwrap(), + Status::TemporaryFailure(TemporaryFailure::TemporaryError) + ); + assert_eq!( + Status::try_from(41).unwrap(), + Status::TemporaryFailure(TemporaryFailure::ServerUnavailable) + ); + assert_eq!( + Status::try_from(42).unwrap(), + Status::TemporaryFailure(TemporaryFailure::CgiError) + ); + assert_eq!( + Status::try_from(43).unwrap(), + Status::TemporaryFailure(TemporaryFailure::ProxyError) + ); + assert_eq!( + Status::try_from(44).unwrap(), + Status::TemporaryFailure(TemporaryFailure::RateLimit) + ); + assert_eq!( + Status::try_from(45).unwrap(), + Status::TemporaryFailure(TemporaryFailure::MailboxFull) + ); + assert_eq!( + Status::try_from(46).unwrap(), + Status::TemporaryFailure(TemporaryFailure::Other) + ); + } + + #[test] + fn parse_permanent_err() { + assert!(PermanentFailure::try_from(42).is_err()); + } + + #[test] + fn parse_status_permanent() { + assert_eq!( + Status::try_from(50).unwrap(), + Status::PermanentFailure(PermanentFailure::PermanentError) + ); + assert_eq!( + Status::try_from(51).unwrap(), + Status::PermanentFailure(PermanentFailure::MailboxNonexistent) + ); + assert_eq!( + Status::try_from(52).unwrap(), + Status::PermanentFailure(PermanentFailure::MailboxGone) + ); + assert_eq!( + Status::try_from(53).unwrap(), + Status::PermanentFailure(PermanentFailure::DomainNotServiced) + ); + assert_eq!( + Status::try_from(59).unwrap(), + Status::PermanentFailure(PermanentFailure::BadRequest) + ); + assert_eq!( + Status::try_from(57).unwrap(), + Status::PermanentFailure(PermanentFailure::Other) + ); + } + + #[test] + fn parse_auth_err() { + assert!(AuthenticationFailure::try_from(42).is_err()); + } + + #[test] + fn parse_status_auth() { + assert_eq!( + Status::try_from(60).unwrap(), + Status::AuthenticationFailure(AuthenticationFailure::CertificateRequired) + ); + assert_eq!( + Status::try_from(61).unwrap(), + Status::AuthenticationFailure(AuthenticationFailure::UnauthorizedSender) + ); + assert_eq!( + Status::try_from(62).unwrap(), + Status::AuthenticationFailure(AuthenticationFailure::CertificateInvalid) + ); + assert_eq!( + Status::try_from(63).unwrap(), + Status::AuthenticationFailure(AuthenticationFailure::IdentityMismatch) + ); + assert_eq!( + Status::try_from(64).unwrap(), + Status::AuthenticationFailure(AuthenticationFailure::ProofRequired) + ); + assert_eq!( + Status::try_from(65).unwrap(), + Status::AuthenticationFailure(AuthenticationFailure::Other) + ); + } +} diff --git a/tags b/tags deleted file mode 100644 index a31ed38..0000000 --- a/tags +++ /dev/null @@ -1,92 +0,0 @@ -!_TAG_EXTRA_DESCRIPTION anonymous /Include tags for non-named objects like lambda/ -!_TAG_EXTRA_DESCRIPTION fileScope /Include tags of file scope/ -!_TAG_EXTRA_DESCRIPTION pseudo /Include pseudo tags/ -!_TAG_EXTRA_DESCRIPTION subparser /Include tags generated by subparsers/ -!_TAG_FIELD_DESCRIPTION epoch /the last modified time of the input file (only for F\/file kind tag)/ -!_TAG_FIELD_DESCRIPTION file /File-restricted scoping/ -!_TAG_FIELD_DESCRIPTION input /input file/ -!_TAG_FIELD_DESCRIPTION name /tag name/ -!_TAG_FIELD_DESCRIPTION pattern /pattern/ -!_TAG_FIELD_DESCRIPTION typeref /Type and name of a variable or typedef/ -!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/ -!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/ -!_TAG_KIND_DESCRIPTION!Rust C,constant /A constant/ -!_TAG_KIND_DESCRIPTION!Rust M,macro /Macro Definition/ -!_TAG_KIND_DESCRIPTION!Rust P,method /A method/ -!_TAG_KIND_DESCRIPTION!Rust c,implementation /implementation/ -!_TAG_KIND_DESCRIPTION!Rust e,enumerator /An enum variant/ -!_TAG_KIND_DESCRIPTION!Rust f,function /Function/ -!_TAG_KIND_DESCRIPTION!Rust g,enum /Enum/ -!_TAG_KIND_DESCRIPTION!Rust i,interface /trait interface/ -!_TAG_KIND_DESCRIPTION!Rust m,field /A struct field/ -!_TAG_KIND_DESCRIPTION!Rust n,module /module/ -!_TAG_KIND_DESCRIPTION!Rust s,struct /structural type/ -!_TAG_KIND_DESCRIPTION!Rust t,typedef /Type Alias/ -!_TAG_KIND_DESCRIPTION!Rust v,variable /Global variable/ -!_TAG_OUTPUT_EXCMD mixed /number, pattern, mixed, or combineV2/ -!_TAG_OUTPUT_FILESEP slash /slash or backslash/ -!_TAG_OUTPUT_MODE u-ctags /u-ctags or e-ctags/ -!_TAG_OUTPUT_VERSION 0.0 /current.age/ -!_TAG_PARSER_VERSION!Rust 0.0 /current.age/ -!_TAG_PATTERN_LENGTH_LIMIT 96 /0 for no limit/ -!_TAG_PROC_CWD /home/nathan/src/dory/ // -!_TAG_PROGRAM_AUTHOR Universal Ctags Team // -!_TAG_PROGRAM_NAME Universal Ctags /Derived from Exuberant Ctags/ -!_TAG_PROGRAM_URL https://ctags.io/ /official site/ -!_TAG_PROGRAM_VERSION 6.0.0 /p6.0.20221218.0/ -AuthenticationFailure src/status.rs /^ AuthenticationFailure(AuthenticationFailure) = 60,$/;" e enum:Status -AuthenticationFailure src/status.rs /^impl TryFrom for AuthenticationFailure {$/;" c -AuthenticationFailure src/status.rs /^pub enum AuthenticationFailure {$/;" g -BadRequest src/status.rs /^ BadRequest = 9,$/;" e enum:PermanentFailure -CertificateInvalid src/status.rs /^ CertificateInvalid = 2,$/;" e enum:AuthenticationFailure -CertificateRequired src/status.rs /^ CertificateRequired = 0,$/;" e enum:AuthenticationFailure -CgiError src/status.rs /^ CgiError = 2,$/;" e enum:TemporaryFailure -DomainNotServiced src/status.rs /^ DomainNotServiced = 3,$/;" e enum:PermanentFailure -Error src/status.rs /^ type Error = StatusError;$/;" t implementation:AuthenticationFailure -Error src/status.rs /^ type Error = StatusError;$/;" t implementation:PermanentFailure -Error src/status.rs /^ type Error = StatusError;$/;" t implementation:Redirect -Error src/status.rs /^ type Error = StatusError;$/;" t implementation:Status -Error src/status.rs /^ type Error = StatusError;$/;" t implementation:TemporaryFailure -IdentityMismatch src/status.rs /^ IdentityMismatch = 3,$/;" e enum:AuthenticationFailure -Input src/status.rs /^ Input = 10,$/;" e enum:Status -MailboxFull src/status.rs /^ MailboxFull = 5,$/;" e enum:TemporaryFailure -MailboxGone src/status.rs /^ MailboxGone = 2,$/;" e enum:PermanentFailure -MailboxNonexistent src/status.rs /^ MailboxNonexistent = 1,$/;" e enum:PermanentFailure -Other src/status.rs /^ Other,$/;" e enum:AuthenticationFailure -Other src/status.rs /^ Other,$/;" e enum:PermanentFailure -Other src/status.rs /^ Other,$/;" e enum:Redirect -Other src/status.rs /^ Other,$/;" e enum:TemporaryFailure -Permanent src/status.rs /^ Permanent = 1,$/;" e enum:Redirect -PermanentError src/status.rs /^ PermanentError = 0,$/;" e enum:PermanentFailure -PermanentFailure src/status.rs /^ PermanentFailure(PermanentFailure) = 50,$/;" e enum:Status -PermanentFailure src/status.rs /^impl TryFrom for PermanentFailure {$/;" c -PermanentFailure src/status.rs /^pub enum PermanentFailure {$/;" g -ProofRequired src/status.rs /^ ProofRequired = 4,$/;" e enum:AuthenticationFailure -ProxyError src/status.rs /^ ProxyError = 3,$/;" e enum:TemporaryFailure -RateLimit src/status.rs /^ RateLimit = 4,$/;" e enum:TemporaryFailure -Redirect src/status.rs /^ Redirect(Redirect) = 30,$/;" e enum:Status -Redirect src/status.rs /^impl TryFrom for Redirect {$/;" c -Redirect src/status.rs /^pub enum Redirect {$/;" g -ServerUnavailable src/status.rs /^ ServerUnavailable = 1,$/;" e enum:TemporaryFailure -Status src/status.rs /^impl TryFrom for Status {$/;" c -Status src/status.rs /^pub enum Status {$/;" g -StatusError src/status.rs /^impl fmt::Display for StatusError {$/;" c -StatusError src/status.rs /^impl std::error::Error for StatusError {}$/;" c -StatusError src/status.rs /^pub struct StatusError;$/;" s -Success src/status.rs /^ Success = 20,$/;" e enum:Status -Temporary src/status.rs /^ Temporary = 0,$/;" e enum:Redirect -TemporaryError src/status.rs /^ TemporaryError = 0,$/;" e enum:TemporaryFailure -TemporaryFailure src/status.rs /^ TemporaryFailure(TemporaryFailure) = 40,$/;" e enum:Status -TemporaryFailure src/status.rs /^impl TryFrom for TemporaryFailure {$/;" c -TemporaryFailure src/status.rs /^pub enum TemporaryFailure {$/;" g -UnauthorizedSender src/status.rs /^ UnauthorizedSender = 1,$/;" e enum:AuthenticationFailure -add src/lib.rs /^pub fn add(left: usize, right: usize) -> usize {$/;" f -fmt src/status.rs /^ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {$/;" P implementation:StatusError -it_works src/lib.rs /^ fn it_works() {$/;" f module:tests -status src/lib.rs /^pub mod status;$/;" n -tests src/lib.rs /^mod tests {$/;" n -try_from src/status.rs /^ fn try_from(value: u8) -> Result {$/;" P implementation:AuthenticationFailure -try_from src/status.rs /^ fn try_from(value: u8) -> Result {$/;" P implementation:PermanentFailure -try_from src/status.rs /^ fn try_from(value: u8) -> Result {$/;" P implementation:Redirect -try_from src/status.rs /^ fn try_from(value: u8) -> Result {$/;" P implementation:Status -try_from src/status.rs /^ fn try_from(value: u8) -> Result {$/;" P implementation:TemporaryFailure