1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
//! 模块:流式处理者列表
//! * 🎯用于流式处理物件,并在这其中灵活控制处理流程
//! * 📌组合式处理流程:多个处理者在一个处理函数中处理
//! * 📌截断式消耗过程:处理的物件可能会在中途被处理者消耗
//!
//! ? 【2024-03-23 14:45:53】是否需要整合进[`nar_dev_utils`]中去

use std::marker::PhantomData;

/// 枚举:处理结果
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum HandleResult<Item, HandlerIndex> {
    /// 物件通过了所有处理者,并最终返回
    Passed(Item),
    /// 物件在处理中途被消耗,指示「消耗了物件的处理者」
    Consumed(HandlerIndex),
}

/// 统一表示「输出处理者」
/// * 🎯简化类型表示
/// * 🚩【2024-04-08 21:04:47】因需进行线程共享,此闭包必须附带`Send`和`Sync`
pub type DynOutputHandler<Item> = dyn FnMut(Item) -> Option<Item> + Send + Sync;

/// 流式处理者列表
/// * 🚩处理者的特征约束:`FnMut(Item) -> Option<Item>`
/// * 📝不能显式声明「处理者」类型
///   * ❗若作为泛型参数,则意味着「需要统一所有类型」
///   * 📌而各个闭包彼此之间类型都是不同的
pub struct FlowHandlerList<Item> {
    /// 存储所有的处理者
    /// * 🚩使用[`Box`]以容纳不同类型的闭包
    handlers: Vec<Box<DynOutputHandler<Item>>>,

    /// 用于对未直接作为字段的`Item`类型的占位符
    /// * 🔗标准库文档:<https://rustwiki.org/zh-CN/std/marker/struct.PhantomData.html>
    _marker: PhantomData<Item>,
}

/// 实现调试呈现
impl<Item> std::fmt::Debug for FlowHandlerList<Item> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "FlowHandlerList(num={})", self.handlers.len())
    }
}

impl<Item> FlowHandlerList<Item> {
    /// 构造函数/从某个[`Box`]迭代器中构造
    /// * ℹ️若需构造一个空列表,可使用[`FlowHandlerList::default`]
    /// * 📝【2024-03-23 15:09:58】避免不了装箱:存储的是特征对象,不能不装箱就迭代
    /// * ❌【2024-03-23 15:31:48】停用:对参数`([Box::new(|x| Some(x)),],)`也无法使用
    ///   * 🚩已改用快捷构造宏
    pub fn new() -> Self {
        Self::from_vec(vec![])
    }

    /// 构造函数/直接从[`Vec`]构造
    /// * 需要自己手动装箱
    /// * ℹ️若需构造一个空列表,可使用[`FlowHandlerList::default`]
    pub fn from_vec(vec: Vec<Box<DynOutputHandler<Item>>>) -> Self {
        Self {
            handlers: vec,
            _marker: PhantomData,
        }
    }

    // 核心逻辑 //

    /// 【核心】处理
    /// * 🚩主要思路:不断让`Item`值通过各个处理者,直到「全部通过」或「有处理者消耗」
    /// * ⚙️返回值:全部通过后的物件 / 被消耗的处理者索引
    /// * 📝实际上也可不用额外的`let item`,直接使用传入所有权的参数变量
    pub fn handle(&mut self, mut item: Item) -> HandleResult<Item, usize> {
        // // 预置好物件变量
        // let mut item = item;
        // 逐个遍历处理者
        for (index, handler) in self.handlers.iter_mut().enumerate() {
            // 调用处理者处理物件,并对返回值做分支
            match handler(item) {
                // 有返回值⇒继续
                // ! 这里的返回值有可能已【不是】原来的那个了
                Some(new_item) => item = new_item,
                // 没返回值⇒报告处理者所在索引
                None => return HandleResult::Consumed(index),
            }
        }
        // 最终通过
        HandleResult::Passed(item)
    }

    // 对「处理者列表」的操作 //

