[][src]Struct no_proto::buffer_ro::NP_Buffer_RO

pub struct NP_Buffer_RO<'buffer> { /* fields omitted */ }

Buffers contain the bytes of each object and allow you to perform reads, updates, deletes and compaction.

Implementations

impl<'buffer> NP_Buffer_RO<'buffer>[src]

pub fn get_writable(&self) -> NP_Buffer<'_>[src]

Copy this read only buffer into a writable one

pub fn json_encode(&self, path: &[&str]) -> Result<NP_JSON, NP_Error>[src]

Copy an object at the provided path and all it's children into JSON.

use no_proto::error::NP_Error;
use no_proto::NP_Factory;
use no_proto::NP_Size_Data;
 
let factory: NP_Factory = NP_Factory::new(r#"{
   "type": "table",
   "columns": [
        ["age", {"type": "uint8"}],
        ["name", {"type": "string"}]
    ]
}"#)?;
 
let mut new_buffer = factory.empty_buffer(None);
new_buffer.set(&["name"], "Jeb Kermin");
new_buffer.set(&["age"], 30u8);
 
let new_buffer = factory.open_buffer_ro(new_buffer.read_bytes());
 
assert_eq!("{\"age\":30,\"name\":\"Jeb Kermin\"}", new_buffer.json_encode(&[])?.stringify());
assert_eq!("\"Jeb Kermin\"", new_buffer.json_encode(&["name"])?.stringify());
 

pub fn close(self) -> Vec<u8>[src]

Moves the underlying bytes out of the buffer, consuming the buffer in the process.

use no_proto::error::NP_Error;
use no_proto::NP_Factory;
use no_proto::NP_Size_Data;
 
let factory: NP_Factory = NP_Factory::new(r#"{
   "type": "string"
}"#)?;
 
let mut new_buffer = factory.empty_buffer(None);
// set initial value
new_buffer.set(&[], "hello")?;
let new_buffer = factory.open_buffer_ro(new_buffer.read_bytes());
// close buffer and get bytes
let bytes: Vec<u8> = new_buffer.close();
assert_eq!([0, 0, 3, 0, 5, 104, 101, 108, 108, 111].to_vec(), bytes);
 

pub fn close_sortable(self) -> Result<Vec<u8>, NP_Error>[src]

If the buffer is sortable, this provides only the sortable elements of the buffer. There is typically 10 bytes or more in front of the buffer that are identical between all the sortable buffers for a given schema.

This calculates how many leading identical bytes there are and returns only the bytes following them. This allows your sortable buffers to be only as large as they need to be.

This operation fails if the buffer is not sortable.

use no_proto::error::NP_Error;
use no_proto::NP_Factory;
use no_proto::NP_Size_Data;
 
let factory: NP_Factory = NP_Factory::new(r#"{
   "type": "tuple",
   "sorted": true,
   "values": [
        {"type": "u8"},
        {"type": "string", "size": 6}
    ]
}"#)?;
 
let mut new_buffer = factory.empty_buffer(None);
// set initial value
new_buffer.set(&["0"], 55u8)?;
new_buffer.set(&["1"], "hello")?;
 
// the buffer with it's vtables take up 20 bytes!
assert_eq!(new_buffer.read_bytes().len(), 20usize);
 
// close buffer and get sortable bytes
let bytes: Vec<u8> = factory.open_buffer_ro(new_buffer.read_bytes()).close_sortable()?;
// with close_sortable() we only get the bytes we care about!
assert_eq!([55, 104, 101, 108, 108, 111, 32].to_vec(), bytes);
 
// you can always re open the sortable buffers with this call
let new_buffer = factory.open_sortable_buffer(bytes)?;
assert_eq!(new_buffer.get(&["0"])?, Some(55u8));
assert_eq!(new_buffer.get(&["1"])?, Some("hello "));
 

pub fn read_bytes(&self) -> &[u8][src]

Read the bytes of the buffer immutably. No touching!

pub fn move_cursor(&mut self, path: &[&str]) -> Result<bool, NP_Error>[src]

Move buffer cursor to new location. Cursors can only be moved into children. If you need to move up reset the cursor to root, then move back down to the desired level.

If you attempt to move into a path that doesn't exist, this method will return false.

pub fn cursor_to_root(&mut self)[src]

Moves cursor position to root of buffer, the default.

pub fn get_iter<'iter>(
    &'iter self,
    path: &'iter [&str]
) -> Result<Option<NP_Generic_Iterator<'iter>>, NP_Error>
[src]

Get an iterator for a collection

List Example

use no_proto::error::NP_Error;
use no_proto::NP_Factory;
use no_proto::NP_Size_Data;
 
let factory: NP_Factory = NP_Factory::new(r#"{
   "type": "list",
    "of": {"type": "string"}
}"#)?;
 
