Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix #156: tuples encoding at depth 0 #157

Open
wants to merge 1 commit into
base: 0.3
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 65 additions & 30 deletions foundationdb/src/tuple/element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,11 +258,13 @@ impl Decode for String {

impl Encode for Vec<Element> {
fn encode<W: Write>(&self, w: &mut W, tuple_depth: TupleDepth) -> std::io::Result<()> {
// TODO: should this only write the Nested markers in the case of tuple_depth?
NESTED.write(w)?;
if tuple_depth.depth() > 0 {
NESTED.write(w)?;
}

for v in self {
match v {
&Element::Empty => {
&Element::Empty if tuple_depth.depth() > 0 => {
// Empty value in nested tuple is encoded with [NIL, ESCAPE] to disambiguate
// itself with end-of-tuple marker.
NIL.write(w)?;
Expand All @@ -273,29 +275,38 @@ impl Encode for Vec<Element> {
}
}
}
NIL.write(w)

if tuple_depth.depth() > 0 {
NIL.write(w)?;
}

Ok(())
}
}

impl Decode for Vec<Element> {
fn decode(mut buf: &[u8], tuple_depth: TupleDepth) -> Result<(Self, usize)> {
if buf.len() < 2 {
if tuple_depth.depth() > 0 && buf.len() < 2 {
return Err(Error::EOF);
}

// TODO: should this only write the Nested markers in the case of tuple_depth?
NESTED.expect(buf[0])?;
let len = buf.len();
buf = &buf[1..];
let nested = buf.len() > 0 && buf[0] == NESTED;
if nested {
buf = &buf[1..];
}

let mut tuples = Vec::new();
loop {
if buf.is_empty() {
// tuple must end with NIL byte
return Err(Error::EOF);
if nested {
Speedy37 marked this conversation as resolved.
Show resolved Hide resolved
// tuple must end with NIL byte
return Err(Error::EOF);
}
break;
}

if buf[0] == NIL {
if nested && buf[0] == NIL {
if buf.len() > 1 && buf[1] == ESCAPE {
// nested Empty value, which is encoded to [NIL, ESCAPE]
tuples.push(Element::Empty);
Expand All @@ -312,6 +323,17 @@ impl Decode for Vec<Element> {
buf = &buf[offset..];
}

if nested && tuple_depth.depth() == 0 && buf.len() > 0 {
Speedy37 marked this conversation as resolved.
Show resolved Hide resolved
let mut root = Vec::new();
root.push(Element::Tuple(Tuple(tuples)));
while buf.len() > 0 {
let (tuple, offset) = Element::decode(buf, tuple_depth.increment())?;
root.push(tuple);
buf = &buf[offset..];
}
tuples = root;
}

// skip the final null
Ok((tuples, len - buf.len()))
}
Expand Down Expand Up @@ -543,51 +565,65 @@ impl Encode for Element {
}

impl Decode for Element {
fn decode(buf: &[u8], tuple_depth: TupleDepth) -> Result<(Self, usize)> {
fn decode(mut buf: &[u8], tuple_depth: TupleDepth) -> Result<(Self, usize)> {
if buf.is_empty() {
return Err(Error::EOF);
}

let code = buf[0];
match code {
NIL => Ok((Element::Empty, 1)),
let (mut el, mut offset) = match code {
NIL => (Element::Empty, 1),
BYTES => {
let (v, offset) = Decode::decode(buf, tuple_depth)?;
Ok((Element::Bytes(v), offset))
(Element::Bytes(v), offset)
}
STRING => {
let (v, offset) = Decode::decode(buf, tuple_depth)?;
Ok((Element::String(v), offset))
(Element::String(v), offset)
}
FLOAT => {
let (v, offset) = Decode::decode(buf, tuple_depth)?;
Ok((Element::F32(v), offset))
(Element::F32(v), offset)
}
DOUBLE => {
let (v, offset) = Decode::decode(buf, tuple_depth)?;
Ok((Element::F64(v), offset))
(Element::F64(v), offset)
}
FALSE => Ok((Element::Bool(false), 1)),
TRUE => Ok((Element::Bool(true), 1)),
FALSE => (Element::Bool(false), 1),
TRUE => (Element::Bool(true), 1),
#[cfg(feature = "uuid")]
UUID => {
let (v, offset) = Decode::decode(buf, tuple_depth)?;
Ok((Element::Uuid(v), offset))
(Element::Uuid(v), offset)
}
NESTED => {
let (v, offset) = Decode::decode(buf, tuple_depth)?;
Ok((Element::Tuple(Tuple(v)), offset))
(Element::Tuple(Tuple(v)), offset)
}
val => {
if val >= NEGINTSTART && val <= POSINTEND {
let (v, offset) = Decode::decode(buf, tuple_depth)?;
Ok((Element::I64(v), offset))
(Element::I64(v), offset)
} else {
//TODO: Versionstamp, ...
Err(Error::InvalidData)
return Err(Error::InvalidData);
}
}
};
buf = &buf[offset..];

if buf.len() > 0 && tuple_depth.depth() == 0 {
let mut root = vec![el];
while buf.len() > 0 {
let (sub_el, sub_offset) = Element::decode(buf, tuple_depth.increment())?;
root.push(sub_el);
offset += sub_offset;
buf = &buf[sub_offset..];
}
el = Element::Tuple(Tuple(root));
}

Ok((el, offset))
}
}

Expand Down Expand Up @@ -649,27 +685,26 @@ mod tests {
Element::I64(42),
])),
&[
NESTED, /*hello*/ 2, 104, 101, 108, 108, 111, 0, /*world*/ 2, 119, 111,
114, 108, 100, 0, /*42*/ 21, 42, /*end nested*/
NIL,
/*hello*/ 2, 104, 101, 108, 108, 111, 0, /*world*/ 2, 119, 111,
114, 108, 100, 0, /*42*/ 21, 42,
],
);

test_round_trip(
Element::Tuple(Tuple(vec![
Element::Bytes(vec![0]),
Element::Empty,
Element::Tuple(Tuple(vec![Element::Bytes(vec![0]), Element::Empty])),
])),
&[5, 1, 0, 255, 0, 0, 255, 5, 1, 0, 255, 0, 0, 255, 0, 0],
&[1, 0, 255, NIL, NIL, NESTED, 1, 0, 255, 0, NIL, 255, NIL],
);

test_round_trip(
Element::Tuple(Tuple(vec![
Element::Bool(true),
Element::Tuple(Tuple(vec![Element::Bool(false)])),
])),
&[NESTED, 39, NESTED, 38, NIL, NIL],
&[39, NESTED, 38, NIL],
);
}

Expand Down
15 changes: 2 additions & 13 deletions foundationdb/src/tuple/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,24 +238,13 @@ tuple_impls! {

impl Encode for Tuple {
fn encode<W: Write>(&self, w: &mut W, tuple_depth: TupleDepth) -> std::io::Result<()> {
for element in self.0.iter() {
element.encode(w, tuple_depth.increment())?;
}
Ok(())
self.0.encode(w, tuple_depth)
}
}

impl Decode for Tuple {
fn decode(buf: &[u8], tuple_depth: TupleDepth) -> Result<(Self, usize)> {
let mut data = buf;
let mut v = Vec::new();
let mut offset = 0_usize;
while !data.is_empty() {
let (s, len): (Element, _) = Element::decode(data, tuple_depth.increment())?;
v.push(s);
offset += len;
data = &data[len..];
}
let (v, offset) = Vec::<Element>::decode(buf, tuple_depth)?;
Ok((Tuple(v), offset))
}
}
Expand Down