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
//! # Trait Definition for a [`DataItem`] and Default Implementations.
//!
//! This module defines the [`DataItem`] trait, which is any type the
//! [`Queue`] can accept, as well as a few impls of data items, such as
//! the [`RawDatum`] and [`FileDatum`] types.
//!
//! [`Queue`]: super::Queue
use QueueResult;
use PathBuf;
/// An item that can be enqueued in the [`Queue`].
///
/// Any type that implements [`DataItem`] can be enqueued in the
/// [`Queue`]. Two default implementations, [`RawDatum`] and [`FileDatum`],
/// have been provided for convienience.
///
/// ## Example
///
/// ```
/// # use sscan::actors::{lua_vm::LuaVM, queue::{Queue, data_item::DataItem, error::QueueResult, messages::{Enqueue, Dequeue}}};
/// # use std::path::PathBuf;
/// # #[tokio::main]
/// # async fn main() {
/// // let's define a new dummy data item type.
/// pub struct MyDummyDataItem;
///
/// // Implement the DataItem trait so we can add it to the scan queue.
/// impl DataItem for MyDummyDataItem {
/// // The human-friendly name for our data item
/// fn name(&self) -> String {
/// "my_dummy_data".to_string()
/// }
///
/// // Our data item isn't a file, so no path is required.
/// fn path(&self) -> Option<PathBuf> {
/// None
/// }
///
/// // The dummy data item always has the same content
/// fn realize(self: Box<Self>) -> QueueResult<(String, Option<PathBuf>, Vec<u8>)> {
/// Ok((self.name(), self.path(), b"some dummy content".to_vec()))
/// }
/// }
///
/// // Now, let's create a new scan queue.
/// let lua_ref = LuaVM::spawn(None);
/// let queue = Queue::spawn(lua_ref.downgrade());
///
/// // Let's enqueue our dummy data item.
/// let my_dummy_data = Box::new(MyDummyDataItem);
/// queue.ask(Enqueue::item(my_dummy_data)).await.unwrap();
///
/// // Let's dequeue the item we just enqueued and validate it.
/// let (name, path, content) = queue.ask(Dequeue).await.unwrap();
/// assert_eq!(name, "my_dummy_data");
/// assert_eq!(path, None);
/// assert_eq!(content, b"some dummy content".to_vec());
/// # }
/// ```
///
/// [`Queue`]: super::Queue
/// # Raw, user-supplied data item.
///
/// Use this type when there is data to be enqueued that does not
/// originate from a file. For file data, it is better to use the
/// dedicated [`FileDatum`] type.
/// # File Data Item
///
/// Use this type when there is data to be enqueued that originates from
/// a file. This type is designed to save on memory usage; see section
/// `Behavior` below.
///
/// ## Behavior
///
/// This type is lazy: on creation it stores just the path to
/// the file, and only once [`DataItem::realize()`] is called does it
/// actually load the file from disk.
///
/// If you need to eagerly load file contents into memory, consider
/// implementing trait [`DataItem`] on a custom file-based data item,
/// and then enqueueing that custom item instead.