library LibBytes {
  using LibBytes for bytes;

  /***********************************|
  |        Pop Bytes Functions        |
  |__________________________________*/

  /**
   * @dev Pops the last byte off of a byte array by modifying its length.
   * @param b Byte array that will be modified.
   * @return result The byte that was popped off.
   */
  function popLastByte(bytes memory b)
    internal
    pure
    returns (bytes1 result)
  {
    require(
      b.length > 0,
      "LibBytes#popLastByte: greater than zero length required"
    );

    // Store last byte.
    result = b[b.length - 1];

    assembly {
      // Decrement length of byte array.
      let newLen := sub(mload(b), 1)
      mstore(b, newLen)
    }
    return result;
  }

  /// @dev Reads an address from a position in a byte array.
  /// @param b Byte array containing an address.
  /// @param index Index in byte array of address.
  /// @return result address from byte array.
  function readAddress(
    bytes memory b,
    uint256 index
  )
    internal
    pure
    returns (address result)
  {
    require(
      b.length >= index + 20,  // 20 is length of address
      "LibBytes#readAddress greater or equal to 20 length required"
    );

    // Add offset to index:
    // 1. Arrays are prefixed by 32-byte length parameter (add 32 to index)
    // 2. Account for size difference between address length and 32-byte storage word (subtract 12 from index)
    index += 20;

    // Read address from array memory
    assembly {
      // 1. Add index to address of bytes array
      // 2. Load 32-byte word from memory
      // 3. Apply 20-byte mask to obtain address
      result := and(mload(add(b, index)), 0xffffffffffffffffffffffffffffffffffffffff)
    }
    return result;
  }

  /***********************************|
  |        Read Bytes Functions       |
  |__________________________________*/

  /**
   * @dev Reads a bytes32 value from a position in a byte array.
   * @param b Byte array containing a bytes32 value.
   * @param index Index in byte array of bytes32 value.
   * @return result bytes32 value from byte array.
   */
  function readBytes32(
    bytes memory b,
    uint256 index
  )
    internal
    pure
    returns (bytes32 result)
  {
    require(
      b.length >= index + 32,
      "LibBytes#readBytes32 greater or equal to 32 length required"
    );

    // Arrays are prefixed by a 256 bit length parameter
    index += 32;

    // Read the bytes32 from array memory
    assembly {
      result := mload(add(b, index))
    }
    return result;
  }

  /// @dev Reads an unpadded bytes4 value from a position in a byte array.
  /// @param b Byte array containing a bytes4 value.
  /// @param index Index in byte array of bytes4 value.
  /// @return result bytes4 value from byte array.
  function readBytes4(
    bytes memory b,
    uint256 index
  )
    internal
    pure
    returns (bytes4 result)
  {
    require(
      b.length >= index + 4,
      "LibBytes#readBytes4 greater or equal to 4 length required"
    );

    // Arrays are prefixed by a 32 byte length field
    index += 32;

    // Read the bytes4 from array memory
    assembly {
      result := mload(add(b, index))
      // Solidity does not require us to clean the trailing bytes.
      // We do it anyway
      result := and(result, 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000)
    }
    return result;
  }

  function readBytes2(
    bytes memory b,
    uint256 index
  )
    internal
    pure
    returns (bytes2 result)
  {
    require(
      b.length >= index + 2,
      "LibBytes#readBytes2 greater or equal to 2 length required"
    );

    // Arrays are prefixed by a 32 byte length field
    index += 32;

    // Read the bytes4 from array memory
    assembly {
      result := mload(add(b, index))
      // Solidity does not require us to clean the trailing bytes.
      // We do it anyway
      result := and(result, 0xFFFF000000000000000000000000000000000000000000000000000000000000)
    }
    return result;
  }
}
function readBytes32(
  bytes memory b,
  uint256 index
)
  internal
  pure
  returns (bytes32 result)
{
  require(
    b.length >= index + 32,
    "LibBytes#readBytes32 greater or equal to 32 length required"
  );

  // Arrays are prefixed by a 256 bit length parameter
  index += 32;

  // Read the bytes32 from array memory
  assembly {
    result := mload(add(b, index))
  }
  return result;
}

/**
 * @dev Reads a bytes32 value from a position in a byte array.
 * @param b Byte array containing a bytes32 value.
 * @param index Index in byte array of bytes32 value.
 * @return result bytes32 value from byte array.
 */