Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Correct BinHex 4.0 alphabet according to specifications #271

Merged
merged 1 commit into from
Apr 30, 2024

Conversation

jobansd
Copy link
Contributor

@jobansd jobansd commented Apr 30, 2024

Description

This pull request addresses an inconsistency between the source code and the BinHex 4.0 specifications. Specifically, the variable BIN_HEX in alphabet.rs and corrects it to align with the specs.

Changes

pub const BIN_HEX: Alphabet = Alphabet::from_str_unchecked(
-    "!\"#$%&'()*+,-0123456789@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdehijklmpqr",
+    "!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr",
);

The new addition includes the character f and excludes the character 7, as per the spec.

References

Misc

#[cfg(test)]
mod tests {
    use base64::{
        alphabet::{self, Alphabet, ParseAlphabetError},
        engine::{self, GeneralPurposeConfig},
        Engine,
    };

    const BIN_HEX_NEW: Result<Alphabet, ParseAlphabetError> = alphabet::Alphabet::new(
        "!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr",
    );

    const ENGINE_CONFIG: GeneralPurposeConfig = engine::GeneralPurposeConfig::new()
        .with_decode_allow_trailing_bits(true)
        .with_encode_padding(false)
        .with_decode_padding_mode(engine::DecodePaddingMode::RequireNone);

    const SAMPLE_INPUT: &str = "Hello, world!";
    const EXPECTED_ENCODED_OUTPUT: &str = "5'9XE'mX)(G[FQaN)3";

    #[test]
    fn src_encode() {
        let engine_src = engine::GeneralPurpose::new(&alphabet::BIN_HEX, ENGINE_CONFIG);
        let res_enc = engine_src.encode(SAMPLE_INPUT);

        assert_eq!(res_enc, EXPECTED_ENCODED_OUTPUT);
    }

    #[test]
    fn src_decode() {
        let engine_src = engine::GeneralPurpose::new(&alphabet::BIN_HEX, ENGINE_CONFIG);
        let res_dec = engine_src.decode(EXPECTED_ENCODED_OUTPUT).unwrap();

        assert_eq!(res_dec, SAMPLE_INPUT.as_bytes());
    }

    #[test]
    fn new_encode() {
        let engine_new = engine::GeneralPurpose::new(&BIN_HEX_NEW.unwrap(), ENGINE_CONFIG);
        let res_enc = engine_new.encode(SAMPLE_INPUT);

        assert_eq!(res_enc, EXPECTED_ENCODED_OUTPUT);
    }

    #[test]
    fn new_decode() {
        let engine_new = engine::GeneralPurpose::new(&BIN_HEX_NEW.unwrap(), ENGINE_CONFIG);
        let res_dec = engine_new.decode(EXPECTED_ENCODED_OUTPUT).unwrap();

        assert_eq!(res_dec, SAMPLE_INPUT.as_bytes());
    }
}

Output

running 4 tests
test tests::new_encode ... ok
test tests::new_decode ... ok
test tests::src_decode ... FAILED
test tests::src_encode ... FAILED

failures:

---- tests::src_decode stdout ----
thread 'tests::src_decode' panicked at src\main.rs:34:9:
assertion `left == right` failed
  left: [72, 101, 173, 112, 111, 45, 32, 119, 176, 118, 124, 165, 33]
 right: [72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33]
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

---- tests::src_encode stdout ----
thread 'tests::src_encode' panicked at src\main.rs:26:9:
assertion `left == right` failed
  left: "5'8VD'mV)(FZEP`M)3"
 right: "5'9XE'mX)(G[FQaN)3"


failures:
    tests::src_decode
    tests::src_encode

test result: FAILED. 2 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

# Description

