From 34f2a5e12d3687f02ee5632a1b48b7417664658d Mon Sep 17 00:00:00 2001 From: ARCJ137442 <61109168+ARCJ137442@users.noreply.github.com> Date: Wed, 3 Apr 2024 14:39:25 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20:recycle:=20=E5=B0=86=E3=80=8C?= =?UTF-8?q?=E8=AF=BB=E5=8F=96=E8=A1=8C=E8=BF=AD=E4=BB=A3=E5=99=A8=E3=80=8D?= =?UTF-8?q?=E4=B8=8E=E3=80=8CNAVM=E8=BE=93=E5=87=BA=E7=BC=93=E5=AD=98?= =?UTF-8?q?=E3=80=8D=E5=86=85=E7=BD=AE=E8=BF=9B=E3=80=8C=E5=91=BD=E4=BB=A4?= =?UTF-8?q?=E8=A1=8C=E6=94=AF=E6=8C=81/=E8=BE=93=E5=85=A5=E8=BE=93?= =?UTF-8?q?=E5=87=BA=E3=80=8D=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/bin/babelnar_cli/runtime_manage.rs | 109 ++---------------------- src/cli_support/io/mod.rs | 7 ++ src/cli_support/io/navm_output_cache.rs | 94 ++++++++++++++++++++ src/cli_support/io/readline_iter.rs | 52 +++++++++++ 6 files changed, 160 insertions(+), 106 deletions(-) create mode 100644 src/cli_support/io/navm_output_cache.rs create mode 100644 src/cli_support/io/readline_iter.rs diff --git a/Cargo.lock b/Cargo.lock index f3b8480..dde25af 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -73,7 +73,7 @@ checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "babel_nar" -version = "0.13.0" +version = "0.13.1" dependencies = [ "anyhow", "clap", diff --git a/Cargo.toml b/Cargo.toml index 83be4c7..4c35312 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "babel_nar" -version = "0.13.0" +version = "0.13.1" edition = "2021" # Cargo文档参考: diff --git a/src/bin/babelnar_cli/runtime_manage.rs b/src/bin/babelnar_cli/runtime_manage.rs index 6afcc37..dd376d6 100644 --- a/src/bin/babelnar_cli/runtime_manage.rs +++ b/src/bin/babelnar_cli/runtime_manage.rs @@ -3,125 +3,26 @@ use crate::{launch_by_config, InputMode, LaunchConfig, LaunchConfigPreludeNAL}; use anyhow::{anyhow, Result}; use babel_nar::{ - cli_support::error_handling_boost::error_anyhow, + cli_support::{ + error_handling_boost::error_anyhow, + io::{navm_output_cache::OutputCache, readline_iter::ReadlineIter}, + }, eprintln_cli, println_cli, test_tools::{nal_format::parse, put_nal, VmOutputCache}, }; use nar_dev_utils::{if_return, ResultBoost}; use navm::{ cmd::Cmd, - output::Output, vm::{VmRuntime, VmStatus}, }; use std::{ fmt::Debug, - io::Result as IoResult, ops::{ControlFlow, ControlFlow::Break, ControlFlow::Continue}, - sync::{Arc, Mutex, MutexGuard}, + sync::{Arc, Mutex}, thread::{self, sleep, JoinHandle}, time::Duration, }; -/// 读取行迭代器 -/// * 🚩每迭代一次,请求用户输入一行 -/// * ✨自动清空缓冲区 -/// * ❌无法在【不复制字符串】的情况下实现「迭代出所输入内容」的功能 -/// * ❌【2024-04-02 03:49:56】无论如何都无法实现:迭代器物件中引入就必须碰生命周期 -/// * 🚩最终仍需复制字符串:调用处方便使用 -/// * ❓是否需要支持提示词 -#[derive(Debug, Clone, Default, PartialEq, Eq)] -pub struct ReadlineIter { - pub buffer: String, -} - -/// 实现迭代器 -impl Iterator for ReadlineIter { - type Item = IoResult; - - fn next(&mut self) -> Option { - // 清空缓冲区 - self.buffer.clear(); - // 读取一行 - // * 📝此处的`stdin`是懒加载的 - if let Err(e) = std::io::stdin().read_line(&mut self.buffer) { - return Some(Err(e)); - } - // 返回 - Some(IoResult::Ok(self.buffer.clone())) - } -} - -/// 线程间可变引用计数的别名 -type ArcMutex = Arc>; - -/// 输出缓存 -/// * 🎯统一「加入输出⇒打印输出」的逻辑 -/// * 🚩仅封装一个[`Vec`],而不对其附加任何[`Arc`]、[`Mutex`]的限定 -/// * ❌【2024-04-03 01:43:13】[`Arc`]必须留给[`RuntimeManager`]:需要对其中键的值进行引用 -#[derive(Debug)] -pub struct OutputCache { - /// 内部封装的输出数组 - /// * 🚩【2024-04-03 01:43:41】不附带任何包装类型,仅包装其自身 - inner: Vec, -} - -/// 功能实现 -impl OutputCache { - /// 构造函数 - pub fn new(inner: Vec) -> Self { - Self { inner } - } - - /// 默认[`Arc`]<[`Mutex`]> - pub fn default_arc_mutex() -> ArcMutex { - Arc::new(Mutex::new(Self::default())) - } - - /// 从[`Arc`]<[`Mutex`]>中解锁 - pub fn unlock_arc_mutex(arc_mutex: &mut ArcMutex) -> Result> { - arc_mutex.lock().transform_err(error_anyhow) - } -} - -/// 默认构造:空数组 -impl Default for OutputCache { - fn default() -> Self { - Self::new(vec![]) - } -} - -/// 实现「输出缓存」 -/// * 不再涉及任何[`Arc`]或[`Mutex`] -impl VmOutputCache for OutputCache { - /// 存入输出 - /// * 🎯统一的「打印输出」逻辑 - /// * 🚩【2024-04-03 01:07:55】不打算封装了 - fn put(&mut self, output: Output) -> Result<()> { - // 尝试打印输出 - println_cli!(&output); - - // 加入输出 - self.inner.push(output); - Ok(()) - } - - /// 遍历输出 - /// * 🚩不是返回迭代器,而是用闭包开始计算 - fn for_each(&self, f: impl Fn(&Output) -> ControlFlow) -> Result> { - // 遍历 - for output in self.inner.iter() { - // 基于控制流的运行 - match f(output) { - ControlFlow::Break(value) => return Ok(Some(value)), - ControlFlow::Continue(()) => {} - } - } - - // 返回 - Ok(None) - } -} - /// 运行时管理器 /// * 🎯在一个数据结构中封装「虚拟机运行时」与「配置信息」 /// * 📌只负责**单个运行时**的运行管理 diff --git a/src/cli_support/io/mod.rs b/src/cli_support/io/mod.rs index 1eb7e90..7a8d0d7 100644 --- a/src/cli_support/io/mod.rs +++ b/src/cli_support/io/mod.rs @@ -2,7 +2,14 @@ //! * ✨终端美化相关 //! + util::mods! { // 输出打印 pub output_print; + + // 读取行迭代器 + pub readline_iter; + + // NAVM输出缓存 + pub navm_output_cache; } diff --git a/src/cli_support/io/navm_output_cache.rs b/src/cli_support/io/navm_output_cache.rs new file mode 100644 index 0000000..fd47f36 --- /dev/null +++ b/src/cli_support/io/navm_output_cache.rs @@ -0,0 +1,94 @@ +//! NAVM输出缓存 +//! * 🎯一站式存储、展示与管理NAVM的输出 +//! * 🎯可被其它二进制库所复用 + +use crate::{cli_support::error_handling_boost::error_anyhow, test_tools::VmOutputCache}; +use anyhow::Result; +use nar_dev_utils::ResultBoost; +use navm::output::Output; +use std::{ + ops::ControlFlow, + sync::{Arc, Mutex, MutexGuard}, +}; + +use super::output_print::OutputType; + +/// 线程间可变引用计数的别名 +type ArcMutex = Arc>; + +/// 输出缓存 +/// * 🎯统一「加入输出⇒打印输出」的逻辑 +/// * 🚩仅封装一个[`Vec`],而不对其附加任何[`Arc`]、[`Mutex`]的限定 +/// * ❌【2024-04-03 01:43:13】[`Arc`]必须留给[`RuntimeManager`]:需要对其中键的值进行引用 +#[derive(Debug)] +pub struct OutputCache { + /// 内部封装的输出数组 + /// * 🚩【2024-04-03 01:43:41】不附带任何包装类型,仅包装其自身 + inner: Vec, +} + +/// 功能实现 +impl OutputCache { + /// 构造函数 + pub fn new(inner: Vec) -> Self { + Self { inner } + } + + /// 默认[`Arc`]<[`Mutex`]> + pub fn default_arc_mutex() -> ArcMutex { + Arc::new(Mutex::new(Self::default())) + } + + /// 从[`Arc`]<[`Mutex`]>中解锁 + pub fn unlock_arc_mutex(arc_mutex: &mut ArcMutex) -> Result> { + arc_mutex.lock().transform_err(error_anyhow) + } + + /// 静默存入输出 + /// * 🎯内部可用的「静默存入输出」逻辑 + /// * 🚩【2024-04-03 01:07:55】不打算封装了 + pub fn put_silent(&mut self, output: Output) -> Result<()> { + // 加入输出 + self.inner.push(output); + Ok(()) + } +} + +/// 默认构造:空数组 +impl Default for OutputCache { + fn default() -> Self { + Self::new(vec![]) + } +} + +/// 实现「输出缓存」 +/// * 🚩【2024-04-03 14:33:50】不再涉及任何[`Arc`]或[`Mutex`] +impl VmOutputCache for OutputCache { + /// 存入输出 + /// * 🎯统一的「打印输出」逻辑 + /// * 🚩【2024-04-03 01:07:55】不打算封装了 + fn put(&mut self, output: Output) -> Result<()> { + // 打印输出 + // * 🚩现在内置入「命令行支持」,不再能直接使用`println_cli` + OutputType::print_from_navm_output(&output); + + // 静默加入输出 + self.put_silent(output) + } + + /// 遍历输出 + /// * 🚩不是返回迭代器,而是用闭包开始计算 + fn for_each(&self, f: impl Fn(&Output) -> ControlFlow) -> Result> { + // 遍历 + for output in self.inner.iter() { + // 基于控制流的运行 + match f(output) { + ControlFlow::Break(value) => return Ok(Some(value)), + ControlFlow::Continue(()) => {} + } + } + + // 返回 + Ok(None) + } +} diff --git a/src/cli_support/io/readline_iter.rs b/src/cli_support/io/readline_iter.rs new file mode 100644 index 0000000..16c54d9 --- /dev/null +++ b/src/cli_support/io/readline_iter.rs @@ -0,0 +1,52 @@ +//! 读取行迭代器 +//! * 🎯以迭代器的语法获取、处理用户输入 +//! * ❌【2024-04-03 14:28:02】放弃「泛型化改造」:[`Stdin`]能`read_line`,但却没实现[`std::io::BufRead`] + +use std::io::{stdin, Result as IoResult, Stdin}; + +/// 读取行迭代器 +/// * 🚩每迭代一次,请求用户输入一行 +/// * ✨自动清空缓冲区 +/// * ❌无法在【不复制字符串】的情况下实现「迭代出所输入内容」的功能 +/// * ❌【2024-04-02 03:49:56】无论如何都无法实现:迭代器物件中引入就必须碰生命周期 +/// * 🚩最终仍需复制字符串:调用处方便使用 +/// * ❓是否需要支持提示词 +#[derive(Debug)] +pub struct ReadlineIter { + /// 内置的「输入内容缓冲区」 + buffer: String, + /// 内置的「标准输入」 + stdin: Stdin, +} + +impl ReadlineIter { + pub fn new() -> Self { + Self { + buffer: String::new(), + stdin: stdin(), + } + } +} + +impl Default for ReadlineIter { + fn default() -> Self { + Self::new() + } +} + +/// 实现迭代器 +impl Iterator for ReadlineIter { + type Item = IoResult; + + fn next(&mut self) -> Option { + // 清空缓冲区 + self.buffer.clear(); + // 读取一行 + // * 📝`stdin()`是懒加载的,只会获取一次,随后返回的都是引用对象 + if let Err(e) = self.stdin.read_line(&mut self.buffer) { + return Some(Err(e)); + } + // 返回 + Some(IoResult::Ok(self.buffer.clone())) + } +}