1use libipld::cache::Cache;
2use libipld::cache::IpldCache;
3use libipld::cbor::DagCbor;
4use libipld::cbor::DagCborCodec;
5use libipld::cid::Cid;
6use libipld::error::Result;
7use libipld::ipld::Ipld;
8use libipld::multihash::Code;
9use libipld::prelude::{Decode, Encode};
10use libipld::store::Store;
11use libipld::store::StoreParams;
12use libipld::DagCbor;
13
14#[derive(Clone, Debug, DagCbor)]
15pub enum Data<T: DagCbor> {
16 Value(T),
17 Link(Cid),
18}
19
20impl<T: DagCbor> Data<T> {
21 fn value(&self) -> Option<&T> {
22 if let Self::Value(value) = self {
23 Some(value)
24 } else {
25 None
26 }
27 }
28
29 fn cid(&self) -> Option<&Cid> {
30 if let Self::Link(cid) = self {
31 Some(cid)
32 } else {
33 None
34 }
35 }
36}
37
38#[derive(Clone, Debug, DagCbor)]
39pub struct Node<T: DagCbor> {
40 width: u32,
41 height: u32,
42 data: Vec<Data<T>>,
43}
44
45impl<T: DagCbor> Node<T> {
46 fn new(width: u32, height: u32, data: Vec<Data<T>>) -> Self {
47 Node {
48 width,
49 height,
50 data,
51 }
52 }
53
54 fn width(&self) -> usize {
55 self.width as usize
56 }
57
58 fn height(&self) -> u32 {
59 self.height
60 }
61
62 fn data(&self) -> &[Data<T>] {
63 &self.data
64 }
65
66 fn data_mut(&mut self) -> &mut Vec<Data<T>> {
67 &mut self.data
68 }
69}
70
71pub struct List<S: Store, T: DagCbor> {
72 nodes: IpldCache<S, DagCborCodec, Node<T>>,
73 root: Cid,
74}
75
76impl<S: Store, T: Clone + DagCbor + Send + Sync> List<S, T>
77where
78 S: Store,
79 S::Params: StoreParams<Hashes = Code>,
80 <S::Params as StoreParams>::Codecs: Into<DagCborCodec>,
81 T: Decode<DagCborCodec> + Encode<DagCborCodec> + Clone + Send + Sync,
82 DagCborCodec: Into<<S::Params as StoreParams>::Codecs>,
83 Ipld: Decode<<S::Params as StoreParams>::Codecs>,
84{
85 pub async fn new(store: S, cache_size: usize, width: u32) -> Result<Self> {
86 let cache = IpldCache::new(store, DagCborCodec, Code::Blake2b256, cache_size);
87 let root = cache.insert(Node::new(width, 0, vec![])).await?;
88 Ok(Self { nodes: cache, root })
89 }
90
91 pub async fn open(store: S, cache_size: usize, root: Cid) -> Result<Self> {
92 let cache = IpldCache::new(store, DagCborCodec, Code::Blake2b256, cache_size);
93 cache.get(&root).await?;
95 Ok(Self { nodes: cache, root })
96 }
97
98 pub fn root(&self) -> &Cid {
99 &self.root
100 }
101
102 pub async fn from(
103 store: S,
104 width: u32,
105 cache_size: usize,
106 items: impl Iterator<Item = T>,
107 ) -> Result<Self> {
108 let cache = IpldCache::new(store, DagCborCodec, Code::Blake2b256, cache_size);
109
110 let mut items: Vec<Data<T>> = items.map(Data::Value).collect();
111 let mut height = 0;
112 let mut cid = cache.insert(Node::new(width, height, vec![])).await?;
113 let width = width as usize;
114
115 loop {
116 let n_items = items.len() / width + 1;
117 let mut items_next = Vec::with_capacity(n_items);
118 for chunk in items.chunks(width) {
119 let node = Node::new(width as u32, height, chunk.to_vec());
120 cid = cache.insert(node).await?;
121 items_next.push(Data::Link(cid));
122 }
123 if items_next.len() == 1 {
124 return Ok(Self {
125 nodes: cache,
126 root: cid,
127 });
128 }
129 items = items_next;
130 height += 1;
131 }
132 }
133
134 pub async fn push(&mut self, value: T) -> Result<()> {
135 let mut value = Data::Value(value);
136 let root = self.nodes.get(&self.root).await?;
137 let height = root.height();
138 let width = root.width();
139
140 let chain = {
141 let mut height = root.height();
142 let mut chain = Vec::with_capacity(height as usize + 1);
143 chain.push(root);
144 while height > 0 {
145 let cid = chain
146 .last()
147 .expect("at least one block")
148 .data()
149 .last()
150 .expect("at least one link")
151 .cid()
152 .expect("height > 0, payload must be a cid");
153 let node = self.nodes.get(cid).await?;
154 height = node.height();
155 chain.push(node);
156 }
157 chain
158 };
159
160 let mut mutated = false;
161 let cache = &self.nodes;
162 let mut last = cache
163 .insert(Node::new(width as u32, height, vec![]))
164 .await?;
165 for mut node in chain.into_iter().rev() {
166 if mutated {
167 let data = node.data_mut();
168 data.pop();
169 data.push(value);
170 last = cache.insert(node).await?;
171 value = Data::Link(last);
172 } else {
173 let data = node.data_mut();
174 if data.len() < width {
175 data.push(value);
176 last = cache.insert(node).await?;
177 value = Data::Link(last);
178 mutated = true;
179 } else {
180 let node = Node::new(width as u32, node.height(), vec![value]);
181 last = cache.insert(node).await?;
182 value = Data::Link(last);
183 mutated = false;
184 }
185 }
186 }
187
188 if !mutated {
189 let children = vec![Data::Link(*self.root()), value];
190 let node = Node::new(width as u32, height + 1, children);
191 last = cache.insert(node).await?;
192 }
193
194 self.root = last;
195
196 Ok(())
197 }
198
199 pub async fn pop(&mut self) -> Result<Option<T>> {
200 Ok(None)
202 }
203
204 pub async fn get(&mut self, mut index: usize) -> Result<Option<T>> {
205 let node = self.nodes.get(&self.root).await?;
206 let mut node_ref = &node;
207 let width = node.width();
208 let mut height = node.height();
209 let mut node;
210
211 if index > width.pow(height + 1) {
212 return Ok(None);
213 }
214
215 loop {
216 let data_index = index / width.pow(height);
217 if let Some(data) = node_ref.data().get(data_index) {
218 if height == 0 {
219 return Ok(Some(data.value().unwrap().clone()));
220 }
221 let cid = data.cid().unwrap();
222 node = self.nodes.get(cid).await?;
223 node_ref = &node;
224 index %= width.pow(height);
225 height = node.height();
226 } else {
227 return Ok(None);
228 }
229 }
230 }
231
232 pub async fn set(&mut self, _index: usize, _value: T) -> Result<()> {
233 Ok(())
235 }
236
237 pub async fn len(&mut self) -> Result<usize> {
238 let root = self.nodes.get(&self.root).await?;
239 let width = root.width();
240 let mut height = root.height();
241 let mut size = width.pow(height + 1);
242 let mut node = root;
243 loop {
244 let data = node.data();
245 size -= width.pow(height) * (width - data.len());
246 if height == 0 {
247 return Ok(size);
248 }
249 let cid = data.last().unwrap().cid().unwrap();
250 node = self.nodes.get(cid).await?;
251 height = node.height();
252 }
253 }
254
255 pub async fn is_empty(&mut self) -> Result<bool> {
256 let root = self.nodes.get(&self.root).await?;
257 Ok(root.data().is_empty())
258 }
259
260 pub fn iter(&mut self) -> Iter<'_, S, T> {
261 Iter {
262 list: self,
263 index: 0,
264 }
265 }
266}
267
268pub struct Iter<'a, S: Store, T: DagCbor> {
269 list: &'a mut List<S, T>,
270 index: usize,
271}
272
273impl<'a, S, T: DagCbor> Iter<'a, S, T>
274where
275 S: Store,
276 S::Params: StoreParams<Hashes = Code>,
277 <S::Params as StoreParams>::Codecs: Into<DagCborCodec>,
278 T: Decode<DagCborCodec> + Encode<DagCborCodec> + Clone + Send + Sync,
279 DagCborCodec: Into<<S::Params as StoreParams>::Codecs>,
280 Ipld: Decode<<S::Params as StoreParams>::Codecs>,
281{
282 #[allow(clippy::should_implement_trait)]
283 pub async fn next(&mut self) -> Result<Option<T>> {
284 let elem = self.list.get(self.index).await?;
285 self.index += 1;
286 Ok(elem)
287 }
288}
289
290#[cfg(test)]
291mod tests {
292 use super::*;
293 use async_std::task;
294 use libipld::mem::MemStore;
295 use libipld::store::DefaultParams;
296 use model::*;
297
298 #[async_std::test]
299 async fn test_list() -> Result<()> {
300 let store = MemStore::<DefaultParams>::default();
301 let mut list = List::new(store, 12, 3).await?;
302 for i in 0..13 {
303 assert_eq!(list.get(i).await?, None);
304 assert_eq!(list.len().await?, i);
305 list.push(i as i64).await?;
306 for j in 0..i {
307 assert_eq!(list.get(j).await?, Some(j as i64));
308 }
309 }
310 Ok(())
319 }
320
321 #[async_std::test]
322 async fn test_list_from() -> Result<()> {
323 let store = MemStore::<DefaultParams>::default();
324 let data: Vec<_> = (0..13).map(|i| i as i64).collect();
325 let mut list = List::from(store, 12, 3, data.clone().into_iter()).await?;
326 let mut data2 = vec![];
327 let mut iter = list.iter();
328 while let Some(elem) = iter.next().await? {
329 data2.push(elem)
330 }
331 assert_eq!(data, data2);
332 Ok(())
333 }
334
335 #[test]
336 fn list_vec_eqv() {
337 const LEN: usize = 25;
338 model! {
339 Model => let mut vec = Vec::new(),
340 Implementation => let mut list = {
341 let store = MemStore::<DefaultParams>::default();
342 let fut = List::new(store, LEN,3);
343 task::block_on(fut).unwrap()
344 },
345 Push(usize)(i in 0..LEN) => {
346 vec.push(i as i64);
347 task::block_on(list.push(i as i64)).unwrap();
348 },
349 Get(usize)(i in 0..LEN) => {
350 let r1 = vec.get(i).cloned();
351 let r2 = task::block_on(list.get(i)).unwrap();
352 assert_eq!(r1, r2);
353 },
354 Len(usize)(_ in 0..LEN) => {
355 let r1 = vec.len();
356 let r2 = task::block_on(list.len()).unwrap();
357 assert_eq!(r1, r2);
358 },
359 IsEmpty(usize)(_ in 0..LEN) => {
360 let r1 = vec.is_empty();
361 let r2 = task::block_on(list.is_empty()).unwrap();
362 assert_eq!(r1, r2);
363 }
364 }
365 }
366}