<commit_before>package com.yubico.authenticator.data.oath

import com.yubico.yubikit.oath.Code
import com.yubico.yubikit.oath.Credential
import com.yubico.yubikit.oath.OathSession
import com.yubico.yubikit.oath.OathType
import java.nio.ByteBuffer
import kotlin.experimental.and

/**
 * Returns true if this credential is considered to be Steam credential
 */
fun Credential.isSteamCredential(): Boolean =
    issuer == "Steam" && oathType == OathType.TOTP

/**
 * @return Code with value formatted for use with Steam
 * @param credential credential that will get new Steam code
 * @param timestamp the timestamp which is used for TOTP calculation
 * @throws IllegalArgumentException in case when the credential is not a Steam credential
 */
fun OathSession.calculateSteamCode(
    credential: Credential,
    timestamp: Long = 0,
): Code {
    val timeSlotMs = 30_000
    if (!credential.isSteamCredential()) {
        throw IllegalArgumentException("This is not steam credential")
    }

    val currentTimeSlot = timestamp / timeSlotMs

    return Code(
        calculateResponse(credential.id, currentTimeSlot.toByteArray()).formatAsSteam(),
        currentTimeSlot * timeSlotMs,
        (currentTimeSlot + 1) * timeSlotMs
    )
}

private fun ByteArray.formatAsSteam(): String {
    val steamCharTable = "23456789BCDFGHJKMNPQRTVWXY"
    val charTableLen = steamCharTable.length
    val offset = this[this.size - 1].and(0x0f).toInt()
    var number = ByteBuffer.wrap(this, offset, 4).int.and(0x7fffffff)
    return String(CharArray(5) {
        steamCharTable[number % charTableLen].also { number /= charTableLen }
    })
}<commit_msg>use and in infix notation for bitwise operations<commit_after>package com.yubico.authenticator.data.oath

import com.yubico.yubikit.oath.Code
import com.yubico.yubikit.oath.Credential
import com.yubico.yubikit.oath.OathSession
import com.yubico.yubikit.oath.OathType
import java.nio.ByteBuffer
import kotlin.experimental.and

/**
 * Returns true if this credential is considered to be Steam credential
 */
fun Credential.isSteamCredential(): Boolean =
    issuer == "Steam" && oathType == OathType.TOTP

/**
 * @return Code with value formatted for use with Steam
 * @param credential credential that will get new Steam code
 * @param timestamp the timestamp which is used for TOTP calculation
 * @throws IllegalArgumentException in case when the credential is not a Steam credential
 */
fun OathSession.calculateSteamCode(
    credential: Credential,
    timestamp: Long = 0,
): Code {
    val timeSlotMs = 30_000
    if (!credential.isSteamCredential()) {
        throw IllegalArgumentException("This is not steam credential")
    }

    val currentTimeSlot = timestamp / timeSlotMs

    return Code(
        calculateResponse(credential.id, currentTimeSlot.toByteArray()).formatAsSteam(),
        currentTimeSlot * timeSlotMs,
        (currentTimeSlot + 1) * timeSlotMs
    )
}

private fun ByteArray.formatAsSteam(): String {
    val steamCharTable = "23456789BCDFGHJKMNPQRTVWXY"
    val charTableLen = steamCharTable.length
    val offset = (this[this.size - 1] and 0x0f).toInt()
    var number = ByteBuffer.wrap(this, offset, 4).int and 0x7fffffff
    return String(CharArray(5) {
        steamCharTable[number % charTableLen].also { number /= charTableLen }
    })
}
{'fraction_non_alphanumeric': 0.09000302023557838, 'fraction_numerical': 0.013289036544850499, 'mean_word_length': 3.9879518072289155, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5220659', 'n_tokens_mistral': 1065, 'n_tokens_neox': 1021, 'n_words': 269}