開発

[binllion] 編集用バッファに上書き機能を追加する

またもや少し時間が空いてしまいました。どこまで実装が進んだのか忘れてしまっていたのですがいよいよエディターの根本的な部分、編集機能を作り込んでいきたいと思います。

先を見越して編集用バッファであるBinDataには既にupdate()が実装されており、値の入力があれば上書きできるようにしてあります。

つまり、キーボードからの入力受取 -> 16進数に変換 -> BinDataのupdate()で上書き、という流れで上書きができそうです。

キーボードからの入力受取

数値の入力を受け付けるために、数値キーのイベントを処理できるようにEventHandlerをアップデートします。

            // 数値データ入力
            KeyCode::Char(char_code @ ('0'..='9' | 'a'..='f' | 'A'..='F')) => {
                self.input_buf.add(char_code);
                let res = self.input_buf.to_hex();
                if let Ok(val) = res.into() {
                    let index = message.cursor().index();
                    message.bin_data_mut().update(index, val);
                    message.cursor_mut().input_buf_x(self.input_buf.index());
                }
            }Code language: PHP (php)

ここので見慣れないのはchar_code @ ('0'..='9' | 'a'..='f' | 'A'..='F')の部分でしょうか。

これは@束縛という書き方でマッチガードと変数への束縛を組み合わせたような書き方です。これで16進数に使う00-FFの入力を受けた時に編集処理に進むようにしています。

入力は2桁になる可能性があるので入力用のミニバッファinput_bufへ一旦値を追加します。

なにも入力がなくてaddされた場合は最初の入力となり、2桁目の値として扱われます。既にaddが実行されていて2桁目の値がある場合に再びaddされた場合は1桁目の値として扱われます。

このようなちょっと複雑な処理になるのでInputBufとして新しい構造体とメソッドを実装しています。

// 入力用ミニバッファ
#[derive(Debug)]
struct InputBuf {
    buf: [char; 2],
    index: usize,
}

use std::num::ParseIntError;
impl InputBuf {
    fn new() -> Self {
        // let mut buf : [char; 2] = Default::default();
        let mut buf: [char; 2] = ['0'; 2];
        let mut index = 0;
        Self { buf, index }
    }

    // バッファにキーボードからの入力を入れる
    fn add(&mut self, value: char) {
        self.buf[self.index] = value;
        self.index = (self.index + 1) % 2;
    }

    // バッファの内容を16進数へ変換
    fn to_hex(&self) -> Result<u8, ParseIntError> {
        let str: String = self.buf.iter().collect();
        let res = u8::from_str_radix(&str, 16);
        // if let Ok(str) = &res {
        //     dbg!(format!("{:X}", str));
        // }
        res
    }

    // バッファに値をセット
    fn set_value(&mut self, value: u8) {
        // 16進数へ変換
        let mut str = format!("{:02X}", value);

        self.index = 0;
        for x in str.chars() {
            self.add(x);
        }
        self.index = 0;
    }

    fn index(&self) -> usize {
        self.index
    }
}
Code language: PHP (php)

16進数に変換

charの配列を一旦Stringに変換して、Stringからu8へu8::from_str_radix()を使うことで16進数へ変換しています。その部分はto_hex()になります。

set_value()は逆の処理でu8からcharの配列に変換しています。ちょっとネーミングが悪いですね。self.index = 0も2回目はいらないでしょう。

indexは2桁目と1桁目のどちらのポジションになるのか管理するためのものです。表示カーソルの位置決めにも使用しています。

BinDataのupdate()で上書き

to_hex()で変換した結果、成功なら上書きを実行するようにします。

つまり、if let Ok(val) = res.into()にマッチした場合に上書きを実行します。

res.into()のinto()が意味不明なので後で修正しておきます。

CursorPositionにinput_buf_x()を新たに追加しています。先程のindexによりカーソルの位置をずらすためのものになります。

            // 数値データ入力
            KeyCode::Char(char_code @ ('0'..='9' | 'a'..='f' | 'A'..='F')) => {
                self.input_buf.add(char_code);
                let res = self.input_buf.to_hex();
                if let Ok(val) = res.into() {
                    let index = message.cursor().index();
                    message.bin_data_mut().update(index, val);
                    message.cursor_mut().input_buf_x(self.input_buf.index());
                }
            }Code language: PHP (php)

GitHubにコードをアップロードしています。0.1.0バージョン

コードのコメントに書かれているfirst_stepなどをcargoコマンドに渡すと実行できます。

# Example
$ cargo run --example first_stepCode language: Bash (bash)

管理人

Recent Posts

情報セキュリティマネジメント試験取得への道

スキルアップを図るべく情報セキ…

2か月 ago

ファイナンシャルプランナー3級試験取得への道

スキルアップを図るべくファイナ…

2か月 ago

[rust] New Type Patternを使ってみる

DDDの考えを取り入れることで…

5か月 ago

RustでDDDの要素を取り入れてみる

前回SOLID原則というものを…

5か月 ago

期間限定!書籍無料キャンペーン2025

「mdBookではじめるKin…

5か月 ago