Rust · Documents

Documents

use ustore::Docs;use ustore::Binary;use ustore::Bitmap;use ustore::Column;use ustore::ColumnFormat;use ustore::Columns;use ustore::DocsGatherConfig;use ustore::Document;use ustore::DocumentEntry;use ustore::FieldAddress;use ustore::FieldEntry;use ustore::FieldFormat;use ustore::FieldType;use ustore::Half;use ustore::Json;use ustore::KeyedBy;use ustore::Modification;use ustore::Paths;use ustore::ReadFormat;use ustore::Scalar;use ustore::StringColumn;use ustore::Text;use ustore::WritableScalar;use ustore::docs::DocsWrite;use ustore::docs::DocsRemove;use ustore::docs::DocsRemoveRange;use ustore::docs::DocsRead;use ustore::docs::DocsGist;use ustore::docs::DocsGather; 1.0.0-rc.1 · d6d40961

Documents are JSON text, which the engine parses as it writes them. Collection::docs parses what it reads through JsonTape: get hands out a jsontape::Json parsed out of the one-off arena it read through, get_json hands out the text itself as a String, and set writes a jsontape::Json. With the serde feature, get_as deserializes a document into any DeserializeOwned type. ustore::Json names JSON text in the batch verbs below, so JsonTape’s types are always spelled with their jsontape:: prefix.

