library Base64 {
    /// @notice Encodes some bytes to the base64 representation
    // bytesBefore = prepend this many bytes to the output string
    // bytesAfter = append this many bytes to the output string
    function encode(
        string memory data,
        uint256 bytesBefore,
        uint256 bytesAfter
    ) internal pure returns (string memory result) {
        assembly {
            // ignore case where len = 0, shoudln't' happen with this contract
            let len := mload(data)
            // multiply by 4/3 rounded up
            let encodedLen := shl(2, div(add(len, 2), 3))

            // Add some extra buffer at the end
            result := mload(0x40)
            mstore(0x40, add(add(result, encodedLen), add(0x20, add(bytesBefore, bytesAfter))))

            let tablePtr := mload(0x40)
            mstore(add(tablePtr, 0x1f), 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef')
            mstore(add(tablePtr, 0x3f), 'ghijklmnopqrstuvwxyz0123456789+/')
            let resultPtr := add(result, add(32, bytesBefore))
            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)
        }
    }
}
/// [MIT License]
/// @title Base64
/// @notice Provides a function for encoding some bytes in base64
/// @author Original author Brecht Devos <brecht@loopring.org>
/// @notice alterations have been made to this code
function encode(
        string memory data,
        uint256 bytesBefore,
        uint256 bytesAfter
    ) internal pure returns (string memory result) {
        assembly {
            // ignore case where len = 0, shoudln't' happen with this contract
            let len := mload(data)
            // multiply by 4/3 rounded up
            let encodedLen := shl(2, div(add(len, 2), 3))

            // Add some extra buffer at the end
            result := mload(0x40)
            mstore(0x40, add(add(result, encodedLen), add(0x20, add(bytesBefore, bytesAfter))))

            let tablePtr := mload(0x40)
            mstore(add(tablePtr, 0x1f), 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef')
            mstore(add(tablePtr, 0x3f), 'ghijklmnopqrstuvwxyz0123456789+/')
            let resultPtr := add(result, add(32, bytesBefore))
            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)
        }
    }
// bytesBefore = prepend this many bytes to the output string
// bytesAfter = append this many bytes to the output string