Skip to content

Commit

Permalink
chore: Migrate to devdocs (#25)
Browse files Browse the repository at this point in the history
* migrate to devdoc

* doc globs

* nit: fmt

* module doc
  • Loading branch information
jtriley2p authored Dec 3, 2024
1 parent ddb4cdc commit 9831aac
Show file tree
Hide file tree
Showing 3 changed files with 214 additions and 39 deletions.
100 changes: 91 additions & 9 deletions src/decoder.nr
Original file line number Diff line number Diff line change
@@ -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: [
Expand Down Expand Up @@ -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: [
Expand Down Expand Up @@ -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<let InputElements: u32, let OutputBytes: u32>(
self,
input: [u8; InputElements],
Expand Down
120 changes: 107 additions & 13 deletions src/encoder.nr
Original file line number Diff line number Diff line change
@@ -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)
Expand All @@ -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: [
Expand All @@ -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<let InputElements: u32>(
self,
input: [u8; InputElements],
Expand All @@ -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<let InputBytes: u32, let OutputElements: u32>(
self,
input: [u8; InputBytes],
Expand Down
33 changes: 16 additions & 17 deletions src/lib.nr
Original file line number Diff line number Diff line change
@@ -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,
Expand Down

0 comments on commit 9831aac

Please sign in to comment.