diff --git a/src/decoder.nr b/src/decoder.nr index fdeab15..36774b3 100644 --- a/src/decoder.nr +++ b/src/decoder.nr @@ -1,19 +1,48 @@ use super::defaults::BASE64_PADDING_CHAR; +/// Standard Base64 Alphabet (base64) with padding. pub global STANDARD: Base64DecodeBE = Base64DecodeBE::new(true); + +/// Standard Base64 Alphabet (base64) without padding. pub global STANDARD_NO_PAD: Base64DecodeBE = Base64DecodeBE::new(false); + +/// URL and Filename Safe Alphabet without padding. pub global URL_SAFE: Base64DecodeBE = Base64DecodeBE::base64url(false); + +/// URL and Filename Safe Alphabet with padding. pub global URL_SAFE_WITH_PAD: Base64DecodeBE = Base64DecodeBE::base64url(true); +/// Invalid value for the lookup table. global INVALID_VALUE: u8 = 255; + +/// Base64 decoder for big-endian byte arrays. +/// +/// > Note: If the lookup table is not defined in a struct, access costs are expensive and ROM +/// tables aren't being used. struct Base64DecodeBE { - // for some reason, if the lookup table is not defined in a struct, access costs are expensive and ROM tables aren't being used :/ + /// The base64 lookup table. table: [u8; 256], + /// Whether the input has padding. pad: bool, } + impl Base64DecodeBE { /// Creates a new decoder that uses the standard Base64 Alphabet (base64) specified in RFC 4648 - /// https://datatracker.ietf.org/doc/html/rfc4648#section-4 + /// (https://datatracker.ietf.org/doc/html/rfc4648#section-4). + /// + /// ## Value Parameters + /// + /// - `pad`: Whether the input has padding. + /// + /// ## Returns + /// + /// The Base64 decoder instance. + /// + /// ## Usage + /// + /// ```nr + /// let decoder = Base64DecodeBE::new(true); + /// ``` fn new(pad: bool) -> Self { Base64DecodeBE { table: [ @@ -280,8 +309,22 @@ impl Base64DecodeBE { } } - // Creates a new decoder that uses the URL and Filename Safe Alphabet specified in RFC 4648 - // https://datatracker.ietf.org/doc/html/rfc4648#section-5 + /// Creates a new decoder that uses the URL and Filename Safe Alphabet specified in RFC 4648 + /// (https://datatracker.ietf.org/doc/html/rfc4648#section-5). + /// + /// ## Value Parameters + /// + /// - `pad`: Whether the input has padding. + /// + /// ## Returns + /// + /// The Base64 decoder instance. + /// + /// ## Usage + /// + /// ```nr + /// let decoder = Base64DecodeBE::base64url(true); + /// ``` fn base64url(pad: bool) -> Self { Base64DecodeBE { table: [ @@ -548,15 +591,54 @@ impl Base64DecodeBE { } } + /// Gets the lookup table value at a given index. + /// + /// ## Value Parameters + /// + /// - `idx`: The index to get the value for. + /// + /// ## Returns + /// + /// The value from the lookup table. + /// + /// ## Usage + /// + /// ```nr + /// let value = Base64DecodeBE::new(true).get(65); + /// ``` fn get(self, idx: Field) -> u8 { self.table[idx] } - /** - * @brief Take an array of ASCII values and convert into *packed* byte array of base64 values - * Each Base64 value is 6 bits. This method will produce a byte array where data is concatenated so that there are no sparse bits - * (e.g. encoding 4 ASCII values produces 24 bits of Base64 data = 3 bytes of output data) - **/ + /// Converts an array of ASCII values into a packed byte array of base64 values. + /// + /// > Note: Each Base64 value is 6 bits. This method will produce a byte array where data is + /// > concatenated so that there are no sparse bits (e.g. encoding 4 ASCII values produces 24 + /// > bits of Base64 data = 3 bytes of output data). + /// + /// ## Type Parameters + /// + /// - `InputElements`: The number of input elements. + /// - `OutputBytes`: The number of output bytes. + /// + /// ## Value Parameters + /// + /// - `self`: The Base64 decoder instance. + /// - `input`: The input array. + /// + /// ## Constraints + /// + /// - input and output lengths are correct, including padding. + /// + /// ## Returns + /// + /// The packed byte array of base64 values. + /// + /// ## Usage + /// + /// ```nr + /// let result = Decoder::new(false).decode::<4, 3>([65, 66, 67, 68]); + /// ``` pub fn decode( self, input: [u8; InputElements], diff --git a/src/encoder.nr b/src/encoder.nr index 3a070aa..1c445f6 100644 --- a/src/encoder.nr +++ b/src/encoder.nr @@ -1,24 +1,50 @@ use super::defaults::BASE64_PADDING_CHAR; +/// Standard base64 encoder with padding. pub global STANDARD: Base64EncodeBE = Base64EncodeBE::new(true); + +/// Standard base64 encoder without padding. pub global STANDARD_NO_PAD: Base64EncodeBE = Base64EncodeBE::new(false); + +/// URL and Filename Safe base64 encoder without padding. pub global URL_SAFE: Base64EncodeBE = Base64EncodeBE::base64url(false); + +/// URL and Filename Safe base64 encoder with padding. pub global URL_SAFE_WITH_PAD: Base64EncodeBE = Base64EncodeBE::base64url(true); +/// Base 64 encoder for big-endian byte arrays. +/// +/// > Note: If the lookup table is not defined in a struct, access costs are expensive and ROM +/// > tables aren't being used. struct Base64EncodeBE { - // for some reason, if the lookup table is not defined in a struct, access costs are expensive and ROM tables aren't being used :/ + /// The base64 lookup table. table: [u8; 64], + /// Whether to pad the output with '=' characters. pad: bool, } impl Base64EncodeBE { /// Creates a new encoder that uses the standard Base64 Alphabet (base64) specified in RFC 4648 - /// (https://datatracker.ietf.org/doc/html/rfc4648#section-4) + /// (https://datatracker.ietf.org/doc/html/rfc4648#section-4). + /// + /// The alphabet values are standard UTF-8 (and ASCII) byte encodings so the index in the table + /// is the 6-bit Base64 value, and the value at that index is the UTF-8 encoding of that value. + /// + /// ## Value Parameters + /// + /// - `pad`: Whether to pad the output with '=' characters. + /// + /// ## Returns + /// + /// The Base64 encoder instance. + /// + /// ## Usage + /// + /// ```nr + /// let encoder = Base64EncodeBE::new(true); + /// ``` fn new(pad: bool) -> Self { Base64EncodeBE { - // The alphabet values here are standard UTF-8 (and ASCII) byte encodings, so the index - // in the table is the 6-bit Base64 value, and the value at that index is the UTF-8 - // encoding of that value. table: [ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, // 0-25 (A-Z) @@ -32,8 +58,22 @@ impl Base64EncodeBE { } } - // Creates a new encoder that uses the URL and Filename Safe Alphabet specified in RFC 4648 - // https://datatracker.ietf.org/doc/html/rfc4648#section-5 + /// Creates a new encoder that uses the URL and Filename Safe Alphabet specified in RFC 4648 + /// (https://datatracker.ietf.org/doc/html/rfc4648#section-5). + /// + /// ## Value Parameters + /// + /// - `pad`: Whether to pad the output with '=' characters. + /// + /// ## Returns + /// + /// The Base64 encoder instance. + /// + /// ## Usage + /// + /// ```nr + /// let encoder = Base64EncodeBE::base64url(true); + /// ``` fn base64url(pad: bool) -> Self { Base64EncodeBE { table: [ @@ -50,13 +90,45 @@ impl Base64EncodeBE { } } + /// Gets the lookup table value at a given index. + /// + /// ## Value Parameters + /// + /// - `idx`: The index in the lookup table. + /// + /// ## Returns + /// + /// The byte value from the lookup table. + /// + /// ## Usage + /// + /// ```nr + /// let encoder = Base64EncodeBE::new(true); + /// ``` fn get(self, idx: Field) -> u8 { self.table[idx] } - /** - * @brief Take an array of ASCII values and convert into base64 values - **/ + /// Converts an array of ASCII values into base64 values. + /// + /// ## Type Parameters + /// + /// - `InputElements`: The number of elements in the input array. + /// + /// ## Value Parameters + /// + /// - `self`: The Base64 encoder instance. + /// - `input`: The input array of ASCII values. + /// + /// ## Returns + /// + /// The array of base64 values. + /// + /// ## Usage + /// + /// ```nr + /// let encoded = Base64EncodeBE::new(true).encode_elements("asdf".as_bytes()); + /// ``` fn encode_elements( self, input: [u8; InputElements], @@ -69,9 +141,31 @@ impl Base64EncodeBE { result } - /** - * @brief Take an array of packed base64 encoded bytes and convert into ASCII - **/ + /// Converts an array of packed base64 values into ASCII values. + /// + /// ## Type Parameters + /// + /// - `InputElements`: The number of elements in the input array. + /// - `OutputElements`: The number of elements in the output array. + /// + /// ## Value Parameters + /// + /// - `self`: The Base64 encoder instance. + /// - `input`: The input array of packed base64 values. + /// + /// ## Constraints + /// + /// - input and output lengths are correct, including padding. + /// + /// ## Returns + /// + /// The array of ASCII values. + /// + /// ## Usage + /// + /// ```nr + /// let decoded = Base64EncodeBE::new(true).encode("asdf".as_bytes()); + /// ``` pub fn encode( self, input: [u8; InputBytes], diff --git a/src/lib.nr b/src/lib.nr index aaf1c9e..7a4644f 100644 --- a/src/lib.nr +++ b/src/lib.nr @@ -1,20 +1,19 @@ -// Encodings use the alphabets and padding rules specified in RFC 4648 -// (https://datatracker.ietf.org/doc/html/rfc4648: -// -// A 65-character subset of US-ASCII is used, enabling 6 bits to be -// represented per printable character. (The extra 65th character, "=", -// is used to signify a special processing function.) -// -// The encoding process represents 24-bit groups of input bits as output -// strings of 4 encoded characters. Proceeding from left to right, a -// 24-bit input group is formed by concatenating 3 8-bit input groups. -// These 24 bits are then treated as 4 concatenated 6-bit groups, each -// of which is translated into a single character in the base 64 -// alphabet. -// -// Each 6-bit group is used as an index into an array of 64 printable -// characters. The character referenced by the index is placed in the -// output string. +//! Base64 Encoder and Decoder +//! +//! Encodings use the alphabets and padding rules specified in RFC-4648 +//! (https://datatracker.ietf.org/doc/html/rfc4648): +//! +//! A 65-character subset of US-ASCII is used, enabling 6 bits to be represented per printable +//! character. (The extra 65th character, "=", is used to signify a special processing function.) +//! +//! The encoding process represents 24-bit groups of input bits as output strings of 4 encoded +//! characters. Proceeding from left to right, a 24-bit input group is formed by concatenating 3 +//! 8-bit input groups. These 24 bits are then treated as 4 concatenated 6-bit groups, each of which +//! is translated into a single character in the base 64 alphabet. +//! +//! Each 6-bit group is used as an index into an array of 64 printable characters. The character +//! referenced by the index is placed in the output string. + mod encoder; pub use encoder::{ STANDARD as BASE64_ENCODER, STANDARD_NO_PAD as BASE64_NO_PAD_ENCODER,