atuin_client/import/
mod.rs1use std::fs::File;
2use std::io::Read;
3use std::path::PathBuf;
4
5use async_trait::async_trait;
6use eyre::{bail, Result};
7use memchr::Memchr;
8
9use crate::history::History;
10
11pub mod bash;
12pub mod fish;
13pub mod nu;
14pub mod nu_histdb;
15pub mod replxx;
16pub mod resh;
17pub mod xonsh;
18pub mod xonsh_sqlite;
19pub mod zsh;
20pub mod zsh_histdb;
21
22#[async_trait]
23pub trait Importer: Sized {
24 const NAME: &'static str;
25 async fn new() -> Result<Self>;
26 async fn entries(&mut self) -> Result<usize>;
27 async fn load(self, loader: &mut impl Loader) -> Result<()>;
28}
29
30#[async_trait]
31pub trait Loader: Sync + Send {
32 async fn push(&mut self, hist: History) -> eyre::Result<()>;
33}
34
35fn unix_byte_lines(input: &[u8]) -> impl Iterator<Item = &[u8]> {
36 UnixByteLines {
37 iter: memchr::memchr_iter(b'\n', input),
38 bytes: input,
39 i: 0,
40 }
41}
42
43struct UnixByteLines<'a> {
44 iter: Memchr<'a>,
45 bytes: &'a [u8],
46 i: usize,
47}
48
49impl<'a> Iterator for UnixByteLines<'a> {
50 type Item = &'a [u8];
51
52 fn next(&mut self) -> Option<Self::Item> {
53 let j = self.iter.next()?;
54 let out = &self.bytes[self.i..j];
55 self.i = j + 1;
56 Some(out)
57 }
58
59 fn count(self) -> usize
60 where
61 Self: Sized,
62 {
63 self.iter.count()
64 }
65}
66
67fn count_lines(input: &[u8]) -> usize {
68 unix_byte_lines(input).count()
69}
70
71fn get_histpath<D>(def: D) -> Result<PathBuf>
72where
73 D: FnOnce() -> Result<PathBuf>,
74{
75 if let Ok(p) = std::env::var("HISTFILE") {
76 is_file(PathBuf::from(p))
77 } else {
78 is_file(def()?)
79 }
80}
81
82fn read_to_end(path: PathBuf) -> Result<Vec<u8>> {
83 let mut bytes = Vec::new();
84 let mut f = File::open(path)?;
85 f.read_to_end(&mut bytes)?;
86 Ok(bytes)
87}
88fn is_file(p: PathBuf) -> Result<PathBuf> {
89 if p.is_file() {
90 Ok(p)
91 } else {
92 bail!("Could not find history file {:?}. Try setting $HISTFILE", p)
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 #[derive(Default)]
101 pub struct TestLoader {
102 pub buf: Vec<History>,
103 }
104
105 #[async_trait]
106 impl Loader for TestLoader {
107 async fn push(&mut self, hist: History) -> Result<()> {
108 self.buf.push(hist);
109 Ok(())
110 }
111 }
112}