    /// 获取某个位置的处理者(不可变)
    pub fn get_handler(&self, index: usize) -> Option<&DynOutputHandler<Item>> {
        // 获取指定位置的box,然后将其转为索引
        self.handlers.get(index).map(Box::as_ref)
    }

    // ! 【2024-03-23 15:16:08】废稿:可变引用的生命周期类型是【invariant】的
    // * 📝生命周期中`'self : 'handler`不代表`&mut 'self`
    // * 🔗参考:<https://doc.rust-lang.org/nomicon/subtyping.html>
    // /// 获取某个位置的处理者(可变)
    // /// * ℹ️[`Self::get_handler`]的可变引用版本
    // pub fn get_handler_mut(
    //     &mut self,
    //     index: usize,
    // ) -> Option<&mut DynOutputHandler<Item>> {
    //     self.handlers.get_mut(index).map(Box::as_mut)
    // }

    /// 添加新的处理者
    /// * ⚠️虽然结构体定义时无需对「处理者」类型约束为`'static`静态周期,
    ///   * 但此处传入作为参数(的函数指针)是需要的
    pub fn add_handler(
        &mut self,
        handler: impl FnMut(Item) -> Option<Item> + Send + Sync + 'static,
    ) {
        self.handlers.push(Box::new(handler))
    }
}

/// 默认构造函数:空数组
impl<Item> Default for FlowHandlerList<Item> {
    fn default() -> Self {
        Self::new()
    }
}

/// 快捷构造宏
#[macro_export]
macro_rules! flow_handler_list {
    [ $($handler:expr),* $(,)? ] => {
        // * ❌【2024-03-23 15:34:04】暂时不使用`$crate`:模块路径尚未固定
        FlowHandlerList::from_vec(
            vec![$(Box::new($handler)),*]
        )
    };
}

/// 单元测试
#[cfg(test)]
mod tests {
    use super::*;
    use util::*;
    use HandleResult::*;

    /// 基础功能测试
    #[test]
    fn test_flow_handler_list() {
        // * 📝`|x| Some(x)`可以直接使用构造函数调用,写成`Some`
        let handler1 = Some;
        let handler2 = |x| Some(x + 1);
        let handler3 = |x| if x > 1 { Some(x) } else { None };

        let mut list = FlowHandlerList::new();

        asserts! {
            // 第一个闭包
            list.add_handler(handler1) => (),
            list.handle(0) =>Passed(0),
            // 第二个闭包
            list.add_handler(handler2) => (),
            list.handle(0) => Passed(1),
            // 第三个闭包
            list.add_handler(handler3) => (),
            list.handle(0) => Consumed(2), // 被消耗,索引在最后一个
            list.handle(1) => Passed(2), // 通过
        }

        let mut list = flow_handler_list![
            Some,
            |x: usize| Some(x + 1),
            |x| Some(dbg!(x)),
            |x: usize| Some(x - 1),
        ];

        asserts! {
            list.handle(0) => Passed(0)
        }
    }

    /// 联动「NAVM输出」测试
    #[test]
    fn test_navm_output() {
        use narsese::conversion::string::impl_lexical::shortcuts::*;
        use navm::output::*;
        // 构造输出
        let answer = Output::ANSWER {
            content_raw: "<A --> B>.".into(),
            narsese: Some(nse!(<A --> B>.)), // * ✨直接使用新版快捷构造宏
        };
        let out = Output::OUT {
            content_raw: "<A --> C>".into(),
            narsese: Some(nse!(<A --> C>.)),
        };
        // 构造处理者列表
        let mut list = flow_handler_list![
            // 展示
            |out: Output| Some(dbg!(out)),
            // 截获回答
            |out| match out {
                Output::ANSWER {
                    content_raw,
                    narsese,
                } => {
                    println!("截获到回答:{content_raw:?} | {narsese:?}");
                    None
                }
                _ => Some(out),
            },
            // 展示
            |out| {
                println!("这是其它输出:{out:?}");
                Some(out)
            },
        ];
        // 测试处理
        asserts! {
            // 回答被截获
            list.handle(answer) => Consumed(1),
            // 其它被通过
            list.handle(out.clone()) => Passed(out),
        }
    }
}