let mut new_buffer = factory.empty_buffer(None);
// set value at 1 index
new_buffer.set(&["1"], "hello")?;
// set value at 4 index
new_buffer.set(&["4"], "world")?;
// push value onto the end
new_buffer.list_push(&[], "!")?;
 
// get iterator of root (list item)
factory.open_buffer_ro(new_buffer.read_bytes()).get_iter(&[])?.unwrap().into_iter().for_each(|item| {
    match item.index {
        0 => assert_eq!(item.get::<&str>().unwrap(), None),
        1 => assert_eq!(item.get::<&str>().unwrap(), Some("hello")),
        2 => assert_eq!(item.get::<&str>().unwrap(), None),
        3 => assert_eq!(item.get::<&str>().unwrap(), None),
        4 => assert_eq!(item.get::<&str>().unwrap(), Some("world")),
        5 => assert_eq!(item.get::<&str>().unwrap(), Some("!")),
        _ => panic!()
    };
});
 

Table Example

use no_proto::error::NP_Error;
use no_proto::NP_Factory;
use no_proto::NP_Size_Data;
 
let factory: NP_Factory = NP_Factory::new(r#"{
   "type": "table",
   "columns": [
        ["age", {"type": "uint8"}],
        ["name", {"type": "string"}],
        ["job", {"type": "string"}],
        ["tags", {"type": "list", "of": {"type": "string"}}]
    ]
}"#)?;
 
let mut new_buffer = factory.empty_buffer(None);
// set value of age
new_buffer.set(&["age"], 20u8)?;
// set value of name
new_buffer.set(&["name"], "Bill Kerman")?;
// push value onto tags list
new_buffer.list_push(&["tags"], "rocket")?;
 
// get iterator of root (table)
factory.open_buffer_ro(new_buffer.read_bytes()).get_iter(&[])?.unwrap().into_iter().for_each(|item| {
     
    match item.key {
        "name" => assert_eq!(item.get::<&str>().unwrap(), Some("Bill Kerman")),
        "age" =>  assert_eq!(item.get::<u8>().unwrap(), Some(20)),
        "job" => assert_eq!(item.get::<&str>().unwrap(), None),
        "tags" => { /* tags column is list, can't do anything with it here */ },
        _ => { panic!() }
    };
});
 
// we can also loop through items of the tags list
factory.open_buffer_ro(new_buffer.read_bytes()).get_iter(&["tags"])?.unwrap().into_iter().for_each(|item| {
    assert_eq!(item.index, 0);
    assert_eq!(item.get::<&str>().unwrap(), Some("rocket"));
});
 

Map Example

use no_proto::error::NP_Error;
use no_proto::NP_Factory;
use no_proto::NP_Size_Data;
 
let factory: NP_Factory = NP_Factory::new(r#"{
   "type": "map",
   "value": {"type": "string"}
}"#)?;
 
let mut new_buffer = factory.empty_buffer(None);
// set value of color key
new_buffer.set(&["color"], "blue")?;
// set value of sport key
new_buffer.set(&["sport"], "soccor")?;
 
// get iterator of root (map)
factory.open_buffer_ro(new_buffer.read_bytes()).get_iter(&[])?.unwrap().into_iter().for_each(|item| {
     
    match item.key {
        "color" => assert_eq!(item.get::<&str>().unwrap(), Some("blue")),
        "sport" => assert_eq!(item.get::<&str>().unwrap(), Some("soccor")),
        _ => panic!()
    }
});
 

Tuple Example

use no_proto::error::NP_Error;
use no_proto::NP_Factory;
use no_proto::NP_Size_Data;
 
let factory: NP_Factory = NP_Factory::new(r#"{
   "type": "tuple",
    "values": [
        {"type": "string"},
        {"type": "u8"},
        {"type": "bool"}
    ]
}"#)?;
 
let mut new_buffer = factory.empty_buffer(None);
// set value at 0 index
new_buffer.set(&["0"], "hello")?;
// set value at 2 index
new_buffer.set(&["2"], false)?;
 
// get iterator of root (tuple item)
factory.open_buffer_ro(new_buffer.read_bytes()).get_iter(&[])?.unwrap().into_iter().for_each(|item| {
    match item.index {
        0 => assert_eq!(item.get::<&str>().unwrap(), Some("hello")),
        1 => assert_eq!(item.get::<u8>().unwrap(), None),
        2 => assert_eq!(item.get::<bool>().unwrap(), Some(false)),
        _ => panic!()
    };
});
 

pub fn length(&self, path: &[&str]) -> Result<Option<usize>, NP_Error>[src]

Get length of String, Bytes, Table, Tuple, List or Map Type

If the type found at the path provided does not support length operations, you'll get None.

If there is no value at the path provodid, you will get None.

If an item is found and it's length is zero, you can expect Some(0).

