Я использую некоторый API, который требует, чтобы входная строка была допустимой строкой UTF8 с максимальной длиной 4096 байт.
У меня была следующая функция для обрезки дополнительных символов:
private static string GetTelegramMessage(string message)
{
const int telegramMessageMaxLength = 4096; // https://core.telegram.org/method/messages.sendMessage#return-errors
const string tooLongMessageSuffix = "...";
if (message == null || message.Length <= 4096)
{
return message;
}
return message.Remove(telegramMessageMaxLength - tooLongMessageSuffix.Length) + tooLongMessageSuffix;
}
Это не сработало, потому что символы! = Байты и символы UTF16! = Символы UTF8.
Поэтому в основном мне нужно преобразовать строку C # UTF16
в строку UTF8
фиксированной длины.Я делаю
var bytes = Encoding.UTF8.GetBytes(myString);
// now I need to get first N characters with overall bytes size less than 4096 bytes
Я могу выразить свою потребность в Rust (рабочий пример ниже):
fn main() {
let foo = format!("{}{}", "ᚠᛇᚻ᛫ᛒᛦᚦ᛫ᚠᚱᚩᚠᚢᚱ᛫ᚠᛁᚱᚪ᛫ᚷᛖᚻᚹᛦᛚᚳᚢᛗ Uppen Sevarne staþe, sel þar him þuhte", (1..5000).map(|_| '1').collect::<String>());
println!("{}", foo.len());
let message = get_telegram_message(&foo);
println!("{}", message);
println!("{}", message.chars().count()); // 4035
println!("{}", message.len()); // 4096
}
pub fn get_telegram_message(foo: &str) -> String {
const PERIOD: &'static str = "...";
const MAX_LENGTH: usize = 4096;
let message_length = MAX_LENGTH - PERIOD.len();
foo.chars()
.map(|c| (c, c.len_utf8())) // getting length for evey char
.scan((0, '\0'), |(s, _), (c, size)| {
*s += size; // running total for all previosely seen characters
Some((*s, c))
})
.take_while(|(len, _)| len <= &message_length) // taking while running total is less than maximum message size
.map(|(_, c)| c)
.chain(PERIOD.chars()) // add trailing ellipsis
.collect() // building a string
}
https://play.rust -lang.org /? Version = stable & mode = debug & edition= 2018 & gist = 471ad0cbe9b0b01b50ec250d17dea233
Проблема здесь в том, что у меня нет chars()
итератора в C #, который позволяет мне обрабатывать последовательность байтов как символы UTF8.
Я игралс Encoding.UTF8
, но я не нашел подходящих API для выполнения этой задачи.
Связанные статьи как-то связаны с моим вопросом, но первый ответ очень плохой, второй переопределение UTF8итератор (это то, что я назвал IEnumerable<long>
ниже).Поскольку я знаю, как это реализовать, мой вопрос о встроенной функции для выполнения этой задачи, так что ни один из связанных ответов не отвечает на это.