Я преобразовал файл в байты и получил vec/массив
[68, 114, 97, 109, 97, 116, 105, 99, 32, 115, 97, 120, 97, 112, 104, 111, 110, 101, 32, 112, 108, 97, 121, 115, 32, 73, 78, 32, 84, 72, 69, 32, 68, 73, 83, 84, 65, 78, 67, 69]
Когда я объединил это, у меня получился номер 4920555689216983877.
Теперь моя проблема заключается в том, что всякий раз, когда я пытаюсь преобразовать это число обратно в байты, у меня остаются только 8 конечных байтов.
Я тестировал это как с крейтом Rust по умолчанию, так и с крейтом BigInt, и ни один из них меня не удовлетворил:
use num_bigint::{BigUint, ToBigUint};
use num_traits::{Zero, One, ToPrimitive, ToBytes, Num};
fn main() {
let the_u8: u128 = 4920555689216983877;
let bigone = (4920555689216983877 as u128).to_biguint().expect("might fail");
let the_u8bytes: [u8;16] = the_u8.to_be_bytes(); //Using a simple array for demonstrated purposes
let bigonebytes: Vec<u8> = bigone.to_be_bytes();
println!("Bytes of base u8: {:?}", the_u8bytes);
println!("Base of BigInt: {:?}", bigonebytes);
}
[dependencies]
num-bigint = "0.4.4"
num-traits = "0.2.18"
По какой-то причине я не могу собрать исходный файл, который является неотъемлемой частью моей программы, но мне кажется, что я выполнил все логические шаги по обратному проектированию этого упрощенного процесса. Может ли кто-нибудь объяснить, что именно происходит не так, и помочь мне сформулировать стратегию противодействия этому?
Раньше я задавал аналогичный вопрос, но у меня не было лучшего минимального воспроизводимого примера, теперь, когда я попытался создать отдельный проект, чтобы попытаться воспроизвести свои проблемы, я столкнулся с аналогичным затруднительным положением.
Это функция, которую я использовал для создания единственного числа для представления всех байтов в десятичном формате:
fn concatenate_bytes(bytes: &[u8]) -> BigUint {
println!("Bytes: {:?}", bytes);
let mut result = 0;
let mut raw_dog = bytes.as_ptr();
for _ in bytes.iter() {
unsafe{
result = (result << 8) | (*raw_dog as u64);
raw_dog = raw_dog.offset(1);
}
}
println!("Result: {}", result);
result.to_biguint().expect("Failed to create uint")
//Is actually valid ??? ^
}
Многие комментарии были сделаны лично для меня, но я понимаю, что они не особенно полезны для вас.
4920555689216983877
для его представления требуется всего 8 байт, поэтому размещение его в типе u128 или bigint не приведет к созданию байтов, если их нет.
«Когда я соединил это, я получил число…» — вам придется подробнее объяснить, как это работает, потому что оказывается, что, несмотря на то, что вы получили это число, оно представляет только последние восемь байтов ваших данных.
@kmdreko Я использовал функцию, которая объединяла все байты в единственное целое число, а затем использовал хэш-карту для преобразования этого единственного целого числа в другую базу. Я знаю, что я преобразовал число из отдельной базы обратно в исходную базу, как только я перевернул хэш-карту, повторил процесс еще раз и в итоге получил то же число, с которым я исходил.
Почему люди используют unsafe
там, где это совершенно не нужно?
@ChayimFriedman, моя идея говорит, что это небезопасно, поэтому я использовал небезопасный блок, Rust Analyzer сказал мне, что это так.
Ну да, но вы можете просто использовать (безопасный) итератор. И этим вам даже удалось вызвать UB. Держитесь подальше от небезопасных, как новичок.
Я бы, честно говоря, не хотел сразу переходить к переполнению стека, поэтому использовал Chat Gpt, чтобы помочь себе, но когда я дошел до определенного момента, я попал в ловушку кода, который написал ранее. Я не осознавал, что нажимал байты, поэтому осталось только 8 байтов. Я некоторое время возился с Rust и делал это небезопасно, когда некоторое время назад создавал простое ядро, но я предположил, что моя первоначальная ошибка заключалась в записи байтов, а не в том, как я их объединял. Я заметил, что моя программа работала только с меньшими значениями, но теперь я вижу, что есть безопасный итератор, который я мог бы использовать в BigUInt.
Первоначально я использовал обычный u32-u128, прежде чем перешел к использованию больших целых чисел и num_traits.
Ваша функция concatenate_bytes
теряет информацию. Переменная result
является u64
, что означает, что она будет содержать только до 8 байт информации. Если вы поместите в него байт, а затем << 8
еще восемь раз, то этот байт «вытолкнется» из результата. Таким образом, result
в конечном итоге отражает только последние 8 байтов.
Если вы используете функцию, которая сохраняет все байты в BigUint
, например from_bytes_be
, то из исходных данных вы получите такое число:
use num_bigint::BigUint;
let bytes = &[68, 114, 97, 109, 97, 116, 105, 99, 32, 115, 97, 120, 97, 112, 104, 111, 110, 101, 32, 112, 108, 97, 121, 115, 32, 73, 78, 32, 84, 72, 69, 32, 68, 73, 83, 84, 65, 78, 67, 69];
let biguint = BigUint::from_bytes_be(bytes);
println!("{biguint}");
571099513965487418103312191225646346334778926396615879607986731592501905638024494155407303787333
Загрузка этого числа как BigUint
и использование to_bytes_be
вернет исходные байты.
Спасибо, я не осознавал, что активно терял информацию, не конвертируя файл в бигуинт. Я бы использовал его позже в своей программе при объединении байтов, но теперь я вижу, что при объединении байтов я теряю информацию. Когда сегодня я пересмотрю свою программу, я посмотрю, работает ли эта версия лучше.
Я также хотел бы сказать спасибо за то, что вы помогли мне дважды подряд.
I ended up with the number 4920555689216983877
... вы уверены, что тип данных — число?