@@ -235,8 +235,17 @@ class CLROutputBlock(Enum):
235235 RAW_BITS = 4
236236
237237
238+ RUST_UNICODE_ESCAPE = re .compile (r'(\\+)u\{([a-f0-9]+)\}' )
239+ def _unrustify_repr (rust_repr ):
240+ # Rust's repr of a Unicode string can include backslash escapes, which are mostly
241+ # compatible with Python's. Unlike Python, however, its Unicode character escapes
242+ # are not always 4 hex digits, and have braces (e.g. '\u{123}')
243+ # To handle the case of an escaped '\\' followed by 'u{...}', we ignore even
244+ # numbers of backslashes.
245+ unrust = RUST_UNICODE_ESCAPE .sub (lambda m : r'\u' + m .group (2 ).rjust (4 , '0' ) if len (m .group (1 )) % 2 else m .group (0 ), rust_repr )
246+ return unrust .encode ().decode ('unicode_escape' )
247+
238248class BarCode (object ):
239- RUST_UNICODE_ESCAPE = re .compile (r'\\u\{([a-f0-9]+)\}' )
240249 POINTS = re .compile (r'PointT\s*\{\s*x\:\s*([-\d.]+),\s*y\:\s*([-\d.]+)\s*\}' )
241250
242251 RXING_FORMAT_TO_ZXING = {'QRCODE' : 'QR_CODE' }
@@ -260,11 +269,8 @@ def parse_rxing(cls, rxing_output, fn):
260269 format = l .removeprefix ('[Barcode Format] ' ).replace (' ' , '_' ).upper ()
261270 format = cls .RXING_FORMAT_TO_ZXING .get (format , format )
262271 elif l .startswith ('[Data] ' ):
263- # This is a Rust repr of a string, include backslash escapes. Unlike Python, its
264- # unicode character escapes are not always 4 digits, and have braces (e.g. '\u{123}')
265- # FIXME: This incorrectly handles the case of an escaped '\\' followed by 'u{...}'
266- raw = l .removeprefix ('[Data] ' )
267- raw = cls .RUST_UNICODE_ESCAPE .sub (lambda m : r'\u' + m .group (1 ).rjust (4 , '0' ), raw ).encode ().decode ('unicode_escape' )
272+ # This is a Rust repr of a string, which is almost-but-not-quite handled by bytes.decode('unicode_escape')
273+ raw = _unrustify_repr (l .removeprefix ('[Data] ' ))
268274 elif l .startswith ('[Points] ' ):
269275 points = [((float (m [0 ]), float (m [1 ]))) for m in cls .POINTS .findall (l .removeprefix ('[Points] ' ))]
270276
0 commit comments