Rust 中的位元組序、API 設計和多型性 - Jimmy

banq發表於2021-11-25

我最近一直在做一個涉及位元組序(也稱為位元組順序)的序列化專案,它讓我探索了 Rust 標準庫中處理位元組序的部分,並分享了我對如何在程式設計中表示位元組序的想法語言及其標準庫,因為我認為這也是 Rust 比 C++ 做得更好的地方,並且也是一個很好的案例研究來討論 Rust 中的 API 設計和多型性。
 

Big End, Little End
當我第一次在 DOS 上學習使用DEBUG.EXE程式進行程式設計時,我第一次遇到了位元組序的概念。當一個16位值顯示為16位值時,它只是正常的十六進位制,但是當它顯示為兩個8位位元組時,顯示就發生了奇怪的事情。
這是一個演示效果的C++ 片段

template<typename T>
void display_bytes(const T &val) {
    char bytes[sizeof(T)];
    memcpy(bytes, &val, sizeof(T));
    for (auto byte : bytes) {
        printf("%2x ", byte);
    }
    printf("\n");
}

int main() {
    int value = 0x12345678;
    printf("%x\n", value);
    display_bytes(value);
}


當在任何小端Little End處理器(絕大多數處理器)上執行時,我們得到:

12345678
78 56 34 12

最低有效位元組在前,因此如果您按順序列印出各個位元組,則必須向後讀取它——儘管每個單獨的位元組仍然是向前的。
如果您在大端Big End,處理器上執行相同的程式碼,您將得到:

12345678
12 34 56 78


在這一點上,我理解的小位元組序是英特爾處理器出於我不理解的原因所做的一件奇怪的事情,這讓我在閱讀十六進位制轉儲時做了一些額外的工作。當時,這很好:我認為必須應用這些額外的奧術知識本身就很酷。而且,我認為小位元組序是做需要額外工作的事情的奇怪方式,而大位元組序是更自然的設計。直到很久以後,我才對這個觀點有了一些細微的差別。
看,我們用於數字的書寫系統是大端。我們不是將數字劃分為位元組(以 256 為基數),而是將其劃分為數字。我們認為頁面左側在頁面右側之前,我們首先寫入最高有效數字。這都是在小學明確教授的:

1234 = 1*10^3 + 2*10^2 + 3*10^1 + 4*10^0

。。。。。
 

位元組序何時相關?
在書寫數字時,數字沒有位元組序,同樣,一個位元組在處理器中是不可分割的。位元組由位組成,但在特殊指令之外,這些位的順序無關緊要。其中一個是最重要的,一個是最不重要的,但是除非我們為特殊指令索引它們,或者透過電線一個接一個地傳送它們,否則無法確定哪個位是“第一個”。
我認為談論(多位元組)字本身的位元組序沒有任何意義。單詞的位元組序只有在它被儲存為——並且可以作為——一系列位元組訪問時才起作用。
那麼從這個角度來看,與位元組序相關的操作是什麼?給定一個詞,它由哪一系列位元組組成?然後,給定一系列位元組,它是什麼詞?
在 Rust 的術語中,這些是to_be_bytes(對於大端)/ to_le_bytes(對於小)在一個方向,而from_be_bytes/from_le_bytes在另一個方向。
這些方法都捆綁在 Rust 文件中, 用於——在這種情況下——原始u32型別,以及ne處理器的本機位元組序。
。。
更多點選標題

相關文章