Skip to content

Commit 6dbd38e

Browse files
committed
prepare for 0.19 release
1 parent 79e4af6 commit 6dbd38e

File tree

9 files changed

+172
-9
lines changed

9 files changed

+172
-9
lines changed
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
---
2+
layout: post
3+
title: 0.19 — setter ergonomics and faster reflection
4+
author: dwrensha
5+
---
6+
7+
As of today,
8+
version 0.19 of [capnproto-rust](https://github.com/capnproto/capnproto-rust)
9+
is [available on crates.io](https://crates.io/crates/capnp).
10+
11+
This release includes improved ergnomics and performance,
12+
while also having a notable breaking change involving text fields.
13+
14+
15+
## setter ergonomics
16+
17+
Suppose that we have the following struct defined in a Cap'n Proto schema file:
18+
19+
```capnp
20+
struct Cookie {
21+
fortune @0 :Text;
22+
numbers @1 :List(UInt16);
23+
}
24+
25+
```
26+
27+
With capnp-v0.18.0 (the previous release), to populate such a struct you would write Rust code like this:
28+
29+
```rust
30+
let mut message = capnp::message::Builder::new_default();
31+
let mut root: cookie::Builder = message.init_root();
32+
root.set_fortune("This too shall pass.".into());
33+
let mut numbers = root.init_numbers(6);
34+
numbers.set(0, 4);
35+
numbers.set(1, 8);
36+
numbers.set(2, 15);
37+
numbers.set(3, 16);
38+
numbers.set(3, 23);
39+
numbers.set(3, 42);
40+
```
41+
42+
This is rather more verbose than you might hope.
43+
The setter methods `set_fortune()` and `set_numbers()` are geared toward
44+
accepting input from *other* Cap'n Proto messages, rather than
45+
from Rust-native values.
46+
When we want to call `set_fortune()` on a Rust-native `&str`,
47+
we first need to convert it into a `capnp::text::Reader` via the `.into()` method.
48+
Similarly, the `set_numbers()` method wants a `primitive_list::Reader<u16>`,
49+
and there is no easy way for us to get one of those from a Rust-native `&[u16]`.
50+
Therefore, we avoid that method altogether, and instead opt to use `init_numbers()`
51+
and to invidually set each element of the list.
52+
53+
54+
In capnp-v0.19.0, we can instead directly set these fields from Rust-native values:
55+
56+
```rust
57+
let mut message = capnp::message::Builder::new_default();
58+
let mut root: cookie::Builder = message.init_root();
59+
root.set_fortune("This too shall pass.");
60+
root.set_numbers(&[4, 8, 15, 16, 23, 42]);
61+
```
62+
63+
This is possible because the setter methods have been generalized
64+
to accept a value of type `impl SetterInput<T>`, as follows:
65+
66+
```rust
67+
68+
mod cookie {
69+
impl <'a> Builder<'a> {
70+
pub fn set_fortune(&mut self, impl SetterInput<capnp::text::Owned>) {
71+
...
72+
}
73+
pub fn set_numbers(&mut self,
74+
impl SetterInput<capnp::primitive_list::Owned<u16>>) {
75+
...
76+
}
77+
}
78+
}
79+
80+
```
81+
82+
The trait `SetterInput<capnp::text::Owned>` is implemented both by
83+
`capnp::text::Reader` and by `&str`, and
84+
the trait `SetterInput<capnp::primitive_list::Owned<u16>>`
85+
is implemented by both `capnp::primitive_list::Reader<u16>`
86+
and by `&[u16]`.
87+
88+
### breaking change
89+
90+
Unfortunately, this generalization does cause some breakage.
91+
If we did not update the old line
92+
```rust
93+
root.set_fortune("This too shall pass.".into());
94+
```
95+
then it would now gives us a type error:
96+
97+
```
98+
error[E0283]: type annotations needed
99+
...
100+
= note: multiple `impl`s satisfying `_: SetterInput<capnp::text::Owned>` found in the `capnp` crate:
101+
- impl<'a> SetterInput<capnp::text::Owned> for &'a String;
102+
- impl<'a> SetterInput<capnp::text::Owned> for &'a str;
103+
- impl<'a> SetterInput<capnp::text::Owned> for capnp::text::Reader<'a>;
104+
note: required by a bound in `cookie::Builder::<'a>::set_fortune`
105+
106+
```
107+
108+
The problem is that `.into()` does not know which type to target.
109+
The fix is to remove the `.into()`.
110+
111+
Note that the need for such `.into()` calls was in fact only recently
112+
introduced, in the release of
113+
[version 0.18]({{site.baseurl}}/2023/09/04/0.18-release.html).
114+
Probably we should have
115+
delayed that release until we had a solution like the
116+
the present `impl SetterInput` generalization,
117+
thereby minimizing the churn of downstream code.
118+
119+
120+
## faster reflection
121+
122+
The [0.17 release]({{site.baseurl}}/2023/05/08/run-time-reflection.html)
123+
added support for run-time reflection,
124+
including a `DynamicStruct` type that supports
125+
looking up fields by name.
126+
The initial implementation
127+
worked by linearly scanning a struct's fields.
128+
That works fine for small structs, but can
129+
get expensive when there are a large number of fields.
130+
131+
In [#469](https://github.com/capnproto/capnproto-rust/pull/469),
132+
[@quartox](https://github.com/quartox) updated
133+
the implementation to use binary search,
134+
resulting in a significant performance increase,
135+
and matching the capnproto-c++ implementation.
136+
137+
This change involved add a new field to the static `RawStructSchema` value included
138+
in the generated code for each Cap'n Proto type.
139+

capnp-futures/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
## v0.19.0
2+
Follow v0.19.0 release of other capnp crates.
3+
14
## v0.18.2
25
- Fix overflow bug in read_message that could potentially lead to denial of service
36
attacks on 32-bit targets.

capnp-futures/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "capnp-futures"
3-
version = "0.19.0-alpha"
3+
version = "0.19.0"
44
authors = [ "David Renshaw <[email protected]>" ]
55
license = "MIT"
66

@@ -12,7 +12,7 @@ edition = "2021"
1212
keywords = ["async"]
1313

1414
[dependencies]
15-
capnp = { version = "0.19.0-alpha", path = "../capnp" }
15+
capnp = { version = "0.19.0", path = "../capnp" }
1616

1717
[dependencies.futures]
1818
version = "0.3.0"
@@ -25,7 +25,7 @@ default-features = false
2525
features = ["executor"]
2626

2727
[dev-dependencies]
28-
capnp = { version = "0.19.0-alpha", path = "../capnp", features = ["quickcheck"] }
28+
capnp = { version = "0.19.0", path = "../capnp", features = ["quickcheck"] }
2929
quickcheck = "1"
3030

3131
[lints]

capnp-rpc/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## v0.19.0
2+
Follow v0.19.0 release of other capnp crates.
3+
4+
## v0.18.0
5+
Follow v0.19.0 release of other capnp crates.
6+
17
## v0.17.0
28
- Rename `WeakCapabilityServerSet` to `CapabilityServerSet` and remove the old implmentation.
39

capnp-rpc/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22

33
name = "capnp-rpc"
4-
version = "0.19.0-alpha"
4+
version = "0.19.0"
55
authors = [ "David Renshaw <[email protected]>" ]
66
license = "MIT"
77
description = "implementation of the Cap'n Proto remote procedure call protocol"
@@ -19,8 +19,8 @@ default-features = false
1919
features = ["std"]
2020

2121
[dependencies]
22-
capnp-futures = { version = "0.19.0-alpha", path = "../capnp-futures" }
23-
capnp = {version = "0.19.0-alpha", path = "../capnp"}
22+
capnp-futures = { version = "0.19.0", path = "../capnp-futures" }
23+
capnp = {version = "0.19.0", path = "../capnp"}
2424

2525
#[lints]
2626
#workspace = true

capnp/CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
## v0.19.0
2+
- Use binary search instead of linear scan in DynamicStruct::get_named().
3+
- Rename SetPointerBuilder to SetterInput.
4+
- Add Receiver type parameter to SetterInput.
5+
- Support setting text fields by text::Reader or &str, via the SetterInput tactic.
6+
This will break code that uses the into() to convert from str to text::Reader
7+
in the arguments of such methods.
8+
- Also support setting primitive list fields by native Rust slices, and text list
9+
fields by slices of AsRef<str>.
10+
- Update embedded-io dependency to version 0.6.1.
11+
112
## v0.18.13
213
- Add PartialEq impls for text::Reader <-> String.
314

capnp/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22

33
name = "capnp"
4-
version = "0.19.0-alpha"
4+
version = "0.19.0"
55
authors = [ "David Renshaw <[email protected]>" ]
66
license = "MIT"
77
description = "runtime library for Cap'n Proto data encoding"

capnpc/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## v0.19.0
2+
- Include new members_by_name field of RawStructSchema.
3+
- Generalize text, primitive_list, and enum_list setters using impl SetterInput.
4+
15
## v0.18.1
26
- Fix overly-restrictive lifetimes in setters of certain list fields.
37

capnpc/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22

33
name = "capnpc"
4-
version = "0.19.0-alpha"
4+
version = "0.19.0"
55
authors = [ "David Renshaw <[email protected]>" ]
66
license = "MIT"
77
description = "Cap'n Proto code generation"
@@ -25,7 +25,7 @@ path = "src/capnpc-rust-bootstrap.rs"
2525

2626

2727
[dependencies.capnp]
28-
version = "0.19.0-alpha"
28+
version = "0.19.0"
2929
path = "../capnp"
3030

3131
[lints]

0 commit comments

Comments
 (0)