Skip to content

Commit 2027641

Browse files
committed
encoding: tweak keycode
1 parent b57ae65 commit 2027641

File tree

1 file changed

+24
-21
lines changed

1 file changed

+24
-21
lines changed

src/encoding/keycode.rs

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
4040
use std::ops::Bound;
4141

42+
use itertools::Either;
4243
use serde::de::{
4344
Deserialize, DeserializeSeed, EnumAccess, IntoDeserializer as _, SeqAccess, VariantAccess,
4445
Visitor,
@@ -127,7 +128,7 @@ impl serde::ser::Serializer for &mut Serializer {
127128
unimplemented!()
128129
}
129130

130-
/// i64 uses the big-endian two's completement encoding, but flips the
131+
/// i64 uses the big-endian two's complement encoding, but flips the
131132
/// left-most sign bit such that negative numbers are ordered before
132133
/// positive numbers.
133134
///
@@ -163,16 +164,15 @@ impl serde::ser::Serializer for &mut Serializer {
163164
unimplemented!()
164165
}
165166

166-
/// f64 is encoded in big-endian form, but it flips the sign bit to order
167-
/// positive numbers after negative numbers, and also flips all other bits
168-
/// for negative numbers to order them from smallest to greatest. NaN is
167+
/// f64 is encoded in big-endian IEEE 754 form, but it flips the sign bit to
168+
/// order positive numbers after negative numbers, and also flips all other
169+
/// bits for negative numbers to order them from smallest to largest. NaN is
169170
/// ordered at the end.
170171
fn serialize_f64(self, v: f64) -> Result<()> {
171172
let mut bytes = v.to_be_bytes();
172-
if bytes[0] & 1 << 7 == 0 {
173-
bytes[0] ^= 1 << 7; // positive, flip sign bit
174-
} else {
175-
bytes.iter_mut().for_each(|b| *b = !*b); // negative, flip all bits
173+
match v.is_sign_negative() {
174+
false => bytes[0] ^= 1 << 7, // positive, flip sign bit
175+
true => bytes.iter_mut().for_each(|b| *b = !*b), // negative, flip all bits
176176
}
177177
self.output.extend(bytes);
178178
Ok(())
@@ -187,14 +187,20 @@ impl serde::ser::Serializer for &mut Serializer {
187187
self.serialize_bytes(v.as_bytes())
188188
}
189189

190-
// Byte slices are terminated by 0x0000, escaping 0x00 as 0x00ff.
191-
// Prefix-length encoding can't be used, since it violates ordering.
190+
// Byte slices are terminated by 0x0000, escaping 0x00 as 0x00ff. This
191+
// ensures that we can detect the end, and that for two overlapping slices,
192+
// the shorter one orders before the longer one.
193+
//
194+
// We can't use e.g. length prefix encoding, since it doesn't sort correctly.
192195
fn serialize_bytes(self, v: &[u8]) -> Result<()> {
193-
let b = v
196+
let bytes = v
194197
.iter()
195-
.flat_map(|&b| if b == 0x00 { vec![0x00, 0xff] } else { vec![b] })
198+
.flat_map(|&byte| match byte {
199+
0x00 => Either::Left([0x00, 0xff].into_iter()),
200+
byte => Either::Right([byte].into_iter()),
201+
})
196202
.chain([0x00, 0x00]);
197-
self.output.extend(b);
203+
self.output.extend(bytes);
198204
Ok(())
199205
}
200206

@@ -354,9 +360,6 @@ impl<'de> Deserializer<'de> {
354360

355361
/// Decodes and chops off the next encoded byte slice.
356362
fn decode_next_bytes(&mut self) -> Result<Vec<u8>> {
357-
// We can't easily share state between Iterator.scan() and
358-
// Iterator.filter() when processing escape sequences, so use a
359-
// straightforward loop.
360363
let mut decoded = Vec::new();
361364
let mut iter = self.input.iter().enumerate();
362365
let taken = loop {
@@ -387,7 +390,7 @@ impl<'de> serde::de::Deserializer<'de> for &mut Deserializer<'de> {
387390
visitor.visit_bool(match self.take_bytes(1)?[0] {
388391
0x00 => false,
389392
0x01 => true,
390-
b => return errdata!("Invalid boolean value {b:?}"),
393+
b => return errdata!("invalid boolean value {b}"),
391394
})
392395
}
393396

@@ -431,10 +434,10 @@ impl<'de> serde::de::Deserializer<'de> for &mut Deserializer<'de> {
431434

432435
fn deserialize_f64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
433436
let mut bytes = self.take_bytes(8)?.to_vec();
434-
if bytes[0] >> 7 & 1 == 1 {
435-
bytes[0] ^= 1 << 7; // positive, flip sign bit
436-
} else {
437-
bytes.iter_mut().for_each(|b| *b = !*b); // negative, flip all bits
437+
match bytes[0] >> 7 {
438+
0 => bytes.iter_mut().for_each(|b| *b = !*b), // negative, flip all bits
439+
1 => bytes[0] ^= 1 << 7, // positive, flip sign bit
440+
_ => panic!("bits can only be 0 or 1"),
438441
}
439442
visitor.visit_f64(f64::from_be_bytes(bytes.as_slice().try_into()?))
440443
}

0 commit comments

Comments
 (0)