This library provides tools to sort, merge, write, and read immutable key-value pairs. The entries in the grenad files are immutable and the only way to modify them is by creating a new file with the changes.

Example: Use the Writer and Reader structs

You can use the [Writer] struct to store key-value pairs into the specified [std::io::Write] type. The [Reader] type can then be used to read the entries.

The entries provided to the [Writer] struct must be given in lexicographic order.

```rust use std::io::Cursor;

use grenad::{Reader, Writer};

fn main() -> Result<(), Box> {

let mut writer = Writer::memory();

// We insert our key-value pairs in lexicographic order. writer.insert("first-counter", 119u32.tonebytes())?; writer.insert("second-counter", 384u32.tonebytes())?;

// We create a reader from our writer. let cursor = writer.intoinner().map(Cursor::new)?; let mut cursor = Reader::new(cursor)?.intocursor()?;

// We can see that the sum of u32s is valid here. asserteq!(cursor.moveonnext()?, Some((&b"first-counter"[..], &119u32.tonebytes()[..]))); asserteq!(cursor.moveonnext()?, Some((&b"second-counter"[..], &384u32.tonebytes()[..]))); asserteq!(cursor.moveon_next()?, None);

// We can also jum on any given entry. asserteq!(cursor.moveonkeygreaterthanorequalto("first")?, Some((&b"first-counter"[..], &119u32.tonebytes()[..]))); asserteq!(cursor.moveonkeyequalto("second-counter")?, Some((&b"second-counter"[..], &384u32.tonebytes()[..]))); asserteq!(cursor.moveonkeylowerthanorequal_to("abracadabra")?, None);

Ok(()) }

```

Example: Use the Merger struct

In this example we show how you can merge multiple [Reader]s by using a merge function when a conflict is encountered.

The entries yielded by the [Merger] struct are returned in lexicographic order, a good way to write them back into a new [Writer].

```rust use std::array::TryFromSliceError; use std::borrow::Cow; use std::convert::TryInto; use std::io::Cursor;

use grenad::{MergerBuilder, Reader, Writer};

// This merge function: // - parses u32s from native-endian bytes, // - wrapping sums them and, // - outputs the result as native-endian bytes. fn wrappingsumu32s<'a>( key: &[u8], values: &[Cow<'a, [u8]>], ) -> Result { let mut output: u32 = 0; for bytes in values.iter().map(AsRef::asref) { let num = bytes.tryinto().map(u32::fromnebytes)?; output = output.wrappingadd(num); } Ok(Cow::Owned(output.tonebytes().to_vec())) }

fn main() -> Result<(), Box> {

// We create our writers in memory to insert our key-value pairs. let mut writera = Writer::memory(); let mut writerb = Writer::memory(); let mut writerc = Writer::memory();

// We insert our key-value pairs in lexicographic order // and mix them between our writers. writera.insert("first-counter", 32u32.tonebytes())?; writera.insert("second-counter", 64u32.tonebytes())?; writerb.insert("first-counter", 23u32.tonebytes())?; writerb.insert("second-counter", 320u32.tonebytes())?; writerc.insert("first-counter", 64u32.tone_bytes())?;

// We create readers from our writers. let cursora = writera.intoinner().map(Cursor::new)?; let cursorb = writerb.intoinner().map(Cursor::new)?; let cursorc = writerc.intoinner().map(Cursor::new)?; let readera = Reader::new(cursora)?.intocursor()?; let readerb = Reader::new(cursorb)?.intocursor()?; let readerc = Reader::new(cursorc)?.intocursor()?;

// We create a merger that will sum our u32s when necessary, // and we add our readers to the list of readers to merge. let mergerbuilder = MergerBuilder::new(wrappingsumu32s); let merger = mergerbuilder.add(readera).add(readerb).add(readerc).build();

// We can iterate over the entries in key-order. let mut iter = merger.intostreammerger_iter()?;

// We can see that the sum of u32s is valid here. asserteq!(iter.next()?, Some((&b"first-counter"[..], &119u32.tonebytes()[..]))); asserteq!(iter.next()?, Some((&b"second-counter"[..], &384u32.tonebytes()[..]))); assert_eq!(iter.next()?, None);

Ok(()) }

```

Example: Use the Sorter struct

In this example we show how by defining a merge function, we can insert multiple entries with the same key and output them in lexicographic order.

The [Sorter] accepts the entries in any given order, will reorder them in-memory and merge them with the merge function when required. It is authorized to have a memory budget during its construction and will try to follow it as closely as possible.

```rust use std::array::TryFromSliceError; use std::borrow::Cow; use std::convert::TryInto;

use grenad::{CursorVec, SorterBuilder};

// This merge function: // - parses u32s from native-endian bytes, // - wrapping sums them and, // - outputs the result as native-endian bytes. fn wrappingsumu32s<'a>( key: &[u8], values: &[Cow<'a, [u8]>], ) -> Result { let mut output: u32 = 0; for bytes in values.iter().map(AsRef::asref) { let num = bytes.tryinto().map(u32::fromnebytes)?; output = output.wrappingadd(num); } Ok(Cow::Owned(output.tonebytes().to_vec())) }

fn main() -> Result<(), Box> {

// We create a sorter that will sum our u32s when necessary. let mut sorter = SorterBuilder::new(wrappingsumu32s).chunk_creator(CursorVec).build();

// We insert multiple entries with the same key but different values // in arbitrary order, the sorter will take care of merging them for us. sorter.insert("first-counter", 32u32.tonebytes())?; sorter.insert("first-counter", 23u32.tonebytes())?; sorter.insert("first-counter", 64u32.tone_bytes())?;

sorter.insert("second-counter", 320u32.tonebytes())?; sorter.insert("second-counter", 64u32.tonebytes())?;

// We can iterate over the entries in key-order. let mut iter = sorter.intostreammerger_iter()?;

// We can see that the sum of u32s is valid here. asserteq!(iter.next()?, Some((&b"first-counter"[..], &119u32.tonebytes()[..]))); asserteq!(iter.next()?, Some((&b"second-counter"[..], &384u32.tonebytes()[..]))); assert_eq!(iter.next()?, None);

Ok(()) }

```