Skip to main content

DomainWriter

Struct DomainWriter 

Source
pub struct DomainWriter { /* private fields */ }
Expand description

Builds a domain file set from sorted (key, value) pairs.

Implementations§

Source§

impl DomainWriter

Source

pub fn create( kv_path: impl AsRef<Path>, opts: DomainOptions, ) -> Result<DomainWriter>

Create a writer that will produce kv_path plus sibling .bt/.kvei files.

Examples found in repository?
examples/recode.rs (lines 26-32)
10fn main() -> Result<(), Box<dyn std::error::Error>> {
11    let mut args = std::env::args().skip(1);
12    let in_kv = args
13        .next()
14        .expect("usage: recode <in.kv> <out.kv> [salt-state.txt]");
15    let out_kv = args
16        .next()
17        .expect("usage: recode <in.kv> <out.kv> [salt-state.txt]");
18    let salt = args.next().and_then(salt_from_file);
19
20    // Read the source words (key/value pairs) and stream them into a DomainWriter.
21    let src = Seg::open(&in_kv)?;
22    let n_words = src.words_count();
23    println!("source: {} words ({} keys)", n_words, n_words / 2);
24
25    let t = Instant::now();
26    let mut w = DomainWriter::create(
27        &out_kv,
28        DomainOptions {
29            salt,
30            ..Default::default()
31        },
32    )?;
33    let mut g = src.getter();
34    while g.has_next() {
35        let key = g.next();
36        let value = if g.has_next() { g.next() } else { Vec::new() };
37        w.add(&key, &value)?;
38    }
39    let paths = w.finish()?;
40    println!("wrote {:?} in {:?}", paths, t.elapsed());
41
42    // Verify: every word matches the source byte-for-byte.
43    let dst = Seg::open(&out_kv)?;
44    assert_eq!(dst.words_count(), n_words);
45    let (mut a, mut b) = (src.getter(), dst.getter());
46    while a.has_next() {
47        assert_eq!(a.next(), b.next(), "word mismatch after re-encode");
48    }
49    assert!(!b.has_next());
50    println!("round-trip OK: all {n_words} words identical");
51
52    // If we built a bloom, confirm it accelerates lookups without false negatives.
53    if let Some(s) = salt {
54        let mut r = KvReader::open(&out_kv)?;
55        assert!(
56            r.enable_bloom(Salt::Known(s)),
57            "rebuilt .kvei failed to validate"
58        );
59        let mut checked = 0;
60        for kv in r.iter().step_by(997).take(500) {
61            let (k, v) = kv?;
62            assert_eq!(r.get(&k)?.as_deref(), Some(v.as_slice()));
63            checked += 1;
64        }
65        println!("bloom enabled; {checked} sampled lookups OK");
66    }
67
68    println!("\nOK");
69    Ok(())
70}
Source

pub fn add(&mut self, key: &[u8], value: &[u8]) -> Result<()>

Append one (key, value) pair. Keys must be strictly increasing.

