Mercurial > hg
comparison mercurial/wireprotoframing.py @ 37290:cc5a040fe150
wireproto: syntax for encoding CBOR into frames
We just vendored a library for encoding and decoding the CBOR
data format. While the intent of that vendor was to support state
files, CBOR is really a nice data format. It is extensible and
compact.
I've been feeling dirty inventing my own data formats for
frame payloads. While custom formats can always beat out a generic
format, there is a cost to be paid in terms of implementation,
comprehension, etc. CBOR is compact enough that I'm not too
worried about efficiency loss. I think the benefits of using
a standardized format outweigh rolling our own formats. So
I plan to make heavy use of CBOR in the wire protocol going
forward.
This commit introduces support for encoding CBOR data in frame
payloads to our function to make a frame from a human string.
We do need to employ some low-level Python code in order to
evaluate a string as a Python expression. But other than that,
this should hopefully be pretty straightforward.
Unit tests for this function have been added.
Differential Revision: https://phab.mercurial-scm.org/D2948
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Wed, 28 Mar 2018 15:05:39 -0700 |
parents | 5fadc63ac99f |
children | b0041036214e |
comparison
equal
deleted
inserted
replaced
37289:5fadc63ac99f | 37290:cc5a040fe150 |
---|---|
14 import struct | 14 import struct |
15 | 15 |
16 from .i18n import _ | 16 from .i18n import _ |
17 from .thirdparty import ( | 17 from .thirdparty import ( |
18 attr, | 18 attr, |
19 cbor, | |
19 ) | 20 ) |
20 from . import ( | 21 from . import ( |
21 error, | 22 error, |
22 util, | 23 util, |
23 ) | 24 ) |
154 return frame | 155 return frame |
155 | 156 |
156 def makeframefromhumanstring(s): | 157 def makeframefromhumanstring(s): |
157 """Create a frame from a human readable string | 158 """Create a frame from a human readable string |
158 | 159 |
160 DANGER: NOT SAFE TO USE WITH UNTRUSTED INPUT BECAUSE OF POTENTIAL | |
161 eval() USAGE. DO NOT USE IN CORE. | |
162 | |
159 Strings have the form: | 163 Strings have the form: |
160 | 164 |
161 <request-id> <stream-id> <stream-flags> <type> <flags> <payload> | 165 <request-id> <stream-id> <stream-flags> <type> <flags> <payload> |
162 | 166 |
163 This can be used by user-facing applications and tests for creating | 167 This can be used by user-facing applications and tests for creating |
167 | 171 |
168 Stream flags, frame type, and flags can be specified by integer or | 172 Stream flags, frame type, and flags can be specified by integer or |
169 named constant. | 173 named constant. |
170 | 174 |
171 Flags can be delimited by `|` to bitwise OR them together. | 175 Flags can be delimited by `|` to bitwise OR them together. |
176 | |
177 If the payload begins with ``cbor:``, the following string will be | |
178 evaluated as Python code and the resulting object will be fed into | |
179 a CBOR encoder. Otherwise, the payload is interpreted as a Python | |
180 byte string literal. | |
172 """ | 181 """ |
173 fields = s.split(b' ', 5) | 182 fields = s.split(b' ', 5) |
174 requestid, streamid, streamflags, frametype, frameflags, payload = fields | 183 requestid, streamid, streamflags, frametype, frameflags, payload = fields |
175 | 184 |
176 requestid = int(requestid) | 185 requestid = int(requestid) |
194 if flag in validflags: | 203 if flag in validflags: |
195 finalflags |= validflags[flag] | 204 finalflags |= validflags[flag] |
196 else: | 205 else: |
197 finalflags |= int(flag) | 206 finalflags |= int(flag) |
198 | 207 |
199 payload = stringutil.unescapestr(payload) | 208 if payload.startswith(b'cbor:'): |
209 payload = cbor.dumps(stringutil.evalpython(payload[5:]), canonical=True) | |
210 | |
211 else: | |
212 payload = stringutil.unescapestr(payload) | |
200 | 213 |
201 return makeframe(requestid=requestid, streamid=streamid, | 214 return makeframe(requestid=requestid, streamid=streamid, |
202 streamflags=finalstreamflags, typeid=frametype, | 215 streamflags=finalstreamflags, typeid=frametype, |
203 flags=finalflags, payload=payload) | 216 flags=finalflags, payload=payload) |
204 | 217 |