glassy 0.0.3

An easy and fast library for encoding and decoding binary data.
Documentation
//! Base32 encoding and decoding.
//!
//! This module implements RFC 4648 sections 6 and 7.  The basic idea is to
//! convert every five bits of binary data into a printable character.  This
//! results in a 5:8 size ratio, an overhead of 60%.
//!
//! The basic algorithm for Base32-encoding data is:
//! 1. Interpret the sequence of bytes as a sequence of bits (within each byte,
//!    bits are ordered from most to least significant).
//! 2. Append zero bits until the number of bits is divisible by 5.
//! 3. Interpret the sequence of bits as a sequence of 5-bit indices (the bits
//!    in the sequence are ordered from most to least significant).
//! 4. Replace each 5-bit index with a 1-byte character from the table below.
//! 5. Optionally, append padding characters until the number of characters is
//!    divisible by 8.
//!
//! The basic algorithm for Base32-decoding data is:
//! 1. Append padding bytes until the number of characters is divisible by 8.
//! 2. Form groups of 8 consecutive characters in the sequence.
//! 3. Determine the number of output bytes in each 8-character group, based on
//!    the number of padding characters at the end of the group, based on the
//!    table below.
//! 4. Replace each character with a 5-bit index from the table below (padding
//!    bytes are interpreted as indices with value 0).
//! 5. Interpret the sequence of groups of 8 5-bit indices as a sequence of
//!    40-bit strings (the bits in each index are ordered from most to least
//!    significant).
//! 6. Interpret the sequence of 40-bit strings as a sequence of groups of 5
//!    8-bit bytes (the bits in the sequence are ordered from most to least
//!    significant).
//! 7. Truncate each group of 5 bytes to the number of actual output bytes,
//!    based on the value computed at step 3.
//! 8. Interpret the sequence of groups of bytes as a sequence of bytes.
//!
//! The following table relates, within the encoding of up to 5 bytes of binary
//! data or the decoding of 8 characters, the number of padding bytes at the end
//! of the encoded data to the number of bytes in the decoded data:
//!
//! ```text
//! Amount of Padding | 0 1 2 3 4 5 6 7 8
//! Non-Padding Bytes | 8 7 6 5 4 3 2 1 0
//!        Input Size | 5 4   3 2   1   0
//! ```
//!
//! All blank entries represent invalid combinations.
//!
//! The following table relates 5-bit indices to printable characters, for the
//! RFC 6468 section 6 encoding `base32`:
//!
//! ```text
//! Bin   Dec Hex  | Hex ASCII
//! 00000   0   0  |  41 A
//! 00001   1   1  |  42 B
//! 00010   2   2  |  43 C
//! 00011   3   3  |  44 D
//! 00100   4   4  |  45 E
//! 00101   5   5  |  46 F
//! 00110   6   6  |  47 G
//! 00111   7   7  |  48 H
//! 01000   8   8  |  49 I
//! 01001   9   9  |  4A J
//! 01010  10   A  |  4B K
//! 01011  11   B  |  4C L
//! 01100  12   C  |  4D M
//! 01101  13   D  |  4E N
//! 01110  14   E  |  4F O
//! 01111  15   F  |  50 P
//! 10000  16  10  |  51 Q
//! 10001  17  11  |  52 R
//! 10010  18  12  |  53 S
//! 10011  19  13  |  54 T
//! 10100  20  14  |  55 U
//! 10101  21  15  |  56 V
//! 10110  22  16  |  57 W
//! 10111  23  17  |  58 X
//! 11000  24  18  |  59 Y
//! 11001  25  19  |  5A Z
//! 11010  26  1A  |  32 2
//! 11011  27  1B  |  33 3
//! 11100  28  1C  |  34 4
//! 11101  29  1D  |  35 5
//! 11110  30  1E  |  36 6
//! 11111  31  1F  |  37 7
//! ```
//!
//! The character `=` (hex `3D`) is used for padding.
//!
//! The following table relates 5-bit indices to printable characters, for the
//! RFC 6468 section 7 encoding `base32hex`:
//!
//! ```text
//!  Bin  Dec Hex  | Hex Character
//! 00000   0   0  |  30 0
//! 00001   1   1  |  31 1
//! 00010   2   2  |  32 2
//! 00011   3   3  |  33 3
//! 00100   4   4  |  34 4
//! 00101   5   5  |  35 5
//! 00110   6   6  |  36 6
//! 00111   7   7  |  37 7
//! 01000   8   8  |  38 8
//! 01001   9   9  |  39 9
//! 01010  10   A  |  41 A
//! 01011  11   B  |  42 B
//! 01100  12   C  |  43 C
//! 01101  13   D  |  44 D
//! 01110  14   E  |  45 E
//! 01111  15   F  |  46 F
//! 10000  16  10  |  47 G
//! 10001  17  11  |  48 H
//! 10010  18  12  |  49 I
//! 10011  19  13  |  4A J
//! 10100  20  14  |  4B K
//! 10101  21  15  |  4C L
//! 10110  22  16  |  4D M
//! 10111  23  17  |  4E N
//! 11000  24  18  |  4F O
//! 11001  25  19  |  50 P
//! 11010  26  1A  |  51 Q
//! 11011  27  1B  |  52 R
//! 11100  28  1C  |  53 S
//! 11101  29  1D  |  54 T
//! 11110  30  1E  |  55 U
//! 11111  31  1F  |  56 V
//! ```
//!
//! The character `=` (hex `3D`) is used for padding.

use core::fmt;

pub mod generic;

/// The specific Base32 format to use.
#[derive(Clone, Debug)]
pub enum Format {
    /// The `base32` format defined by RFC 4648 section 6.
    Base32 {
        /// Whether the encoder should output padding bytes.
        encode_padding: bool,

        /// Whether the decoder accepts padding bytes.
        decode_padding: bool,

        /// Whether the decoder ignores garbage characters.
        decode_garbage: bool,
    },

    /// The `base32hex` format defined by RFC 4648 section 7.
    Base32Hex {
        /// Whether the encoder should output padding bytes.
        encode_padding: bool,

        /// Whether the decoder accepts padding bytes.
        decode_padding: bool,

        /// Whether the decoder ignores garbage characters.
        decode_garbage: bool,
    },
}

impl Format {
    /// Whether to encode padding or not.
    ///
    /// If this returns [`true`], then padding bytes will be inserted at the end
    /// of the encoding process so that the complete encoded string's byte size
    /// is a multiple of 8.
    pub fn encode_padding(&self) -> bool {
        match self {
            Self::Base32 { encode_padding, .. }
          | Self::Base32Hex { encode_padding, .. }
            => *encode_padding,
        }
    }

    /// Whether to decode padding or not.
    ///
    /// If this returns [`true`], then padding bytes in the input will be parsed
    /// correctly.
    pub fn decode_padding(&self) -> bool {
        match self {
            Self::Base32 { decode_padding, .. }
          | Self::Base32Hex { decode_padding, .. }
            => *decode_padding,
        }
    }

    /// Whether to decode garbage or not.
    ///
    /// If this returns [`true`], then 'garbage' bytes in the input (those that
    /// could not have been produced by the encoder) will be ignored rather than
    /// causing errors.
    pub fn decode_garbage(&self) -> bool {
        match self {
            Self::Base32 { decode_garbage, .. }
          | Self::Base32Hex { decode_garbage, .. }
            => *decode_garbage,
        }
    }
}

/// A decoding error.
#[derive(Clone, Debug)]
pub struct DecodeError;

impl fmt::Display for DecodeError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str("A malformed input was received")
    }
}