1use persy::{
51 ByteVec, IndexId, IndexInfo, IndexType, IndexTypeId, Persy, PersyError, PersyId, SegmentId, Snapshot, Transaction,
52 ValueIter, ValueMode,
53};
54use std::io;
55use std::iter::Iterator;
56use std::ops::RangeBounds;
57
58pub type EIRes<T> = Result<T, Error>;
59
60#[cfg(feature = "serde")]
61use serde_derive::{Deserialize, Serialize};
62
63#[cfg(feature = "serde")]
64mod serde;
65#[cfg(feature = "serde")]
66use crate::serde::{
67 bytevec_deserialize, bytevec_serialize, index_id_deserialize, index_id_serialize, index_type_id_deserialize,
68 index_type_id_serialize, persy_id_deserialize, persy_id_serialize, segment_id_deserialize, segment_id_serialize,
69 value_mode_deserialize, value_mode_serialize, vec_bytevec_deserialize, vec_bytevec_serialize,
70 vec_persy_id_deserialize, vec_persy_id_serialize,
71};
72
73#[cfg(feature = "json")]
74mod json;
75#[cfg(feature = "json")]
76pub use json::{export_json, export_json_from_snapshot, import_json};
77
78#[cfg(feature = "binary")]
79mod binary;
80#[cfg(feature = "binary")]
81pub use binary::{export_binary, export_binary_from_snapshot, import_binary};
82
83#[derive(Debug)]
84pub enum Error {
85 PersyError(PersyError),
86 IoError(io::Error),
87 SerdeError(String),
88}
89
90impl<T: Into<PersyError>> From<persy::PE<T>> for Error {
91 fn from(err: persy::PE<T>) -> Error {
92 Error::PersyError(err.error().into())
93 }
94}
95
96impl From<io::Error> for Error {
97 fn from(err: io::Error) -> Error {
98 Error::IoError(err)
99 }
100}
101
102#[cfg(feature = "json")]
103impl From<serde_json::error::Error> for Error {
104 fn from(err: serde_json::error::Error) -> Error {
105 Error::SerdeError(format!("{}", err))
106 }
107}
108
109#[cfg(feature = "bincode")]
110impl From<bincode::Error> for Error {
111 fn from(err: bincode::Error) -> Error {
112 Error::SerdeError(format!("{}", err))
113 }
114}
115
116#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
117pub struct SegmentMetadata {
118 pub version: u32,
119 pub name: String,
120 #[cfg_attr(
121 feature = "serde",
122 serde(serialize_with = "segment_id_serialize", deserialize_with = "segment_id_deserialize")
123 )]
124 pub id: SegmentId,
125}
126
127#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
128pub struct Record {
129 pub version: u32,
130 pub segment: String,
131 #[cfg_attr(
132 feature = "serde",
133 serde(serialize_with = "persy_id_serialize", deserialize_with = "persy_id_deserialize")
134 )]
135 pub id: PersyId,
136 pub content: Vec<u8>,
137}
138
139#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
140pub struct IndexMetadata {
141 pub version: u32,
142 pub name: String,
143 #[cfg_attr(
144 feature = "serde",
145 serde(serialize_with = "index_id_serialize", deserialize_with = "index_id_deserialize")
146 )]
147 pub id: IndexId,
148 #[cfg_attr(
149 feature = "serde",
150 serde(
151 serialize_with = "index_type_id_serialize",
152 deserialize_with = "index_type_id_deserialize"
153 )
154 )]
155 pub key_type: IndexTypeId,
156 #[cfg_attr(
157 feature = "serde",
158 serde(
159 serialize_with = "index_type_id_serialize",
160 deserialize_with = "index_type_id_deserialize"
161 )
162 )]
163 pub value_type: IndexTypeId,
164 #[cfg_attr(
165 feature = "serde",
166 serde(serialize_with = "value_mode_serialize", deserialize_with = "value_mode_deserialize")
167 )]
168 pub value_mode: ValueMode,
169}
170
171#[derive(Clone)]
172#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
173pub enum IndexKey {
174 U8(u8),
175 U16(u16),
176 U32(u32),
177 U64(u64),
178 U128(u128),
179 I8(i8),
180 I16(i16),
181 I32(i32),
182 I64(i64),
183 I128(i128),
184 F32(f32),
185 F64(f64),
186 String(String),
187 #[cfg_attr(
188 feature = "serde",
189 serde(serialize_with = "persy_id_serialize", deserialize_with = "persy_id_deserialize")
190 )]
191 PersyId(PersyId),
192 #[cfg_attr(
193 feature = "serde",
194 serde(serialize_with = "bytevec_serialize", deserialize_with = "bytevec_deserialize")
195 )]
196 ByteVec(ByteVec),
197}
198
199#[derive(Clone)]
200#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
201pub enum IndexValue {
202 U8(Vec<u8>),
203 U16(Vec<u16>),
204 U32(Vec<u32>),
205 U64(Vec<u64>),
206 U128(Vec<u128>),
207 I8(Vec<i8>),
208 I16(Vec<i16>),
209 I32(Vec<i32>),
210 I64(Vec<i64>),
211 I128(Vec<i128>),
212 F32(Vec<f32>),
213 F64(Vec<f64>),
214 String(Vec<String>),
215 #[cfg_attr(
216 feature = "serde",
217 serde(
218 serialize_with = "vec_persy_id_serialize",
219 deserialize_with = "vec_persy_id_deserialize"
220 )
221 )]
222 PersyId(Vec<PersyId>),
223 #[cfg_attr(
224 feature = "serde",
225 serde(
226 serialize_with = "vec_bytevec_serialize",
227 deserialize_with = "vec_bytevec_deserialize"
228 )
229 )]
230 ByteVec(Vec<ByteVec>),
231}
232
233fn range<K: IndexType + 'static, V: IndexType + 'static, T: PersyReader>(
234 persy: T,
235 name: &str,
236) -> EIRes<impl Iterator<Item = (K, ValueIter<V>)>> {
237 persy.range::<K, V, _>(name, ..)
238}
239
240fn resolve_value_type<K: IndexType + 'static, T: PersyReader + 'static>(
241 persy: T,
242 name: &str,
243 info: IndexInfo,
244) -> EIRes<Box<dyn Iterator<Item = (K, IndexValue)>>> {
245 Ok(match info.value_type {
246 IndexTypeId::U8 => {
247 Box::new(range::<K, u8, T>(persy, name)?.map(|(k, v)| (k, IndexValue::U8(v.into_iter().collect()))))
248 }
249 IndexTypeId::U16 => {
250 Box::new(range::<K, u16, T>(persy, name)?.map(|(k, v)| (k, IndexValue::U16(v.into_iter().collect()))))
251 }
252 IndexTypeId::U32 => {
253 Box::new(range::<K, u32, T>(persy, name)?.map(|(k, v)| (k, IndexValue::U32(v.into_iter().collect()))))
254 }
255 IndexTypeId::U64 => {
256 Box::new(range::<K, u64, T>(persy, name)?.map(|(k, v)| (k, IndexValue::U64(v.into_iter().collect()))))
257 }
258 IndexTypeId::U128 => {
259 Box::new(range::<K, u128, T>(persy, name)?.map(|(k, v)| (k, IndexValue::U128(v.into_iter().collect()))))
260 }
261 IndexTypeId::I8 => {
262 Box::new(range::<K, i8, T>(persy, name)?.map(|(k, v)| (k, IndexValue::I8(v.into_iter().collect()))))
263 }
264 IndexTypeId::I16 => {
265 Box::new(range::<K, i16, T>(persy, name)?.map(|(k, v)| (k, IndexValue::I16(v.into_iter().collect()))))
266 }
267 IndexTypeId::I32 => {
268 Box::new(range::<K, i32, T>(persy, name)?.map(|(k, v)| (k, IndexValue::I32(v.into_iter().collect()))))
269 }
270 IndexTypeId::I64 => {
271 Box::new(range::<K, i64, T>(persy, name)?.map(|(k, v)| (k, IndexValue::I64(v.into_iter().collect()))))
272 }
273 IndexTypeId::I128 => {
274 Box::new(range::<K, i128, T>(persy, name)?.map(|(k, v)| (k, IndexValue::I128(v.into_iter().collect()))))
275 }
276 IndexTypeId::F32W => {
277 Box::new(range::<K, f32, T>(persy, name)?.map(|(k, v)| (k, IndexValue::F32(v.into_iter().collect()))))
278 }
279 IndexTypeId::F64W => {
280 Box::new(range::<K, f64, T>(persy, name)?.map(|(k, v)| (k, IndexValue::F64(v.into_iter().collect()))))
281 }
282 IndexTypeId::String => {
283 Box::new(range::<K, String, T>(persy, name)?.map(|(k, v)| (k, IndexValue::String(v.into_iter().collect()))))
284 }
285 IndexTypeId::PersyId => Box::new(
286 range::<K, PersyId, T>(persy, name)?.map(|(k, v)| (k, IndexValue::PersyId(v.into_iter().collect()))),
287 ),
288 IndexTypeId::ByteVec => Box::new(
289 range::<K, ByteVec, T>(persy, name)?.map(|(k, v)| (k, IndexValue::ByteVec(v.into_iter().collect()))),
290 ),
291 })
292}
293fn browse<T: PersyReader + 'static>(
294 persy: T,
295 name: &str,
296 info: IndexInfo,
297) -> EIRes<Box<dyn Iterator<Item = (IndexKey, IndexValue)>>> {
298 Ok(match info.key_type {
299 IndexTypeId::U8 => Box::new(resolve_value_type::<u8, T>(persy, name, info)?.map(|(k, v)| (IndexKey::U8(k), v))),
300 IndexTypeId::U16 => {
301 Box::new(resolve_value_type::<u16, T>(persy, name, info)?.map(|(k, v)| (IndexKey::U16(k), v)))
302 }
303 IndexTypeId::U32 => {
304 Box::new(resolve_value_type::<u32, T>(persy, name, info)?.map(|(k, v)| (IndexKey::U32(k), v)))
305 }
306 IndexTypeId::U64 => {
307 Box::new(resolve_value_type::<u64, T>(persy, name, info)?.map(|(k, v)| (IndexKey::U64(k), v)))
308 }
309 IndexTypeId::U128 => {
310 Box::new(resolve_value_type::<u128, T>(persy, name, info)?.map(|(k, v)| (IndexKey::U128(k), v)))
311 }
312 IndexTypeId::I8 => Box::new(resolve_value_type::<i8, T>(persy, name, info)?.map(|(k, v)| (IndexKey::I8(k), v))),
313 IndexTypeId::I16 => {
314 Box::new(resolve_value_type::<i16, T>(persy, name, info)?.map(|(k, v)| (IndexKey::I16(k), v)))
315 }
316 IndexTypeId::I32 => {
317 Box::new(resolve_value_type::<i32, T>(persy, name, info)?.map(|(k, v)| (IndexKey::I32(k), v)))
318 }
319 IndexTypeId::I64 => {
320 Box::new(resolve_value_type::<i64, T>(persy, name, info)?.map(|(k, v)| (IndexKey::I64(k), v)))
321 }
322 IndexTypeId::I128 => {
323 Box::new(resolve_value_type::<i128, T>(persy, name, info)?.map(|(k, v)| (IndexKey::I128(k), v)))
324 }
325 IndexTypeId::F32W => {
326 Box::new(resolve_value_type::<f32, T>(persy, name, info)?.map(|(k, v)| (IndexKey::F32(k), v)))
327 }
328 IndexTypeId::F64W => {
329 Box::new(resolve_value_type::<f64, T>(persy, name, info)?.map(|(k, v)| (IndexKey::F64(k), v)))
330 }
331 IndexTypeId::String => {
332 Box::new(resolve_value_type::<String, T>(persy, name, info)?.map(|(k, v)| (IndexKey::String(k), v)))
333 }
334 IndexTypeId::PersyId => {
335 Box::new(resolve_value_type::<PersyId, T>(persy, name, info)?.map(|(k, v)| (IndexKey::PersyId(k), v)))
336 }
337 IndexTypeId::ByteVec => {
338 Box::new(resolve_value_type::<ByteVec, T>(persy, name, info)?.map(|(k, v)| (IndexKey::ByteVec(k), v)))
339 }
340 })
341}
342
343#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
344pub struct Entry {
345 pub version: u32,
346 pub index: String,
347 pub key: IndexKey,
348 pub value: IndexValue,
349}
350
351#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
352pub enum Info {
353 Segment(SegmentMetadata),
354 Record(Record),
355 Index(IndexMetadata),
356 Entry(Entry),
357}
358
359fn iter_keys<T: PersyReader + 'static>(
360 persy: T,
361 (name, infos): (String, IndexInfo),
362) -> EIRes<Box<impl Iterator<Item = Info>>> {
363 let entries = browse(persy, &name, infos)?;
364 Ok(Box::new(entries.map(move |(k, v)| {
365 Info::Entry(Entry {
366 version: 0,
367 index: name.clone(),
368 key: k,
369 value: v,
370 })
371 })))
372}
373
374fn create_index_k<K: IndexType + 'static>(tx: &mut Transaction, info: IndexMetadata) -> EIRes<()> {
375 Ok(match info.value_type {
376 IndexTypeId::U8 => tx.create_index::<K, u8>(&info.name, info.value_mode)?,
377 IndexTypeId::U16 => tx.create_index::<K, u16>(&info.name, info.value_mode)?,
378 IndexTypeId::U32 => tx.create_index::<K, u32>(&info.name, info.value_mode)?,
379 IndexTypeId::U64 => tx.create_index::<K, u64>(&info.name, info.value_mode)?,
380 IndexTypeId::U128 => tx.create_index::<K, u128>(&info.name, info.value_mode)?,
381 IndexTypeId::I8 => tx.create_index::<K, i8>(&info.name, info.value_mode)?,
382 IndexTypeId::I16 => tx.create_index::<K, i16>(&info.name, info.value_mode)?,
383 IndexTypeId::I32 => tx.create_index::<K, i32>(&info.name, info.value_mode)?,
384 IndexTypeId::I64 => tx.create_index::<K, i64>(&info.name, info.value_mode)?,
385 IndexTypeId::I128 => tx.create_index::<K, i128>(&info.name, info.value_mode)?,
386 IndexTypeId::F32W => tx.create_index::<K, f32>(&info.name, info.value_mode)?,
387 IndexTypeId::F64W => tx.create_index::<K, f64>(&info.name, info.value_mode)?,
388 IndexTypeId::String => tx.create_index::<K, String>(&info.name, info.value_mode)?,
389 IndexTypeId::PersyId => tx.create_index::<K, PersyId>(&info.name, info.value_mode)?,
390 IndexTypeId::ByteVec => tx.create_index::<K, ByteVec>(&info.name, info.value_mode)?,
391 })
392}
393fn create_index(tx: &mut Transaction, info: IndexMetadata) -> EIRes<()> {
394 match info.key_type {
395 IndexTypeId::U8 => create_index_k::<u8>(tx, info),
396 IndexTypeId::U16 => create_index_k::<u16>(tx, info),
397 IndexTypeId::U32 => create_index_k::<u32>(tx, info),
398 IndexTypeId::U64 => create_index_k::<u64>(tx, info),
399 IndexTypeId::U128 => create_index_k::<u128>(tx, info),
400 IndexTypeId::I8 => create_index_k::<i8>(tx, info),
401 IndexTypeId::I16 => create_index_k::<i16>(tx, info),
402 IndexTypeId::I32 => create_index_k::<i32>(tx, info),
403 IndexTypeId::I64 => create_index_k::<i64>(tx, info),
404 IndexTypeId::I128 => create_index_k::<i128>(tx, info),
405 IndexTypeId::F32W => create_index_k::<f32>(tx, info),
406 IndexTypeId::F64W => create_index_k::<f64>(tx, info),
407 IndexTypeId::String => create_index_k::<String>(tx, info),
408 IndexTypeId::PersyId => create_index_k::<PersyId>(tx, info),
409 IndexTypeId::ByteVec => create_index_k::<ByteVec>(tx, info),
410 }
411}
412
413fn remap_persy_id(tx: &mut Transaction, orig: PersyId, new: PersyId) -> EIRes<()> {
414 Ok(tx.put("xx__persy__id__mapper", orig, new)?)
415}
416
417fn create_map_persy_id_index(tx: &mut Transaction) -> EIRes<()> {
418 Ok(tx.create_index::<PersyId, PersyId>("xx__persy__id__mapper", ValueMode::Replace)?)
419}
420
421fn drop_map_persy_id_index(tx: &mut Transaction) -> EIRes<()> {
422 Ok(tx.drop_index("xx__persy__id__mapper")?)
423}
424
425fn map_persy_id(tx: &mut Transaction, id: PersyId) -> EIRes<PersyId> {
426 Ok(tx.get("xx__persy__id__mapper", &id)?.into_iter().next().unwrap_or(id))
427}
428
429fn map_persy_id_out(persy: &Persy, id: PersyId) -> EIRes<PersyId> {
430 Ok(persy
431 .get("xx__persy__id__mapper", &id)?
432 .into_iter()
433 .next()
434 .unwrap_or(id))
435}
436
437fn put_all_id<K: IndexType>(tx: &mut Transaction, index: &str, k: K, v: Vec<PersyId>) -> EIRes<()> {
438 for val in v {
439 let mapped = map_persy_id(tx, val)?;
440 tx.put(index, k.clone(), mapped)?;
441 }
442 Ok(())
443}
444
445fn put_all<K: IndexType, V: IndexType>(tx: &mut Transaction, index: &str, k: K, v: Vec<V>) -> EIRes<()> {
446 for val in v {
447 tx.put(index, k.clone(), val)?;
448 }
449 Ok(())
450}
451
452fn put_entry_k<K: IndexType + 'static>(tx: &mut Transaction, k: K, entry: Entry) -> EIRes<()> {
453 match entry.value {
454 IndexValue::U8(v) => put_all(tx, &entry.index, k, v),
455 IndexValue::U16(v) => put_all(tx, &entry.index, k, v),
456 IndexValue::U32(v) => put_all(tx, &entry.index, k, v),
457 IndexValue::U64(v) => put_all(tx, &entry.index, k, v),
458 IndexValue::U128(v) => put_all(tx, &entry.index, k, v),
459 IndexValue::I8(v) => put_all(tx, &entry.index, k, v),
460 IndexValue::I16(v) => put_all(tx, &entry.index, k, v),
461 IndexValue::I32(v) => put_all(tx, &entry.index, k, v),
462 IndexValue::I64(v) => put_all(tx, &entry.index, k, v),
463 IndexValue::I128(v) => put_all(tx, &entry.index, k, v),
464 IndexValue::F32(v) => put_all(tx, &entry.index, k, v),
465 IndexValue::F64(v) => put_all(tx, &entry.index, k, v),
466 IndexValue::String(v) => put_all(tx, &entry.index, k, v),
467 IndexValue::PersyId(v) => put_all_id(tx, &entry.index, k, v),
468 IndexValue::ByteVec(v) => put_all(tx, &entry.index, k, v),
469 }
470}
471fn put_entry(tx: &mut Transaction, entry: Entry) -> EIRes<()> {
472 match entry.key.clone() {
473 IndexKey::U8(k) => put_entry_k(tx, k, entry),
474 IndexKey::U16(k) => put_entry_k(tx, k, entry),
475 IndexKey::U32(k) => put_entry_k(tx, k, entry),
476 IndexKey::U64(k) => put_entry_k(tx, k, entry),
477 IndexKey::U128(k) => put_entry_k(tx, k, entry),
478 IndexKey::I8(k) => put_entry_k(tx, k, entry),
479 IndexKey::I16(k) => put_entry_k(tx, k, entry),
480 IndexKey::I32(k) => put_entry_k(tx, k, entry),
481 IndexKey::I64(k) => put_entry_k(tx, k, entry),
482 IndexKey::I128(k) => put_entry_k(tx, k, entry),
483 IndexKey::F32(k) => put_entry_k(tx, k, entry),
484 IndexKey::F64(k) => put_entry_k(tx, k, entry),
485 IndexKey::String(k) => put_entry_k(tx, k, entry),
486 IndexKey::PersyId(k) => {
487 let mapped_key = map_persy_id(tx, k)?;
488 put_entry_k(tx, mapped_key, entry)
489 }
490 IndexKey::ByteVec(k) => put_entry_k(tx, k, entry),
491 }
492}
493
494pub trait PersyReader: Clone + Sized {
495 fn list_segments(&self) -> EIRes<Vec<(String, SegmentId)>>;
496
497 fn list_indexes(&self) -> EIRes<Vec<(String, IndexInfo)>>;
498
499 fn scan(&self, segment: &str) -> EIRes<Box<dyn Iterator<Item = (PersyId, Vec<u8>)>>>;
500
501 fn range<K, V, R>(&self, index_name: &str, range: R) -> EIRes<Box<dyn Iterator<Item = (K, ValueIter<V>)>>>
502 where
503 K: IndexType + 'static,
504 V: IndexType + 'static,
505 R: RangeBounds<K>;
506}
507
508impl PersyReader for Persy {
509 fn list_segments(&self) -> EIRes<Vec<(String, SegmentId)>> {
510 Ok(self.list_segments()?)
511 }
512 fn list_indexes(&self) -> EIRes<Vec<(String, IndexInfo)>> {
513 Ok(self.list_indexes()?)
514 }
515 fn scan(&self, segment: &str) -> EIRes<Box<dyn Iterator<Item = (PersyId, Vec<u8>)>>> {
516 Ok(Box::new(self.scan(segment)?))
517 }
518 fn range<K, V, R>(&self, index_name: &str, range: R) -> EIRes<Box<dyn Iterator<Item = (K, ValueIter<V>)>>>
519 where
520 K: IndexType + 'static,
521 V: IndexType + 'static,
522 R: RangeBounds<K>,
523 {
524 Ok(Box::new(self.range::<K, V, R>(index_name, range)?))
525 }
526}
527impl PersyReader for Snapshot {
528 fn list_segments(&self) -> EIRes<Vec<(String, SegmentId)>> {
529 Ok(self.list_segments()?)
530 }
531
532 fn list_indexes(&self) -> EIRes<Vec<(String, IndexInfo)>> {
533 Ok(self.list_indexes()?)
534 }
535
536 fn scan(&self, segment: &str) -> EIRes<Box<dyn Iterator<Item = (PersyId, Vec<u8>)>>> {
537 Ok(Box::new(self.scan(segment)?))
538 }
539 fn range<K, V, R>(&self, index_name: &str, range: R) -> EIRes<Box<dyn Iterator<Item = (K, ValueIter<V>)>>>
540 where
541 K: IndexType + 'static,
542 V: IndexType + 'static,
543 R: RangeBounds<K>,
544 {
545 Ok(Box::new(self.range::<K, V, R>(index_name, range)?))
546 }
547}
548
549pub fn export(persy_p: &Persy) -> EIRes<Box<impl Iterator<Item = Info>>> {
567 export_from_reader(persy_p)
568}
569fn export_from_reader<T: PersyReader + 'static>(persy_p: &T) -> EIRes<Box<impl Iterator<Item = Info>>> {
570 let persy = persy_p.clone();
571 let segs = persy.list_segments()?.into_iter();
572 let indexes = persy.list_indexes()?.into_iter();
573 let p_keys = persy.clone();
574 let all_keys = indexes
575 .clone()
576 .map(move |i| iter_keys(p_keys.clone(), i))
577 .flatten()
578 .flatten();
579 let indexes_info = indexes.map(|(name, infos)| {
580 Info::Index(IndexMetadata {
581 version: 0,
582 name,
583 id: infos.id,
584 key_type: infos.key_type,
585 value_type: infos.value_type,
586 value_mode: infos.value_mode,
587 })
588 });
589 let all_records = segs
590 .clone()
591 .map(move |(name, _)| -> EIRes<_> {
592 Ok(persy.clone().scan(&name)?.map(move |(id, content)| {
593 Info::Record(Record {
594 version: 0,
595 segment: name.clone(),
596 id,
597 content,
598 })
599 }))
600 })
601 .flatten()
602 .flatten();
603 let segs_info = segs.map(|(name, id)| Info::Segment(SegmentMetadata { version: 0, name, id }));
604 Ok(Box::new(
605 segs_info.chain(indexes_info).chain(all_records).chain(all_keys),
606 ))
607}
608
609pub fn export_from_snapshot(persy_p: &Snapshot) -> EIRes<Box<impl Iterator<Item = Info>>> {
628 export_from_reader(persy_p)
629}
630
631pub fn import<I>(persy: &Persy, importer: I) -> EIRes<()>
648where
649 I: Iterator<Item = Info>,
650{
651 import_with_handler(persy, importer, NothingHandler())
652}
653
654pub fn import_with_handler<I, H>(persy: &Persy, importer: I, handler: H) -> EIRes<()>
685where
686 I: Iterator<Item = Info>,
687 H: Handler,
688{
689 let mut tx = persy.begin()?;
690 create_map_persy_id_index(&mut tx)?;
691 tx.prepare()?.commit()?;
692 let mapper = Mapper::new(persy);
693 handler.pre(persy, &mapper)?;
694 for val in importer {
695 let mut tx = persy.begin()?;
696 match val {
697 Info::Segment(segment) => {
698 tx.create_segment(&segment.name)?;
699 }
700 Info::Record(record) => {
701 let inserted_id = tx.insert(&record.segment, &record.content)?;
702 remap_persy_id(&mut tx, record.id, inserted_id)?;
703 }
704 Info::Index(index) => {
705 create_index(&mut tx, index)?;
706 }
707 Info::Entry(entry) => {
708 put_entry(&mut tx, entry)?;
709 }
710 }
711 let prep = tx.prepare()?;
712 prep.commit()?;
713 }
714 handler.post(persy, &mapper)?;
715 let mut tx = persy.begin()?;
716 drop_map_persy_id_index(&mut tx)?;
717 tx.prepare()?.commit()?;
718 Ok(())
719}
720
721pub trait Handler {
722 fn pre(&self, persy: &Persy, mapper: &Mapper) -> EIRes<()>;
723 fn post(&self, persy: &Persy, mapper: &Mapper) -> EIRes<()>;
724}
725struct NothingHandler();
726
727impl Handler for NothingHandler {
728 fn pre(&self, _persy: &Persy, _mapper: &Mapper) -> EIRes<()> {
729 Ok(())
730 }
731 fn post(&self, _persy: &Persy, _mapper: &Mapper) -> EIRes<()> {
732 Ok(())
733 }
734}
735
736pub struct Mapper {
737 persy: Persy,
738}
739impl Mapper {
740 fn new(persy: &Persy) -> Self {
741 Self { persy: persy.clone() }
742 }
743 pub fn map(&self, id: PersyId) -> EIRes<PersyId> {
744 map_persy_id_out(&self.persy, id)
745 }
746}
747
748#[cfg(test)]
749mod tests {
750 use super::{export, export_from_snapshot, import, Info};
751 use persy::{ByteVec, Config, IndexType, Persy, PersyId, Transaction, ValueMode};
752 use std::fs;
753
754 fn util<C, V>(name: &str, create: C, verify: V)
755 where
756 C: FnOnce(&mut Transaction),
757 V: FnOnce(&Persy),
758 {
759 let c_name = format!("target/{}.pei", name);
760 let rec_name = format!("target/{}_fill.pei", name);
761 Persy::create(c_name.to_string()).expect("creation works fine");
762 let p = Persy::open(c_name.to_string(), Config::new()).expect("open fine");
763 let mut tx = p.begin().unwrap();
764 create(&mut tx);
765 let prep = tx.prepare().unwrap();
766 prep.commit().unwrap();
767 let data: Vec<Info> = export(&p).unwrap().collect();
768
769 Persy::create(rec_name.to_string()).expect("creation works fine");
770 let p1 = Persy::open(rec_name.to_string(), Config::new()).expect("open fine");
771 import(&p1, data.into_iter()).unwrap();
772 verify(&p1);
773 fs::remove_file(c_name).unwrap();
774 fs::remove_file(rec_name).unwrap();
775 }
776
777 #[test]
778 fn base_snapshot_export_import() {
779 let name = "snapshot";
780 let c_name = format!("target/{}.pei", name);
781 let rec_name = format!("target/{}_fill.pei", name);
782 Persy::create(c_name.to_string()).expect("creation works fine");
783 let p = Persy::open(c_name.to_string(), Config::new()).expect("open fine");
784 let mut tx = p.begin().unwrap();
785 tx.create_segment("test").unwrap();
786 tx.insert("test", &"test".to_string().as_bytes()).unwrap();
787 tx.create_index::<u8, u8>("test_u8", ValueMode::Replace).unwrap();
788 tx.put::<u8, u8>("test_u8", 10, 10).unwrap();
789 let prep = tx.prepare().unwrap();
790 prep.commit().unwrap();
791 let data: Vec<Info> = export_from_snapshot(&p.snapshot().unwrap()).unwrap().collect();
792
793 Persy::create(rec_name.to_string()).expect("creation works fine");
794 let p1 = Persy::open(rec_name.to_string(), Config::new()).expect("open fine");
795 import(&p1, data.into_iter()).unwrap();
796
797 for (_, content) in p.scan("test").unwrap() {
798 assert_eq!("test".to_string().as_bytes().to_vec(), content);
799 }
800 check_key_value(&p1, "test_u8", 10 as u8, 10 as u8);
801 fs::remove_file(c_name).unwrap();
802 fs::remove_file(rec_name).unwrap();
803 }
804
805 #[test]
806 fn segment_metadata_export_import() {
807 util(
808 "segment",
809 |tx| {
810 tx.create_segment("test").unwrap();
811 },
812 |p| {
813 assert!(p.exists_segment("test").unwrap());
814 },
815 );
816 }
817 #[test]
818 fn index_metadata_export_import() {
819 util(
820 "index",
821 |tx| {
822 tx.create_index::<u8, u8>("test", ValueMode::Replace).unwrap();
823 },
824 |p| {
825 assert!(p.exists_index("test").unwrap());
826 },
827 );
828 }
829
830 #[test]
831 fn segment_data_export_import() {
832 util(
833 "segment_data",
834 |tx| {
835 tx.create_segment("test").unwrap();
836 tx.insert("test", &"test".to_string().as_bytes()).unwrap();
837 },
838 |p| {
839 for (_, content) in p.scan("test").unwrap() {
840 assert_eq!("test".to_string().as_bytes().to_vec(), content);
841 }
842 },
843 );
844 }
845 #[test]
846 fn index_data_export_import() {
847 util(
848 "index_data",
849 |tx| {
850 tx.create_index::<u8, u8>("test", ValueMode::Replace).unwrap();
851 tx.put::<u8, u8>("test", 10, 10).unwrap();
852 },
853 |p| assert_eq!(10, p.get::<u8, u8>("test", &10).unwrap().into_iter().next().unwrap()),
854 );
855 }
856
857 #[test]
858 fn all_data_export_import() {
859 util(
860 "all_data",
861 |tx| {
862 tx.create_segment("test").unwrap();
863 let persy_id = tx.insert("test", &"test".to_string().as_bytes()).unwrap();
864 tx.create_index::<u8, u8>("test_u8", ValueMode::Replace).unwrap();
865 tx.put::<u8, u8>("test_u8", 10, 10).unwrap();
866 tx.create_index::<u16, u16>("test_u16", ValueMode::Replace).unwrap();
867 tx.put::<u16, u16>("test_u16", 10, 10).unwrap();
868 tx.create_index::<u32, u32>("test_u32", ValueMode::Replace).unwrap();
869 tx.put::<u32, u32>("test_u32", 10, 10).unwrap();
870 tx.create_index::<u64, u64>("test_u64", ValueMode::Replace).unwrap();
871 tx.put::<u64, u64>("test_u64", 10, 10).unwrap();
872 tx.create_index::<u128, u128>("test_u128", ValueMode::Replace).unwrap();
873 tx.put::<u128, u128>("test_u128", 10, 10).unwrap();
874 tx.create_index::<i8, i8>("test_i8", ValueMode::Replace).unwrap();
875 tx.put::<i8, i8>("test_i8", 10, 10).unwrap();
876 tx.create_index::<i16, i16>("test_i16", ValueMode::Replace).unwrap();
877 tx.put::<i16, i16>("test_i16", 10, 10).unwrap();
878 tx.create_index::<i32, i32>("test_i32", ValueMode::Replace).unwrap();
879 tx.put::<i32, i32>("test_i32", 10, 10).unwrap();
880 tx.create_index::<i64, i64>("test_i64", ValueMode::Replace).unwrap();
881 tx.put::<i64, i64>("test_i64", 10, 10).unwrap();
882 tx.create_index::<i128, i128>("test_i128", ValueMode::Replace).unwrap();
883 tx.put::<i128, i128>("test_i128", 10, 10).unwrap();
884 tx.create_index::<f32, f32>("test_f32", ValueMode::Replace).unwrap();
885 tx.put::<f32, f32>("test_f32", 10.0, 10.0).unwrap();
886 tx.create_index::<f64, f64>("test_f64", ValueMode::Replace).unwrap();
887 tx.put::<f64, f64>("test_f64", 10.0, 10.0).unwrap();
888 tx.create_index::<String, String>("test_string", ValueMode::Replace)
889 .unwrap();
890 tx.put::<String, String>("test_string", "one".to_string(), "two".to_string())
891 .unwrap();
892 tx.create_index::<ByteVec, ByteVec>("test_bytevec", ValueMode::Replace)
893 .unwrap();
894 let bv = ByteVec::new(vec![20, 10]);
895 let bv1 = ByteVec::new(vec![10, 20]);
896 tx.put::<ByteVec, ByteVec>("test_bytevec", bv, bv1).unwrap();
897 tx.create_index::<PersyId, PersyId>("test_p", ValueMode::Replace)
898 .unwrap();
899 tx.put::<PersyId, PersyId>("test_p", persy_id.clone(), persy_id)
900 .unwrap();
901 },
902 |p| {
903 for (_, content) in p.scan("test").unwrap() {
904 assert_eq!("test".to_string().as_bytes().to_vec(), content);
905 }
906 check_key_value(p, "test_u8", 10 as u8, 10 as u8);
907 check_key_value(p, "test_u16", 10 as u16, 10 as u16);
908 check_key_value(p, "test_u32", 10 as u32, 10 as u32);
909 check_key_value(p, "test_u64", 10 as u64, 10 as u64);
910 check_key_value(p, "test_u128", 10 as u128, 10 as u128);
911 check_key_value(p, "test_i8", 10 as i8, 10 as i8);
912 check_key_value(p, "test_i16", 10 as i16, 10 as i16);
913 check_key_value(p, "test_i32", 10 as i32, 10 as i32);
914 check_key_value(p, "test_i64", 10 as i64, 10 as i64);
915 check_key_value(p, "test_i128", 10 as i128, 10 as i128);
916 check_key_value(p, "test_f32", 10 as f32, 10 as f32);
917 check_key_value(p, "test_f64", 10 as f64, 10 as f64);
918 check_key_value(p, "test_string", "one".to_string(), "two".to_string());
919 let bv = ByteVec::new(vec![20, 10]);
920 let bv1 = ByteVec::new(vec![10, 20]);
921 check_key_value(p, "test_bytevec", bv, bv1);
922 assert_eq!(
923 1,
924 p.range::<PersyId, PersyId, _>("test_p", ..)
925 .unwrap()
926 .into_iter()
927 .count()
928 );
929 },
930 );
931 }
932
933 pub fn check_key_value<K: IndexType + PartialEq, V: IndexType + PartialEq + std::fmt::Debug>(
934 p: &Persy,
935 index: &str,
936 k: K,
937 v: V,
938 ) {
939 assert_eq!(v, p.get::<K, V>(index, &k).unwrap().into_iter().next().unwrap());
940 }
941
942 #[test]
943 fn index_id_mapping() {
944 util(
945 "id_mapping",
946 |tx| {
947 tx.create_segment("test").unwrap();
948 let id = tx.insert("test", "xxx".as_bytes()).unwrap();
949 tx.create_index::<u8, PersyId>("test", ValueMode::Replace).unwrap();
950 tx.put::<u8, PersyId>("test", 10, id).unwrap();
951 },
952 |p| {
953 let id = p.get::<u8, PersyId>("test", &10).unwrap().next().unwrap();
954 assert_eq!(Some("xxx".as_bytes().into()), p.read("test", &id).unwrap());
955 },
956 );
957 }
958}