从函数中有效地返回 1-9 个字节
Efficiently returning 1-9 bytes from a function
至少有三种方法可以从函数中获取 return 个字节。
- 作为迭代器生成
u8
s.
- 以
Writer
作为参数。
- 接受
&mut [u8]
论点。
我的函数将在每次调用时生成 1-9 个字节。
我希望它易于使用且高效,以便:
- 提供消耗字节的迭代器管道。
- 写入磁盘。
- 写入网络。
- 写入内存。
我能否只实现该函数一次,并相信编译器会在用户调整输出时使单个实现对所有用例都有效?
或者我是否需要实施三次(或更多次)才能有效地涵盖所有用例?
让我们评估选项。
如果我们写一个接受&mut [u8]
的函数,我们想使用它:
- 要写入 disk/network(两者都是
std::io::Write
)- 我们可以创建一个类型为 [u8; 9]
的数组(因为它最多写入 9 个字节),将其传递给它,然后将其(更准确地说,是实际写入的部分)传递给 Write::write_all()
.
- 写入内存最简单:只需将切片传递给大小为
[u8; 9]
的数组即可。
- 如果我们想将其送入迭代器管道,我们将需要一些样板文件:
let bytes = [0; 9];
let written = foo(&mut bytes);
bytes.into_iter().take(written).some_iterator_chain()
// Or
bytes[..written].iter().copied().some_iterator_chain()
但编译器可能会优化这两种方式以获得非常高效的汇编。
如果我们写一个接受std::io::Write
的迭代器,那么写入disk/network会很容易,我们甚至可以使用[=]写入内存26=],但通过迭代器将其管道化将需要与上述相同的样板。总的来说,无论您选择写入 &mut [u8]
还是写入实现 Write
.
的类型都几乎没有关系
然而,如果我们 return 一个迭代器,我们可以很容易地将它放在一个迭代器链中,使用 for
循环写入内存也很容易,但是要写入 network/disk,您将不得不多次调用 write()
(或 write_all()
),这通常比一次调用效率低,或者将其收集到 Vec
中,这也是效率较低的。所以这可能是更糟糕的选择。
至少有三种方法可以从函数中获取 return 个字节。
- 作为迭代器生成
u8
s. - 以
Writer
作为参数。 - 接受
&mut [u8]
论点。
我的函数将在每次调用时生成 1-9 个字节。
我希望它易于使用且高效,以便:
- 提供消耗字节的迭代器管道。
- 写入磁盘。
- 写入网络。
- 写入内存。
我能否只实现该函数一次,并相信编译器会在用户调整输出时使单个实现对所有用例都有效?
或者我是否需要实施三次(或更多次)才能有效地涵盖所有用例?
让我们评估选项。
如果我们写一个接受&mut [u8]
的函数,我们想使用它:
- 要写入 disk/network(两者都是
std::io::Write
)- 我们可以创建一个类型为[u8; 9]
的数组(因为它最多写入 9 个字节),将其传递给它,然后将其(更准确地说,是实际写入的部分)传递给Write::write_all()
. - 写入内存最简单:只需将切片传递给大小为
[u8; 9]
的数组即可。 - 如果我们想将其送入迭代器管道,我们将需要一些样板文件:
let bytes = [0; 9];
let written = foo(&mut bytes);
bytes.into_iter().take(written).some_iterator_chain()
// Or
bytes[..written].iter().copied().some_iterator_chain()
但编译器可能会优化这两种方式以获得非常高效的汇编。
如果我们写一个接受std::io::Write
的迭代器,那么写入disk/network会很容易,我们甚至可以使用[=]写入内存26=],但通过迭代器将其管道化将需要与上述相同的样板。总的来说,无论您选择写入 &mut [u8]
还是写入实现 Write
.
然而,如果我们 return 一个迭代器,我们可以很容易地将它放在一个迭代器链中,使用 for
循环写入内存也很容易,但是要写入 network/disk,您将不得不多次调用 write()
(或 write_all()
),这通常比一次调用效率低,或者将其收集到 Vec
中,这也是效率较低的。所以这可能是更糟糕的选择。