Mapping (String line) { if (line.startsWith("#")) return null; String[] parts = line.split("\\s+"); if (parts.length != 3) return null; if (!parts[0].startsWith("U+")) return null; int codePoint = Integer.parseInt(parts[0].substring(2), 16); if (codePoint < PinyinMatcher.BASE_CODE_POINT) return null; // Codepoints outside BMP are not supported for now if (codePoint > 0xA000) return null; String[] readings; switch (parts[1]) { case "kMandarin" -> readings = new String[]{parts[2]}; case "kHanyuPinyin" -> { int colonPos = parts[2].indexOf(':'); if (colonPos == -1) return null; readings = parts[2].substring(colonPos + 1).split(","); } default -> { return null; } } long encoded = 0; for (String reading : readings) { char initial = Normalizer.normalize(reading, Normalizer.Form.NFKD).charAt(0); encoded |= 1L << (initial - 'a'); } return new Mapping(codePoint, encoded); }