That fuck shit the fascists are using
1package org.tm.archive.util;
2
3import androidx.annotation.NonNull;
4
5import org.tm.archive.recipients.Recipient;
6
7import java.math.BigInteger;
8import java.nio.ByteBuffer;
9import java.nio.ByteOrder;
10import java.security.MessageDigest;
11import java.security.NoSuchAlgorithmException;
12import java.util.Arrays;
13import java.util.UUID;
14
15/**
16 * Logic to bucket a user for a given feature flag based on their UUID.
17 */
18public final class BucketingUtil {
19
20 private BucketingUtil() {}
21
22 /**
23 * Calculate a user bucket for a given feature flag, uuid, and part per modulus.
24 *
25 * @param key Feature flag key (e.g., "research.megaphone.1")
26 * @param uuid Current user's UUID (see {@link Recipient#getServiceId()})
27 * @param modulus Drives the bucketing parts per N (e.g., passing 1,000,000 indicates bucketing into parts per million)
28 */
29 public static long bucket(@NonNull String key, @NonNull UUID uuid, long modulus) {
30 MessageDigest digest;
31 try {
32 digest = MessageDigest.getInstance("SHA-256");
33 } catch (NoSuchAlgorithmException e) {
34 throw new AssertionError(e);
35 }
36
37 digest.update(key.getBytes());
38 digest.update(".".getBytes());
39
40 ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[16]);
41 byteBuffer.order(ByteOrder.BIG_ENDIAN);
42 byteBuffer.putLong(uuid.getMostSignificantBits());
43 byteBuffer.putLong(uuid.getLeastSignificantBits());
44
45 digest.update(byteBuffer.array());
46
47 return new BigInteger(Arrays.copyOfRange(digest.digest(), 0, 8)).mod(BigInteger.valueOf(modulus)).longValue();
48 }
49}