This pull request addresses an inconsistency between the source code and the [BinHex 4.0 specifications](https://files.stairways.com/other/binhex-40-specs-info.txt). Specifically, the variable `BIN_HEX` in [`alphabet.rs`](https://github.com/marshallpierce/rust-base64/blob/bf15ccf30af8bb6b1f326fffa025d7b0aaa3342f/src/alphabet.rs#L201C1-L206C3) and corrects it to align with the specs.

# Changes

```diff
pub const BIN_HEX: Alphabet = Alphabet::from_str_unchecked(
-    "!\"#$%&'()*+,-0123456789@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdehijklmpqr",
+    "!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr",
);
```

The new addition includes the character `f` and excludes the character `7`, as per the spec.

# References

- [BinHex 4.0 Definition](https://files.stairways.com/other/binhex-40-specs-info.txt)
- [RFC 1741 - MIME Content Type for BinHex Encoded Files](https://www.rfc-editor.org/rfc/rfc1741.txt)
- [MacMIME - How to send Macintosh files with MIME](https://www.iana.org/assignments/media-types/application/applefile)

# Misc

```rust
#[cfg(test)]
mod tests {
    use base64::{
        alphabet::{self, Alphabet, ParseAlphabetError},
        engine::{self, GeneralPurposeConfig},
        Engine,
    };

    const BIN_HEX_NEW: Result<Alphabet, ParseAlphabetError> = alphabet::Alphabet::new(
        "!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr",
    );

    const ENGINE_CONFIG: GeneralPurposeConfig = engine::GeneralPurposeConfig::new()
        .with_decode_allow_trailing_bits(true)
        .with_encode_padding(false)
        .with_decode_padding_mode(engine::DecodePaddingMode::RequireNone);

    const SAMPLE_INPUT: &str = "Hello, world!";
    const EXPECTED_ENCODED_OUTPUT: &str = "5'9XE'mX)(G[FQaN)3";

    #[test]
    fn src_encode() {
        let engine_src = engine::GeneralPurpose::new(&alphabet::BIN_HEX, ENGINE_CONFIG);
        let res_enc = engine_src.encode(SAMPLE_INPUT);

        assert_eq!(res_enc, EXPECTED_ENCODED_OUTPUT);
    }

    #[test]
    fn src_decode() {
        let engine_src = engine::GeneralPurpose::new(&alphabet::BIN_HEX, ENGINE_CONFIG);
        let res_dec = engine_src.decode(EXPECTED_ENCODED_OUTPUT).unwrap();

        assert_eq!(res_dec, SAMPLE_INPUT.as_bytes());
    }

    #[test]
    fn new_encode() {
        let engine_new = engine::GeneralPurpose::new(&BIN_HEX_NEW.unwrap(), ENGINE_CONFIG);
        let res_enc = engine_new.encode(SAMPLE_INPUT);

        assert_eq!(res_enc, EXPECTED_ENCODED_OUTPUT);
    }

    #[test]
    fn new_decode() {
        let engine_new = engine::GeneralPurpose::new(&BIN_HEX_NEW.unwrap(), ENGINE_CONFIG);
        let res_dec = engine_new.decode(EXPECTED_ENCODED_OUTPUT).unwrap();

        assert_eq!(res_dec, SAMPLE_INPUT.as_bytes());
    }
}
```

Output

```sh
running 4 tests
test tests::new_encode ... ok
test tests::new_decode ... ok
test tests::src_decode ... FAILED
test tests::src_encode ... FAILED

failures:

---- tests::src_decode stdout ----
thread 'tests::src_decode' panicked at src\main.rs:34:9:
assertion `left == right` failed
  left: [72, 101, 173, 112, 111, 45, 32, 119, 176, 118, 124, 165, 33]
 right: [72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33]
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

---- tests::src_encode stdout ----
thread 'tests::src_encode' panicked at src\main.rs:26:9:
assertion `left == right` failed
  left: "5'8VD'mV)(FZEP`M)3"
 right: "5'9XE'mX)(G[FQaN)3"


failures:
    tests::src_decode
    tests::src_encode

test result: FAILED. 2 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
```
@marshallpierce
Copy link
Owner

Thanks for the delightful PR!

@marshallpierce marshallpierce merged commit 64cca59 into marshallpierce:master Apr 30, 2024
5 checks passed
@marshallpierce
Copy link
Owner

Fix released in 0.22.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants