cannot borrow data in a `&` reference as mutable
共通鍵関連で、DES暗号化をRustで実装しているんですが、そのときにちょっとハマりかけたのでメモ。
fn main() {
let mut src = "abc".to_string();
let mut s = src.as_bytes();
println!("{:08b}", &s[0]);
set_bit(&mut s, 0);
println!("↓");
println!("{:08b}", &s[0]);
}
fn set_bit(bytes: &mut [u8], bit: usize) {
bytes[bit / 8 as usize] |= 0x80 >> (bit % 8);
}
処理自体は単純で、文字列をbyte配列に変換後、指定されたビットを立てるような感じです。
ただ、このソースをコンパイルしようとすると、下記のようなエラーが発生します。
error[E0596]: cannot borrow data in a `&` reference as mutable
--> src/main.rs:8:13
|
8 | set_bit(&mut s, 0);
| ^^^^^^ cannot borrow as mutable
原因
as_bytes()の定義を確認すると、
pub const fn as_bytes(&self) -> &[u8]
as_bytes()
の返り値はバイト配列への不変参照になるので、それを可変な変数に格納しても、 set_bit()
でバイト配列には可変アクセスできないのでした。
解決策
今回の場合、unsafeなas_bytes_mut()を使用することで、バイト配列への可変参照を取得できます。
最終的には下記のようなソースにすることで、コンパイルが通ります。
fn main() {
let mut src = "abc".to_string();
let mut s = unsafe { src.as_bytes_mut() };
println!("{:08b}", &s[0]);
set_bit(&mut s, 0);
println!("↓");
println!("{:08b}", &s[0]);
}
fn set_bit(bytes: &mut [u8], bit: usize) {
bytes[bit / 8 as usize] |= 0x80 >> (bit % 8);
}
出力結果:
01100001
↓
11100001
まとめ
Rustを書き始めたときはちんぷんかんぷんでしたが、最近はメモリの状態を意識しながら書くことに慣れてきました。こういうしょうもないエラーもたまにやってしまいますが、トラブルシューティングはかなりスムーズにできるようになってきた気がします。