String Example

use no_proto::error::NP_Error;
use no_proto::NP_Factory;
use no_proto::NP_Size_Data;
 
let factory: NP_Factory = NP_Factory::new(r#"{
   "type": "string"
}"#)?;
 
let mut new_buffer = factory.empty_buffer(None);
// set initial value
new_buffer.set(&[], "hello")?;
// get length of value at root (String)
assert_eq!(factory.open_buffer_ro(new_buffer.read_bytes()).length(&[])?, Some(5));
 

Collection (List) Example

use no_proto::error::NP_Error;
use no_proto::NP_Factory;
use no_proto::NP_Size_Data;
 
let factory: NP_Factory = NP_Factory::new(r#"{
   "type": "list",
    "of": {"type": "string"}
}"#)?;
 
let mut new_buffer = factory.empty_buffer(None);
// set value at 9th index
new_buffer.set(&["9"], "hello")?;
// get length of value at root (List)
assert_eq!(factory.open_buffer_ro(new_buffer.read_bytes()).length(&[])?, Some(10));
 

Collection (Table) Example

use no_proto::error::NP_Error;
use no_proto::NP_Factory;
use no_proto::NP_Size_Data;
 
let factory: NP_Factory = NP_Factory::new(r#"{
   "type": "table",
   "columns": [
        ["age", {"type": "u8"}],
        ["name", {"type": "string"}]
    ]
}"#)?;
 
let mut new_buffer = factory.empty_buffer(None);
// get length of value at root (Table)
assert_eq!(factory.open_buffer_ro(new_buffer.read_bytes()).length(&[])?, Some(2));
 

Collection (Map) Example

use no_proto::error::NP_Error;
use no_proto::NP_Factory;
use no_proto::NP_Size_Data;
 
let factory: NP_Factory = NP_Factory::new(r#"{
   "type": "map",
   "value": {"type": "string"}
}"#)?;
 
let mut new_buffer = factory.empty_buffer(None);
// set values
new_buffer.set(&["foo"], "bar")?;
new_buffer.set(&["foo2"], "bar2")?;
// get length of value at root (Map)
assert_eq!(factory.open_buffer_ro(new_buffer.read_bytes()).length(&[])?, Some(2));
 

Collection (Tuple) Example

use no_proto::error::NP_Error;
use no_proto::NP_Factory;
use no_proto::NP_Size_Data;
 
let factory: NP_Factory = NP_Factory::new(r#"{
   "type": "tuple",
   "values": [
        {"type": "string"}, 
        {"type": "string"}
    ]
}"#)?;
 
let mut new_buffer = factory.empty_buffer(None);
// get length of value at root (Tuple)
assert_eq!(factory.open_buffer_ro(new_buffer.read_bytes()).length(&[])?, Some(2));
 

pub fn get_schema_type(
    &self,
    path: &[&str]
) -> Result<Option<NP_TypeKeys>, NP_Error>
[src]

Retrieve the schema type at a given path.

use no_proto::error::NP_Error;
use no_proto::NP_Factory;
use no_proto::schema::NP_TypeKeys;
 
// a list where each item is a map where each key has a value containing a list of strings
let factory: NP_Factory = NP_Factory::new(r#"{
   "type": "tuple",
   "values": [
        {"type": "geo8"},
        {"type": "dec", "exp": 2},
        {"type": "string"}
    ]
}"#)?;
 
let mut new_buffer = factory.empty_buffer(None);
let new_buffer = factory.open_buffer_ro(new_buffer.read_bytes());
 
assert_eq!(new_buffer.get_schema_type(&[])?.unwrap(), NP_TypeKeys::Tuple);
assert_eq!(new_buffer.get_schema_type(&["0"])?.unwrap(), NP_TypeKeys::Geo);
assert_eq!(new_buffer.get_schema_type(&["1"])?.unwrap(), NP_TypeKeys::Decimal);
assert_eq!(new_buffer.get_schema_type(&["2"])?.unwrap(), NP_TypeKeys::UTF8String);
 

pub fn get_schema_default<'get, X: 'get>(
    &'get self,
    path: &[&str]
) -> Result<Option<X>, NP_Error> where
    X: NP_Value<'get> + NP_Scalar<'get>, 
[src]

Retrieve the schema default at a given path.

This is useful for geo and dec data types where there is information about the value in the schema.

For example, when you create an NP_Geo type to put into a geo field, you must know the resolution (4/8/16). If you use this method you can get an empty NP_Geo type that already has the correct resolution set based on the schema.

The type that you cast the request to will be compared to the schema, if it doesn't match the schema the request will fail.

use no_proto::error::NP_Error;
use no_proto::NP_Factory;
use no_proto::pointer::dec::NP_Dec;
use no_proto::pointer::geo::NP_Geo;
 