let mut movies = database.collection("movies")?;
movies.docs().set(avatar, &jsontape::parse(br#"{"title":"Avatar","year":2009}"#)?)?;
let title = movies.docs().get(avatar)?.and_then(|movie| movie["title"].as_str().map(str::to_owned));
let text: Option<String> = movies.docs().get_json(avatar)?;
let fields: Option<BTreeMap<String, jsontape::Json>> = movies.docs().get_as(avatar)?;

The batch verbs carry documents as text both ways and parse nothing on the Rust side. A field is a top-level key or an RFC 6901 pointer, which crosses as the bytes of a &str, so a "/user/name" literal crosses as it stands, and an empty field addresses the whole document. docs_write writes whole documents or fields inside them, and docs_read reads either, as ustore_docs_write and ustore_docs_read do.

use ustore::{Column, Document, DocumentEntry, FieldAddress, FieldEntry, Json, KeyedBy, Modification, Text};

let documents = [DocumentEntry::<Json>::new(ada, r#"{"name":"Ada","born":1815}"#)];
database.head().docs_write(people, &documents, Modification::Upsert, Durability::Buffered)?;

let born = [DocumentEntry::<i64>::new(Key::from(5u64), &1815)];
database.head().docs_write(people, &born, Modification::Upsert, Durability::Buffered)?;

let keyed = [Document::new(r#"{"_id":2,"name":"Grace"}"#)];
database.head().docs_write(people, KeyedBy("_id", &keyed), Modification::Insert, Durability::Buffered)?;

let died = [FieldEntry::<i64>::new(ada, "died", &1852)];
database.head().docs_write(people, &died, Modification::Upsert, Durability::Buffered)?;
let family = [FieldEntry::<Json>::new(ada, "/family", r#"{"father":"Byron"}"#)];
database.head().docs_write(people, &family, Modification::Upsert, Durability::Buffered)?;
let unborn = [DocumentEntry::<Json>::new(ada, r#"{"born":null}"#)];
database.head().docs_write(people, &unborn, Modification::Merge, Durability::Buffered)?;

let whole = database.head().docs_read(people, [ada, grace], Json, &mut arena)?;
let names = database.head().docs_read(people, &[FieldAddress::new(ada, "name")], Text, &mut arena)?;

A write carries one format for the whole batch, named by the type of its entries: a scalar from f64 down to u8 or bool, Text for a JSON string, or Json for any JSON value. The same formats write a whole document, which is then one number, one boolean or one string rather than an object. KeyedBy writes documents that carry their keys under a field of their own: a non-negative integer, spelled as Key::from spells it, or a UUID in canonical text. Mixing two formats in one batch does not compile, and every entry carries a value: On::remove removes whole documents, and a merge carrying a JSON null removes a field. Modification chooses between an upsert, an update, an insert, an RFC 6902 patch and an RFC 7386 merge. Reads hand back the same Values a binary read does, of keys for whole documents or of FieldAddress values for fields, exported in the format named before the arena, Json or printed Text, with a missing document or field reported as None.

Every document verb also takes owned inputs, which a deferred view needs. Whole documents go as keys beside a stringtape::CharsTape of JSON texts, or as the tape alone inside a KeyedBy, and field writes as keys and a CharsTape of paths beside a tape of JSON values. A field read takes keys beside a CharsTape of paths, and a gather a Vec<Column<'static>>, whose Column::new takes a &str or a String.

use ustore::stringtape::CharsTape;

let deferred = database.head().deferred(&executor);
let texts: CharsTape<u64> = [r#"{"name":"Ada"}"#, r#"{"name":"Grace"}"#].into_iter().collect();
deferred.docs_write(people, (vec![ada, grace], texts), Modification::Upsert, Durability::Buffered)?.wait()?;

let paths: CharsTape<u32> = ["name", "name"].into_iter().collect();
let names = deferred.docs_read(people, (vec![ada, grace], paths), Text, &mut arena)?.await?;
assert_eq!(names.get(1), Some(b"Grace".as_slice()));

A gist lists the unique paths to the leaves of a batch of documents as &str pointers, and a gather converts fields into typed columns, a row per key:

let paths = database.head().docs_gist(people, [ada, grace], &mut arena)?;

let columns = [Column::new::<u64>("born"), Column::new::<Text>("name")];
let gathered = database.head().docs_gather(people, &[ada, grace], &columns, &mut other_arena)?;
let born: &[u64] = gathered.scalars::<u64>(0)?;
let valid = gathered.validities(0)?.unwrap().get(1);
let name = gathered.strings(1)?.get(0);

Columns borrow their arena and hold the columns they were asked for, borrowed or owned, and hand out scalar columns as slices straight out of the arena, and string columns as a StringColumn each, whose Text strings come without the null terminator the arena keeps after them. Beside the scalars a gather converts into, Half is a column of IEEE 754 binary16 bit patterns the caller reinterprets and UUID a column of sixteen bytes parsed from canonical text; neither is a format a write carries, and a value that will not fit either leaves its cell zero and sets the collision bit of its row. Every column carries three bitmaps: validity for a value found and converted, conversions for a value whose meaning changed on the way, such as text parsed into a number, and collisions for a value of a type that would not convert. Asking for a column in a type other than the one it was gathered in is refused with Status::InvalidArgument. Paths from one arena address the fields a gather reads through another.

API

StructDocsThe JSON documents of one collection, parsed through JsonTape.4
collection.rs:298 ↗
pub struct Docs<'collection, 'view, Parent = Database>

Every verb consumes the view; Collection::docs hands out the next one.

Implements

Debug
getThe document under key, parsed out of the one-off arena it was read into, or None for a key without one.
collection.rs:304 ↗
pub fn get(self, key: Key) -> Result<Option<Json>>
get_jsonThe document under key as the JSON text the engine holds, or None for a key without one.
collection.rs:309 ↗
pub fn get_json(self, key: Key) -> Result<Option<String>>
setStores document under key, creating the collection to hold documents when it is missing.
collection.rs:326 ↗
pub fn set(self, key: Key, document: &Json) -> Result<()>
removeRemoves the document under key, whether or not the collection holds one.
collection.rs:337 ↗
pub fn remove(self, key: Key) -> Result<()>
StructBinaryA gathered column of printed text without null terminators.
docs.rs:389 ↗
pub struct Binary;

Implements

Clone, Copy, StructuralPartialEq, PartialEq, Eq, Debug, Hash, ColumnFormat
StructBitmapOne bit per row of a batch, least significant bit first.4
docs.rs:1103 ↗
pub struct Bitmap<'arena>

Implements

Clone, Copy, Debug
lenHow many rows the bitmap covers.
docs.rs:1115 ↗
pub fn len(&self) -> usize
is_emptyWhether the bitmap covers no rows.
docs.rs:1120 ↗
pub fn is_empty(&self) -> bool
getWhether the bit of row is set, which a row past the end never is.
docs.rs:1125 ↗
pub fn get(&self, row: usize) -> bool
as_bytesThe bytes of the bitmap, as Arrow reads a validity buffer.
docs.rs:1130 ↗
pub fn as_bytes(&self) -> &'arena [u8]
StructColumnA field to gather from every document, borrowed or owned, and the type to convert it into.1
docs.rs:771 ↗
pub struct Column<'field>

Implements

Clone, Debug
newGathers field, a &str or an owned String, converted into Format.
docs.rs:778 ↗
pub fn new<Format: ColumnFormat>(field: impl Into<Cow<'field, str>>) -> Self
TraitColumnFormatThe format a gathered column converts its values into.
docs.rs:517 ↗
pub trait ColumnFormat: Format

Implementors

StructColumnsThe columns one gather exported, a row per document and a column per requested field, holding the requests that name the format of each.8
docs.rs:1194 ↗
pub struct Columns<'arena, Requested>

A value is valid when it was found and converted, converted when the conversion changed its meaning, such as text parsed into a number, and colliding when a value of an inconvertible type sits there.

Implements

Clone, Copy, Debug
rowsHow many documents the gather read.
docs.rs:1205 ↗
pub fn rows(&self) -> usize
columnsHow many fields the gather read.
docs.rs:1210 ↗
pub fn columns(&self) -> usize
validitiesWhich rows of column hold a value, or None past the last column.
docs.rs:1215 ↗
pub fn validities(&self, column: usize) -> Result<Option<Bitmap<'arena>>>
conversionsWhich rows of column changed their meaning on conversion, or None past the last column.
docs.rs:1220 ↗
pub fn conversions(&self, column: usize) -> Result<Option<Bitmap<'arena>>>
collisionsWhich rows of column hold a value that would not convert, or None past the last column.
docs.rs:1225 ↗
pub fn collisions(&self, column: usize) -> Result<Option<Bitmap<'arena>>>
scalarsThe values of a scalar column, one per row, with zero or a partial conversion in invalid rows.
docs.rs:1230 ↗
pub fn scalars<Value: Scalar>(&self, column: usize) -> Result<&'arena [Value]>
stringsThe values of a column gathered as Text or Binary.
docs.rs:1244 ↗
pub fn strings(&self, column: usize) -> Result<StringColumn<'arena>>
to_arrowEvery column as one Arrow array beside its schema, in request order, or none for a gather that reached no engine.
docs.rs:1289 ↗
pub fn to_arrow(&self) -> Result<Vec<ArrowExport<'arena>>>

Scalars and Binary columns export in place, and Text ones copied without their terminators. The columns of a device arena stay on the device, as ArrowDeviceArray::device_type says. Each export borrows the arena, so the call that would rewind it does not compile while one lives:

use ustore::{Arena, Column, RAMOptions, Database, Key, Modality, Text};

let database = Database::init_ram(&RAMOptions::default())?;
let mut arena = Arena::new()?;
let people = database.collection_create("people", Modality::Docs)?;
let columns = [Column::new::<Text>("name")];
let ada = Key::from(1u64);
let exported = database.head().docs_gather(people, &[ada], &columns, &mut arena)?.to_arrow()?;
database.head().docs_gist(people, [ada], &mut arena)?;
drop(exported);

Calls ustore_docs_column_view_to_arrow.

StructDocsGatherConfigThe typed columns a gather reads; see On::docs_gather.
docs.rs:1026 ↗
pub struct DocsGatherConfig<Requested>

Fields

columnsRequestedThe fields and the format each lands in, borrowed or owned.

Implements

Clone, Copy, Debug, From<Requested>
StructDocumentA document carrying its own key under an id field, which KeyedBy names, laid out so a slice of them crosses through an accessor.1
docs.rs:700 ↗
pub struct Document<'text>

Implements

Clone, Copy, Debug
newBorrows the JSON text of a document.
docs.rs:707 ↗
pub fn new(text: &'text str) -> Self
StructDocumentEntryA document and the key it is stored under, laid out so a slice of them crosses as it stands: the keys as one strided run, and the documents through an accessor over the same entries.2
docs.rs:674 ↗
pub struct DocumentEntry<'value, Format: FieldFormat>

A whole document is written in one format the batch shares: Json for the text the engine parses, Text for a document that is one JSON string, or any WritableScalar for a document that is one number or one boolean.

Implements

Clone, Copy, Debug
newPairs a key with the document to store under it.
docs.rs:682 ↗
pub fn new(key: Key, value: &'value Format::Value) -> Self
keyThe key this entry stores under.
docs.rs:691 ↗
pub fn key(&self) -> Key
StructFieldAddressA field of one document to read, laid out so a slice of them crosses as it stands.1
docs.rs:752 ↗
pub struct FieldAddress<'field>

Implements

Clone, Copy, Debug
newAddresses field of the document under key.
docs.rs:760 ↗
pub fn new(key: Key, field: &'field str) -> Self
StructFieldEntryA field of one document and the value written into it, laid out so a slice of them crosses as it stands.1
docs.rs:730 ↗
pub struct FieldEntry<'value, Format: FieldFormat>

Implements

Clone, Copy, Debug
newPairs a field with the value to write into it.
docs.rs:739 ↗
pub fn new(key: Key, field: &'value str, value: &'value Format::Value) -> Self
TraitFieldFormatThe format of the values one field write carries, which the whole batch shares.2
docs.rs:477 ↗
pub trait FieldFormat: Format

Implementors

ValueWhat a field of this format is written from.
docs.rs:479 ↗
type Value: ?Sized;
*× 3The bytes the ABI reads for value.
docs.rs:482 ↗
fn bytes(value: &Self::Value) -> &[u8]
EnumFieldTypeThe type a field crosses as, which every format above names one of.
docs.rs:577 ↗
pub enum FieldType

Values

Json0JSON text.
Null10The JSON null.
Bool11A boolean.
UUID12A 128-bit UUID.
F6442A 64-bit float.
F3241A 32-bit float.
F1640A 16-bit float.
I6423A signed 64-bit integer.
I3222A signed 32-bit integer.
I1621A signed 16-bit integer.
I820A signed 8-bit integer.
U6433An unsigned 64-bit integer.
U3232An unsigned 32-bit integer.
U1631An unsigned 16-bit integer.
U830An unsigned 8-bit integer.
Binary50The text of a value without a null terminator.
String51A value printed as text.

Implements

Clone, Copy, StructuralPartialEq, PartialEq, Eq, Debug, Default, Hash, Display, FromStr
StructHalfA gathered half-precision float, held as the two bytes of its IEEE 754 binary16 encoding.
docs.rs:397 ↗
pub struct Half(pub u16);

The crate reinterprets nothing: a value whose magnitude will not fit sets the collision bit of its row and leaves the cell zero.

Fields

0u16

Implements

ColumnFormat, Clone, Copy, StructuralPartialEq, PartialEq, Eq, Debug, Default, Hash, Scalar
StructJsonJSON text: a whole value written into a field, or a field read back as the JSON it holds.
docs.rs:381 ↗
pub struct Json;

Implements

Clone, Copy, StructuralPartialEq, PartialEq, Eq, Debug, Hash, FieldFormat, ReadFormat
StructKeyedByDocuments carrying their keys under one field of their own, as a docs write takes them: borrowed Document values, or an owned stringtape::CharsTape of JSON texts, which a deferred write needs beside an owned or 'static field.
docs.rs:719 ↗
pub struct KeyedBy<Field, Texts>(pub Field, pub Texts);

Fields

0FieldThe field holding the key of every document, such as "_id": a non-negative integer, spelled as Key::from spells it, or a UUID in canonical text.
1TextsThe documents.

Implements

Clone, Debug
EnumModificationHow a write combines what it carries with what the document already holds.
docs.rs:526 ↗
pub enum Modification

Values

Upsert0Replaces the document or the field, creating it when missing.
Update1Replaces the document or the field, which must exist.
Insert2Creates the document or the field, which must not exist.
Patch3Applies the carried RFC 6902 patch.
Merge4Applies the carried RFC 7386 merge patch.

Implements

Clone, Copy, StructuralPartialEq, PartialEq, Eq, Debug, Default, Hash, Display, FromStr
StructPathsThe unique paths to the leaves of the documents one gist inspected, in the order they were found.4
docs.rs:1058 ↗
pub struct Paths<'arena>

Implements

Clone, Copy, Debug
lenHow many unique paths the gist found.
docs.rs:1077 ↗
pub fn len(&self) -> usize
is_emptyWhether the gist found no leaves at all.
docs.rs:1082 ↗
pub fn is_empty(&self) -> bool
getThe JSON Pointer at index, ready to address a field, or None past the end.
docs.rs:1087 ↗
pub fn get(&self, index: usize) -> Option<&'arena str>
iterEvery path in the order the gist found it.
docs.rs:1095 ↗
pub fn iter(&self) -> impl Iterator<Item = &'arena str> + 'arena
TraitReadFormatThe format a field read exports its values in.
docs.rs:511 ↗
pub trait ReadFormat: Format

Implementors

TraitScalarA fixed-width value a gathered column converts into.
docs.rs:371 ↗
pub trait Scalar: Format + Copy

Implementors

StructStringColumnA gathered column of strings, whose value in a row is absent unless the row is valid.4
docs.rs:1137 ↗
pub struct StringColumn<'arena>

Implements

Clone, Copy, Debug, IntoIterator
lenHow many rows the column holds.
docs.rs:1146 ↗
pub fn len(&self) -> usize
is_emptyWhether the column holds no rows.
docs.rs:1151 ↗
pub fn is_empty(&self) -> bool
getThe string of row without its terminator, or None for a row whose field was missing or would not convert.
docs.rs:1156 ↗
pub fn get(&self, row: usize) -> Option<&'arena [u8]>
iterEvery row in order.
docs.rs:1165 ↗
pub fn iter(&self) -> Rows<StringColumn<'arena>, Option<&'arena [u8]>>
StructTextA string: a field written as a JSON string, or a value read and gathered as printed text.
docs.rs:385 ↗
pub struct Text;

Implements

Clone, Copy, StructuralPartialEq, PartialEq, Eq, Debug, Hash, FieldFormat, ReadFormat, ColumnFormat
TraitWritableScalarA scalar a write carries into a whole document or into one of its fields.
docs.rs:377 ↗
pub trait WritableScalar: Scalar

Half and UUID are gathered but never written: the engine builds a document from the bytes of a scalar and has no JSON spelling for either.

Implementors

StructDocsWriteA write of whole documents or of fields inside them; see On::docs_write.
docs.rs:1584 ↗
pub struct DocsWrite<'collections, Documents>

Implements

Debug
StructDocsRemoveA removal of a batch of whole documents; see On::docs_remove.
docs.rs:1634 ↗
pub struct DocsRemove<'collections, Keys>

Implements

Debug
StructDocsRemoveRangeA removal of one range of documents; see On::docs_remove_range.
docs.rs:1680 ↗
pub struct DocsRemoveRange

Implements

Debug
StructDocsReadA read of whole documents or of fields inside them; see On::docs_read.
docs.rs:1885 ↗
pub struct DocsRead<'arena, 'collections, Targets>

Implements

Debug
StructDocsGistA listing of the paths to the leaves of documents; see On::docs_gist.
docs.rs:1943 ↗
pub struct DocsGist<'arena, 'collections, Keys>

Implements

Debug
StructDocsGatherA conversion of fields into typed columns; see On::docs_gather.
docs.rs:1990 ↗
pub struct DocsGather<'arena, 'collections, Keys, Requested>

Implements

Debug