[−][src]Struct no_proto::buffer_ro::NP_Buffer_RO
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]
&'iter self,
path: &'iter [&str]
) -> Result<Option<NP_Generic_Iterator<'iter>>, NP_Error>
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]
&self,
path: &[&str]
) -> Result<Option<NP_TypeKeys>, NP_Error>
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]
&'get self,
path: &[&str]
) -> Result<Option<X>, NP_Error> where
X: NP_Value<'get> + NP_Scalar<'get>,
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]
&'get self,
path: &[&str]
) -> Result<Option<X>, NP_Error> where
X: NP_Value<'get> + NP_Scalar<'get>,
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]
&mut self,
new_capacity: Option<usize>,
callback: F
) -> Result<NP_Buffer<'_>, NP_Error> where
F: FnMut(NP_Size_Data) -> bool,
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
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]
&mut self,
new_capacity: Option<usize>
) -> Result<NP_Buffer<'_>, NP_Error>
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
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]
pub fn clone(&self) -> Self
[src]
pub fn clone_from(&mut self, source: &Self)
1.0.0[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]
T: 'static + ?Sized,
impl<T> Borrow<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
[src]
T: ?Sized,
pub fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> From<T> for T
[src]
impl<T, U> Into<U> for T where
U: From<T>,
[src]
U: From<T>,
impl<T> ToOwned for T where
T: Clone,
[src]
T: Clone,
type Owned = T
The resulting type after obtaining ownership.
pub fn to_owned(&self) -> T
[src]
pub fn clone_into(&self, target: &mut T)
[src]
impl<T, U> TryFrom<U> for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
pub fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,