From 36a834c1e3c754cf10c71096734eebd0b52ce9cd Mon Sep 17 00:00:00 2001 From: Fernando Herrera Date: Sun, 24 Oct 2021 13:20:01 +0100 Subject: [PATCH] encode list --- crates/nu-plugin/src/lib.rs | 204 +++++++++++++++++++++--------------- 1 file changed, 122 insertions(+), 82 deletions(-) diff --git a/crates/nu-plugin/src/lib.rs b/crates/nu-plugin/src/lib.rs index 0e822c5c3f..2a296e6ad4 100644 --- a/crates/nu-plugin/src/lib.rs +++ b/crates/nu-plugin/src/lib.rs @@ -8,79 +8,55 @@ pub mod plugin_value { use capnp::serialize_packed; use nu_protocol::{Span, Value}; - pub fn serialize_value(value: &Value, writer: &mut impl std::io::Write) -> capnp::Result<()> { + pub fn serialize_message(value: &Value, writer: &mut impl std::io::Write) -> capnp::Result<()> { let mut message = ::capnp::message::Builder::new_default(); - { - let mut serialized_value = message.init_root::(); + let mut builder = message.init_root::(); - let value_span = match value { - Value::Nothing { span } => { - serialized_value.set_void(()); - *span - } - Value::Bool { val, span } => { - serialized_value.set_bool(*val); - *span - } - Value::Int { val, span } => { - serialized_value.set_int(*val); - *span - } - Value::Float { val, span } => { - serialized_value.set_float(*val); - *span - } - Value::String { val, span } => { - serialized_value.set_string(&val); - *span - } - Value::List { vals, span } => { - { - serialize_list(vals, &mut serialized_value); - } - *span - } - _ => Span::unknown(), - }; - - { - let mut span = serialized_value.reborrow().init_span(); - span.set_start(value_span.start as u64); - span.set_end(value_span.end as u64); - } - } + let value_span = serialize_value(value, builder.reborrow()); + let mut span = builder.reborrow().init_span(); + span.set_start(value_span.start as u64); + span.set_end(value_span.end as u64); serialize_packed::write_message(writer, &message) } - fn serialize_list(vals: &[Value], builder: &mut value::Builder) { - let mut list_builder = builder.reborrow().init_list(vals.len() as u32); - - for (index, val) in vals.iter().enumerate() { - match val { - Value::Nothing { .. } => { - list_builder.reborrow().get(index as u32).set_void(()); - } - Value::Bool { val, .. } => { - list_builder.reborrow().get(index as u32).set_bool(*val); - } - Value::Int { val, .. } => { - list_builder.reborrow().get(index as u32).set_int(*val); - } - Value::Float { val, .. } => { - list_builder.reborrow().get(index as u32).set_float(*val); - } - Value::String { val, .. } => { - list_builder.reborrow().get(index as u32).set_string(val); - } - Value::List { vals, .. } => serialize_list(vals, builder), - _ => {} + fn serialize_value(value: &Value, mut builder: value::Builder) -> Span { + match value { + Value::Nothing { span } => { + builder.set_void(()); + *span } + Value::Bool { val, span } => { + builder.set_bool(*val); + *span + } + Value::Int { val, span } => { + builder.set_int(*val); + *span + } + Value::Float { val, span } => { + builder.set_float(*val); + *span + } + Value::String { val, span } => { + builder.set_string(&val); + *span + } + Value::List { vals, span } => { + let mut list_builder = builder.reborrow().init_list(vals.len() as u32); + for (index, value) in vals.iter().enumerate() { + let inner_builder = list_builder.reborrow().get(index as u32); + serialize_value(value, inner_builder); + } + + *span + } + _ => Span::unknown(), } } - pub fn deserialize_value(reader: &mut impl std::io::BufRead) -> Value { + pub fn deserialize_message(reader: &mut impl std::io::BufRead) -> Value { let message_reader = serialize_packed::read_message(reader, ::capnp::message::ReaderOptions::new()).unwrap(); @@ -92,7 +68,11 @@ pub mod plugin_value { end: span_reader.get_end() as usize, }; - match plugin_value.which() { + deserialize_value(span, plugin_value.reborrow()) + } + + fn deserialize_value(span: Span, reader: value::Reader) -> Value { + match reader.which() { Ok(value::Void(())) => Value::Nothing { span }, Ok(value::Bool(val)) => Value::Bool { val, span }, Ok(value::Int(val)) => Value::Int { val, span }, @@ -101,9 +81,32 @@ pub mod plugin_value { val: val.unwrap().to_string(), span, }, - Ok(value::List(_)) => Value::Nothing { - span: Span::unknown(), - }, + Ok(value::List(vals)) => { + let values = vals.expect("something"); + + let values_list = values + .iter() + .map(|value| match value.which() { + Ok(value::Void(())) => Value::Nothing { span }, + Ok(value::Bool(val)) => Value::Bool { val, span }, + Ok(value::Int(val)) => Value::Int { val, span }, + Ok(value::Float(val)) => Value::Float { val, span }, + Ok(value::String(val)) => Value::String { + val: val.unwrap().to_string(), + span, + }, + Ok(value::List(_)) => Value::Nothing { span }, + Err(capnp::NotInSchema(_)) => Value::Nothing { + span: Span::unknown(), + }, + }) + .collect::>(); + + Value::List { + vals: values_list, + span, + } + } Err(capnp::NotInSchema(_)) => Value::Nothing { span: Span::unknown(), }, @@ -139,27 +142,64 @@ mod tests { for value in values { let mut buffer: Vec = Vec::new(); - plugin_value::serialize_value(&value, &mut buffer).expect("unable to write message"); - let returned_value = plugin_value::deserialize_value(&mut buffer.as_slice()); + plugin_value::serialize_message(&value, &mut buffer).expect("unable to write message"); + let returned_value = plugin_value::deserialize_message(&mut buffer.as_slice()); assert_eq!(value, returned_value) } + } - { - // Since nothing doesn't implement PartialOrd, we only compare that the - // encoded and decoded spans are correct - let value = Value::Nothing { - span: Span { start: 0, end: 10 }, - }; + #[test] + fn value_nothing_round_trip() { + // Since nothing doesn't implement PartialOrd, we only compare that the + // encoded and decoded spans are correct + let value = Value::Nothing { + span: Span { start: 0, end: 10 }, + }; - let mut buffer: Vec = Vec::new(); - plugin_value::serialize_value(&value, &mut buffer).expect("unable to write message"); - let returned_value = plugin_value::deserialize_value(&mut buffer.as_slice()); + let mut buffer: Vec = Vec::new(); + plugin_value::serialize_message(&value, &mut buffer).expect("unable to write message"); + let returned_value = plugin_value::deserialize_message(&mut buffer.as_slice()); - assert_eq!( - value.span().expect("span"), - returned_value.span().expect("span") - ) - } + assert_eq!( + value.span().expect("span"), + returned_value.span().expect("span") + ) + } + + #[test] + fn list_round_trip() { + let values = vec![ + Value::Bool { + val: false, + span: Span { start: 1, end: 20 }, + }, + Value::Int { + val: 10, + span: Span { start: 2, end: 30 }, + }, + Value::Float { + val: 10.0, + span: Span { start: 3, end: 40 }, + }, + Value::String { + val: "a string".into(), + span: Span { start: 4, end: 50 }, + }, + ]; + + let value = Value::List { + vals: values, + span: Span { start: 1, end: 10 }, + }; + + let mut buffer: Vec = Vec::new(); + plugin_value::serialize_message(&value, &mut buffer).expect("unable to write message"); + let returned_value = plugin_value::deserialize_message(&mut buffer.as_slice()); + + assert_eq!( + value.span().expect("span"), + returned_value.span().expect("span") + ) } }