// a list where each item is a map where each key has a value containing a list of strings
let factory: NP_Factory = NP_Factory::new(r#"{
   "type": "tuple",
   "values": [
        {"type": "geo8"},
        {"type": "dec", "exp": 2}
    ]
}"#)?;
 
let mut new_buffer = factory.empty_buffer(None);
let new_buffer = factory.open_buffer_ro(new_buffer.read_bytes());
 
// Get an empty NP_Geo type that has the correct resolution for the schema
// 
let geo_default: NP_Geo = new_buffer.get_schema_default::<NP_Geo>(&["0"])?.unwrap();
assert_eq!(geo_default.size, 8); // geo is size 8 in schema
 
// Get an empty NP_Dec type that has the correct exp for the schema
// 
let dec_default: NP_Dec = new_buffer.get_schema_default::<NP_Dec>(&["1"])?.unwrap();
assert_eq!(dec_default.exp, 2); // exponent is 2 in schema
 

pub fn get<'get, X: 'get>(
    &'get self,
    path: &[&str]
) -> Result<Option<X>, NP_Error> where
    X: NP_Value<'get> + NP_Scalar<'get>, 
[src]

Retrieve an inner value from the buffer.

The type that you cast the request to will be compared to the schema, if it doesn't match the schema the request will fail.

use no_proto::error::NP_Error;
use no_proto::NP_Factory;
use no_proto::NP_Size_Data;
 
// a list where each item is a map where each key has a value containing a list of strings
let factory: NP_Factory = NP_Factory::new(r#"{
   "type": "list",
   "of": {"type": "map", "value": {
        "type": "list", "of": {"type": "string"}
    }}
}"#)?;
 
let mut new_buffer = factory.empty_buffer(None);
// third item in the top level list -> key "alpha" of map at 3rd element -> 9th element of list at "alpha" key
// 
new_buffer.set(&["3", "alpha", "9"], "who would build a schema like this")?;
 
// get the same item we just set
let ro_buffer = factory.open_buffer_ro(new_buffer.read_bytes());
let message = ro_buffer.get::<&str>(&["3", "alpha", "9"])?;
 
assert_eq!(message, Some("who would build a schema like this"));
 

pub fn maybe_compact<F>(
    &mut self,
    new_capacity: Option<usize>,
    callback: F
) -> Result<NP_Buffer<'_>, NP_Error> where
    F: FnMut(NP_Size_Data) -> bool, 
[src]

This performs a compaction if the closure provided as the second argument returns true. Compaction is a pretty expensive operation (requires full copy of the whole buffer) so should be done sparingly.

For read only buffers the compaction method compacts into a writable buffer.

The closure is provided an argument that contains the original size of the buffer, how many bytes could be saved by compaction, and how large the new buffer would be after compaction. The closure should return true to perform compaction, false otherwise.

The first argument, new_capacity, is the capacity of the underlying Vec that we'll be copying the data into. The default is the size of the old buffer.

WARNING Your cursor location will be reset to the root.

pub fn compact<'compact>(
    &mut self,
    new_capacity: Option<usize>
) -> Result<NP_Buffer<'_>, NP_Error>
[src]

Compacts a buffer to remove an unused bytes or free space after a mutation. This is a pretty expensive operation (requires full copy of the whole buffer) so should be done sparingly.

For read only buffers the compaction method compacts into a writable buffer.

The first argument, new_capacity, is the capacity of the underlying Vec that we'll be copying the data into. The default is the size of the old buffer.

WARNING Your cursor location will be reset to the root.

pub fn calc_bytes<'bytes>(&self) -> Result<NP_Size_Data, NP_Error>[src]

Recursively measures how many bytes each element in the buffer is using. This will let you know how many bytes can be saved from a compaction.

use no_proto::error::NP_Error;
use no_proto::NP_Factory;
use no_proto::NP_Size_Data;
 
let factory: NP_Factory = NP_Factory::new(r#"{
   "type": "string"
}"#)?;
 
let mut new_buffer = factory.empty_buffer(None);
new_buffer.set(&[], "hello")?;
assert_eq!(NP_Size_Data {
    current_buffer: 10,
    after_compaction: 10,
    wasted_bytes: 0
}, factory.open_buffer_ro(new_buffer.read_bytes()).calc_bytes()?);
 

Trait Implementations

impl<'buffer> Clone for NP_Buffer_RO<'buffer>[src]

impl<'buffer> Debug for NP_Buffer_RO<'buffer>[src]

Auto Trait Implementations

impl<'buffer> Send for NP_Buffer_RO<'buffer>[src]

impl<'buffer> Sync for NP_Buffer_RO<'buffer>[src]

impl<'buffer> Unpin for NP_Buffer_RO<'buffer>[src]

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

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

The type returned in the event of a conversion error.