public static void write(BsonWriter writer, Object value) {
        switch (value) {
            // double
            case BsonDouble val -> writer.writeDouble(val.doubleValue());
            case Float val -> writer.writeDouble(val);
            case Double val -> writer.writeDouble(val);
            // string
            case BsonString val -> writer.writeString(val.getValue());
            case String val -> writer.writeString(val);
            // document
            case BsonDocument val -> {
                writer.writeStartDocument();
                for (Map.Entry<String, BsonValue> entry : val.entrySet()) {
                    writer.writeName(entry.getKey());
                    write(writer, entry.getValue());
                }
                writer.writeEndDocument();
            }
            case Map<?, ?> val -> {
                writer.writeStartDocument();
                for (Map.Entry<?, ?> entry : val.entrySet()) {
                    writer.writeName(entry.getKey()
                            .toString());
                    write(writer, entry.getValue());
                }
                writer.writeEndDocument();
            }
            // array
            case BsonArray val -> {
                writer.writeStartArray();
                for (BsonValue v : val) {
                    write(writer, v);
                }
                writer.writeEndArray();
            }
            case Collection<?> val -> {
                writer.writeStartArray();
                for (Object v : val) {
                    write(writer, v);
                }
                writer.writeEndArray();
            }
            // binary
            case BsonBinary val -> writer.writeBinaryData(val);
            case byte[] val -> writer.writeBinaryData(new BsonBinary(val));
            // undefined
            case BsonUndefined ignored -> writer.writeUndefined();
            // object id
            case ObjectId val -> writer.writeObjectId(val);
            // bool
            case BsonBoolean val -> writer.writeBoolean(val.getValue());
            case Boolean val -> writer.writeBoolean(val);
            // date time
            case BsonDateTime val -> writer.writeDateTime(val.getValue());
            case Date val -> writer.writeDateTime(val.getTime());
            // null
            case BsonNull ignored -> writer.writeNull();
            case null -> writer.writeNull();
            // regular expression
            case BsonRegularExpression val -> writer.writeRegularExpression(val);
            case Pattern val ->
                writer.writeRegularExpression(new BsonRegularExpression(val.pattern()));
            // javascript
            case BsonJavaScript val -> writer.writeJavaScript(val.getCode());
            // int32
            case BsonInt32 val -> writer.writeInt32(val.getValue());
            case Integer val -> writer.writeInt32(val);
            // timestamp
            case BsonTimestamp val -> writer.writeTimestamp(val);
            // int64
            case BsonInt64 val -> writer.writeInt64(val.getValue());
            case Long val -> writer.writeInt64(val);
            // decimal128
            case BsonDecimal128 val -> writer.writeDecimal128(val.getValue());
            case Decimal128 val -> writer.writeDecimal128(val);
            // min key
            case BsonMinKey ignored -> writer.writeMinKey();
            // max key
            case BsonMaxKey ignored -> writer.writeMaxKey();
            default -> {
                if (value.getClass()
                        .isArray()) {
                    int length = Array.getLength(value);
                    writer.writeStartArray();
                    for (int i = 0; i < length; i++) {
                        write(writer, Array.get(value, i));
                    }
                    writer.writeEndArray();
                    return;
                }
                throw new IllegalArgumentException(
                        "Unsupported value: "
                                + value);
            }
        }
    }
TODO: unify the logic of {@link #encode} and {@link #write}
turms-server-common/src/main/java/im/turms/server/common/storage/mongo/codec/CodecUtil.java