From 66a683f5838249591758c7a70cfc7027a4a6dd12 Mon Sep 17 00:00:00 2001 From: whitequark Date: Fri, 9 Jun 2017 06:22:34 +0000 Subject: [PATCH] compiler: add support for bytes values in RPC (#714). --- artiq/compiler/transforms/llvm_ir_generator.py | 2 ++ artiq/coredevice/comm_kernel.py | 6 ++++++ artiq/firmware/libproto/rpc_proto.rs | 11 ++++++++++- artiq/test/coredevice/test_embedding.py | 3 +++ 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/artiq/compiler/transforms/llvm_ir_generator.py b/artiq/compiler/transforms/llvm_ir_generator.py index 0bb73ef05..84eddfc88 100644 --- a/artiq/compiler/transforms/llvm_ir_generator.py +++ b/artiq/compiler/transforms/llvm_ir_generator.py @@ -1168,6 +1168,8 @@ class LLVMIRGenerator: return b"f" elif builtins.is_str(typ): return b"s" + elif builtins.is_bytes(typ): + return b"B" elif builtins.is_list(typ): return b"l" + self._rpc_tag(builtins.get_iterable_elt(typ), error_handler) diff --git a/artiq/coredevice/comm_kernel.py b/artiq/coredevice/comm_kernel.py index c197c5c3a..d75c8e96a 100644 --- a/artiq/coredevice/comm_kernel.py +++ b/artiq/coredevice/comm_kernel.py @@ -369,6 +369,8 @@ class CommKernel: return Fraction(numerator, denominator) elif tag == "s": return self._read_string() + elif tag == "B": + return self._read_bytes() elif tag == "l": length = self._read_int32() return [self._receive_rpc_value(embedding_map) for _ in range(length)] @@ -461,6 +463,10 @@ class CommKernel: check(isinstance(value, str) and "\x00" not in value, lambda: "str") self._write_string(value) + elif tag == "B": + check(isinstance(value, bytes), + lambda: "bytes") + self._write_bytes(value) elif tag == "l": check(isinstance(value, list), lambda: "list") diff --git a/artiq/firmware/libproto/rpc_proto.rs b/artiq/firmware/libproto/rpc_proto.rs index cf5012031..51984b8f0 100644 --- a/artiq/firmware/libproto/rpc_proto.rs +++ b/artiq/firmware/libproto/rpc_proto.rs @@ -28,7 +28,7 @@ unsafe fn recv_value(reader: &mut Read, tag: Tag, data: &mut *mut (), consume_value!(u64, |ptr| { *ptr = reader.read_u64()?; Ok(()) }), - Tag::String => { + Tag::String | Tag::Bytes => { consume_value!(CMutSlice, |ptr| { let length = reader.read_u32()? as usize; *ptr = CMutSlice::new(alloc(length)? as *mut u8, length); @@ -108,6 +108,9 @@ unsafe fn send_value(writer: &mut Write, tag: Tag, data: &mut *const ()) -> io:: Tag::String => consume_value!(CSlice, |ptr| writer.write_string(str::from_utf8((*ptr).as_ref()).unwrap())), + Tag::Bytes => + consume_value!(CSlice, |ptr| + writer.write_bytes((*ptr).as_ref())), Tag::Tuple(it, arity) => { let mut it = it.clone(); writer.write_u8(arity)?; @@ -202,6 +205,7 @@ mod tag { Int64, Float64, String, + Bytes, Tuple(TagIterator<'a>, u8), List(TagIterator<'a>), Array(TagIterator<'a>), @@ -219,6 +223,7 @@ mod tag { Tag::Int64 => b'I', Tag::Float64 => b'f', Tag::String => b's', + Tag::Bytes => b'B', Tag::Tuple(_, _) => b't', Tag::List(_) => b'l', Tag::Array(_) => b'a', @@ -236,6 +241,7 @@ mod tag { Tag::Int64 => 8, Tag::Float64 => 8, Tag::String => 4, + Tag::Bytes => 4, Tag::Tuple(it, arity) => { let mut size = 0; for _ in 0..arity { @@ -280,6 +286,7 @@ mod tag { b'I' => Tag::Int64, b'f' => Tag::Float64, b's' => Tag::String, + b'B' => Tag::Bytes, b't' => { let count = self.data[0]; self.data = &self.data[1..]; @@ -327,6 +334,8 @@ mod tag { write!(f, "Float64")?, Tag::String => write!(f, "String")?, + Tag::Bytes => + write!(f, "Bytes")?, Tag::Tuple(it, _) => { write!(f, "Tuple(")?; it.fmt(f)?; diff --git a/artiq/test/coredevice/test_embedding.py b/artiq/test/coredevice/test_embedding.py index f0bd12e45..87f6dad77 100644 --- a/artiq/test/coredevice/test_embedding.py +++ b/artiq/test/coredevice/test_embedding.py @@ -38,6 +38,9 @@ class RoundtripTest(ExperimentCase): def test_str(self): self.assertRoundtrip("foo") + def test_bytes(self): + self.assertRoundtrip(b"foo") + def test_list(self): self.assertRoundtrip([10])