Skip to content
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 {
// 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 {
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