library Base64 {
  bytes internal constant TABLE =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

  /// @notice Encodes some bytes to the base64 representation
  function encode(bytes memory data) internal pure returns (string memory) {
    uint256 len = data.length;
    if (len == 0) return "";

    // multiply by 4/3 rounded up
    uint256 encodedLen = 4 * ((len + 2) / 3);

    // Add some extra buffer at the end
    bytes memory result = new bytes(encodedLen + 32);

    bytes memory table = TABLE;

    assembly {
      let tablePtr := add(table, 1)
      let resultPtr := add(result, 32)

      for {
        let i := 0
      } lt(i, len) {

      } {
        i := add(i, 3)
        let input := and(mload(add(data, i)), 0xffffff)

        let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))
        out := shl(8, out)
        out := add(
          out,
          and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF)
        )
        out := shl(8, out)
        out := add(
          out,
          and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF)
        )
        out := shl(8, out)
        out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))
        out := shl(224, out)

        mstore(resultPtr, out)

        resultPtr := add(resultPtr, 4)
      }

      switch mod(len, 3)
      case 1 {
        mstore(sub(resultPtr, 2), shl(240, 0x3d3d))
      }
      case 2 {
        mstore(sub(resultPtr, 1), shl(248, 0x3d))
      }

      mstore(result, encodedLen)
    }

    return string(result);
  }
}
/// [MIT License]
/// @title Base64
/// @notice Provides a function for encoding some bytes in base64
/// @author Brecht Devos <brecht@loopring.org>
function encode(bytes memory data) internal pure returns (string memory) {
  uint256 len = data.length;
  if (len == 0) return "";

  // multiply by 4/3 rounded up
  uint256 encodedLen = 4 * ((len + 2) / 3);

  // Add some extra buffer at the end
  bytes memory result = new bytes(encodedLen + 32);

  bytes memory table = TABLE;

  assembly {
    let tablePtr := add(table, 1)
    let resultPtr := add(result, 32)

    for {
      let i := 0
    } lt(i, len) {

    } {
      i := add(i, 3)
      let input := and(mload(add(data, i)), 0xffffff)

      let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))
      out := shl(8, out)
      out := add(
        out,
        and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF)
      )
      out := shl(8, out)
      out := add(
        out,
        and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF)
      )
      out := shl(8, out)
      out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))
      out := shl(224, out)

      mstore(resultPtr, out)

      resultPtr := add(resultPtr, 4)
    }

    switch mod(len, 3)
    case 1 {
      mstore(sub(resultPtr, 2), shl(240, 0x3d3d))
    }
    case 2 {
      mstore(sub(resultPtr, 1), shl(248, 0x3d))
    }

    mstore(result, encodedLen)
  }

  return string(result);
}

/// @notice Encodes some bytes to the base64 representation