Examples found in repository?
examples/recode.rs (line 37)
10fn main() -> Result<(), Box<dyn std::error::Error>> {
11    let mut args = std::env::args().skip(1);
12    let in_kv = args
13        .next()
14        .expect("usage: recode <in.kv> <out.kv> [salt-state.txt]");
15    let out_kv = args
16        .next()
17        .expect("usage: recode <in.kv> <out.kv> [salt-state.txt]");
18    let salt = args.next().and_then(salt_from_file);
19
20    // Read the source words (key/value pairs) and stream them into a DomainWriter.
21    let src = Seg::open(&in_kv)?;
22    let n_words = src.words_count();
23    println!("source: {} words ({} keys)", n_words, n_words / 2);
24
25    let t = Instant::now();
26    let mut w = DomainWriter::create(
27        &out_kv,
28        DomainOptions {
29            salt,
30            ..Default::default()
31        },
32    )?;
33    let mut g = src.getter();
34    while g.has_next() {
35        let key = g.next();
36        let value = if g.has_next() { g.next() } else { Vec::new() };
37        w.add(&key, &value)?;
38    }
39    let paths = w.finish()?;
40    println!("wrote {:?} in {:?}", paths, t.elapsed());
41
42    // Verify: every word matches the source byte-for-byte.
43    let dst = Seg::open(&out_kv)?;
44    assert_eq!(dst.words_count(), n_words);
45    let (mut a, mut b) = (src.getter(), dst.getter());
46    while a.has_next() {
47        assert_eq!(a.next(), b.next(), "word mismatch after re-encode");
48    }
49    assert!(!b.has_next());
50    println!("round-trip OK: all {n_words} words identical");
51
52    // If we built a bloom, confirm it accelerates lookups without false negatives.
53    if let Some(s) = salt {
54        let mut r = KvReader::open(&out_kv)?;
55        assert!(
56            r.enable_bloom(Salt::Known(s)),
57            "rebuilt .kvei failed to validate"
58        );
59        let mut checked = 0;
60        for kv in r.iter().step_by(997).take(500) {
61            let (k, v) = kv?;
62            assert_eq!(r.get(&k)?.as_deref(), Some(v.as_slice()));
63            checked += 1;
64        }
65        println!("bloom enabled; {checked} sampled lookups OK");
66    }
67
68    println!("\nOK");
69    Ok(())
70}
Source

pub fn key_count(&self) -> u64

Number of keys added so far.

Source

pub fn finish(self) -> Result<DomainPaths>

Finalize: write the .kv, then build the .bt and (if a salt was given) .kvei.

Examples found in repository?
examples/recode.rs (line 39)
10fn main() -> Result<(), Box<dyn std::error::Error>> {
11    let mut args = std::env::args().skip(1);
12    let in_kv = args
13        .next()
14        .expect("usage: recode <in.kv> <out.kv> [salt-state.txt]");
15    let out_kv = args
16        .next()
17        .expect("usage: recode <in.kv> <out.kv> [salt-state.txt]");
18    let salt = args.next().and_then(salt_from_file);
19
20    // Read the source words (key/value pairs) and stream them into a DomainWriter.
21    let src = Seg::open(&in_kv)?;
22    let n_words = src.words_count();
23    println!("source: {} words ({} keys)", n_words, n_words / 2);
24
25    let t = Instant::now();
26    let mut w = DomainWriter::create(
27        &out_kv,
28        DomainOptions {
29            salt,
30            ..Default::default()
31        },
32    )?;
33    let mut g = src.getter();
34    while g.has_next() {
35        let key = g.next();
36        let value = if g.has_next() { g.next() } else { Vec::new() };
37        w.add(&key, &value)?;
38    }
39    let paths = w.finish()?;
40    println!("wrote {:?} in {:?}", paths, t.elapsed());
41
42    // Verify: every word matches the source byte-for-byte.
43    let dst = Seg::open(&out_kv)?;
44    assert_eq!(dst.words_count(), n_words);
45    let (mut a, mut b) = (src.getter(), dst.getter());
46    while a.has_next() {
47        assert_eq!(a.next(), b.next(), "word mismatch after re-encode");
48    }
49    assert!(!b.has_next());
50    println!("round-trip OK: all {n_words} words identical");
51
52    // If we built a bloom, confirm it accelerates lookups without false negatives.
53    if let Some(s) = salt {
54        let mut r = KvReader::open(&out_kv)?;
55        assert!(
56            r.enable_bloom(Salt::Known(s)),
57            "rebuilt .kvei failed to validate"
58        );
59        let mut checked = 0;
60        for kv in r.iter().step_by(997).take(500) {
61            let (k, v) = kv?;
62            assert_eq!(r.get(&k)?.as_deref(), Some(v.as_slice()));
63            checked += 1;
64        }
65        println!("bloom enabled; {checked} sampled lookups OK");
66    }
67
68    println!("\nOK");
69    Ok(())
70}

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.