summaryrefslogtreecommitdiff
path: root/ports/unix
diff options
context:
space:
mode:
authorJeff Epler <jepler@gmail.com>2019-12-03 14:50:37 -0600
committerJeff Epler <jepler@gmail.com>2019-12-04 09:29:57 -0600
commit238e12123690debaf2cf8488fb2a4d4003a06506 (patch)
treeb12a6de61a40b29a2baff0d24c09f9e25c960156 /ports/unix
parent15886b1505d854d76e353b9c5261568c7065d2bf (diff)
protocols: Allow them to be (optionally) type-safe
Protocols are nice, but there is no way for C code to verify whether a type's "protocol" structure actually implements some particular protocol. As a result, you can pass an object that implements the "vfs" protocol to one that expects the "stream" protocol, and the opposite of awesomeness ensues. This patch adds an OPTIONAL (but enabled by default) protocol identifier as the first member of any protocol structure. This identifier is simply a unique QSTR chosen by the protocol designer and used by each protocol implementer. When checking for protocol support, instead of just checking whether the object's type has a non-NULL protocol field, use `mp_proto_get` which implements the protocol check when possible. The existing protocols are now named: protocol_framebuf protocol_i2c protocol_pin protocol_stream protocol_spi protocol_vfs (most of these are unused in CP and are just inherited from MP; vfs and stream are definitely used though) I did not find any crashing examples, but here's one to give a flavor of what is improved, using `micropython_coverage`. Before the change, the vfs "ioctl" protocol is invoked, and the result is not intelligible as json (but it could have resulted in a hard fault, potentially): >>> import uos, ujson >>> u = uos.VfsPosix('/tmp') >>> ujson.load(u) Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: syntax error in JSON After the change, the vfs object is correctly detected as not supporting the stream protocol: >>> ujson.load(p) Traceback (most recent call last): File "<stdin>", line 1, in <module> OSError: stream operation not supported
Diffstat (limited to 'ports/unix')
-rw-r--r--ports/unix/coverage.c2
-rw-r--r--ports/unix/file.c2
-rw-r--r--ports/unix/modusocket.c1
3 files changed, 5 insertions, 0 deletions
diff --git a/ports/unix/coverage.c b/ports/unix/coverage.c
index 841924c58..849820fff 100644
--- a/ports/unix/coverage.c
+++ b/ports/unix/coverage.c
@@ -96,6 +96,7 @@ STATIC const mp_rom_map_elem_t rawfile_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table);
STATIC const mp_stream_p_t fileio_stream_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = stest_read,
.write = stest_write,
.ioctl = stest_ioctl,
@@ -123,6 +124,7 @@ STATIC const mp_rom_map_elem_t rawfile_locals_dict_table2[] = {
STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict2, rawfile_locals_dict_table2);
STATIC const mp_stream_p_t textio_stream_p2 = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = stest_read2,
.write = NULL,
.is_text = true,
diff --git a/ports/unix/file.c b/ports/unix/file.c
index c0cf6dcc4..e5c73d26c 100644
--- a/ports/unix/file.c
+++ b/ports/unix/file.c
@@ -230,6 +230,7 @@ STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table);
#if MICROPY_PY_IO_FILEIO
STATIC const mp_stream_p_t fileio_stream_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = fdfile_read,
.write = fdfile_write,
.ioctl = fdfile_ioctl,
@@ -248,6 +249,7 @@ const mp_obj_type_t mp_type_fileio = {
#endif
STATIC const mp_stream_p_t textio_stream_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = fdfile_read,
.write = fdfile_write,
.ioctl = fdfile_ioctl,
diff --git a/ports/unix/modusocket.c b/ports/unix/modusocket.c
index 84e9298fd..95da276ed 100644
--- a/ports/unix/modusocket.c
+++ b/ports/unix/modusocket.c
@@ -374,6 +374,7 @@ STATIC const mp_rom_map_elem_t usocket_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(usocket_locals_dict, usocket_locals_dict_table);
STATIC const mp_stream_p_t usocket_stream_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = socket_read,
.write = socket_write,
.ioctl = socket_ioctl,