diff --git a/decode.go b/decode.go index 354084c..b9d58cf 100644 --- a/decode.go +++ b/decode.go @@ -245,11 +245,13 @@ func decodeInt32(b []byte) ([]byte, int32, error) { if i > VarIntLen32 && cb > 1 { return b, 0, InvalidInt32 } - // End of varint, add the last bits and cast to signed integer - x := int32((ux | uint32(cb)<> 1) - // Flip the bits if the sign bit is set + // End of varint, add the last bits + ux |= uint32(cb) << s + // Separate value and sign + x := int32(ux >> 1) + // If sign bit is set, negate the number if ux&1 != 0 { - x = ^x + x = -(x + 1) } return b[i+1:], x, nil } @@ -271,11 +273,13 @@ func decodeInt64(b []byte) ([]byte, int64, error) { if i > VarIntLen64 && cb > 1 { return b, 0, InvalidInt64 } - // End of varint, add the last bits and cast to signed integer - x := int64((ux | uint64(cb)<> 1) - // Flip the bits if the sign bit is set + // End of varint, add the last bits + ux |= uint64(cb) << s + // Separate value and sign + x := int64(ux >> 1) + // If sign bit is set, negate the number if ux&1 != 0 { - x = ^x + x = -(x + 1) } return b[i+1:], x, nil } diff --git a/decode_test.go b/decode_test.go index f268157..baebdfd 100644 --- a/decode_test.go +++ b/decode_test.go @@ -456,7 +456,7 @@ func TestDecodeInt32(t *testing.T) { t.Parallel() p := NewBuffer() - v := int32(-2147483648) + v := int32(2147483647) encodeInt32(p, v) var value int32 @@ -466,6 +466,15 @@ func TestDecodeInt32(t *testing.T) { assert.Equal(t, v, value) assert.Equal(t, 0, len(remaining)) + v = int32(-2147483647) + p.Reset() + encodeInt32(p, v) + + remaining, value, err = decodeInt32(p.Bytes()) + assert.NoError(t, err) + assert.Equal(t, v, value) + assert.Equal(t, 0, len(remaining)) + _, _, err = decodeInt32((p.Bytes())[1:]) assert.ErrorIs(t, err, InvalidInt32) @@ -491,7 +500,7 @@ func TestDecodeInt64(t *testing.T) { t.Parallel() p := NewBuffer() - v := int64(-9223372036854775808) + v := int64(9223372036854775807) encodeInt64(p, v) var value int64 @@ -501,6 +510,15 @@ func TestDecodeInt64(t *testing.T) { assert.Equal(t, v, value) assert.Equal(t, 0, len(remaining)) + v = int64(-9223372036854775807) + p.Reset() + encodeInt64(p, v) + + remaining, value, err = decodeInt64(p.Bytes()) + assert.NoError(t, err) + assert.Equal(t, v, value) + assert.Equal(t, 0, len(remaining)) + _, _, err = decodeInt64((p.Bytes())[1:]) assert.ErrorIs(t, err, InvalidInt64) diff --git a/decoder.rs b/decoder.rs index c9302a5..4a4d4a9 100644 --- a/decoder.rs +++ b/decoder.rs @@ -254,9 +254,10 @@ impl Decoder for Cursor<&mut Vec> { for _ in 0..VARINT_LEN32 { let byte = self.read_u8().ok().ok_or(DecodingError::InvalidI32)?; if byte < CONTINUATION { - let mut x = ((ux | (byte as u32) << s) >> 1) as i32; + ux |= (byte as u32) << s; + let mut x = (ux >> 1) as i32; if ux & 1 != 0 { - x = !x + x = -(x + 1) } return Ok(x); } @@ -277,9 +278,10 @@ impl Decoder for Cursor<&mut Vec> { for _ in 0..VARINT_LEN64 { let byte = self.read_u8().ok().ok_or(DecodingError::InvalidI64)?; if byte < CONTINUATION { - let mut x = ((ux | (byte as u64) << s) >> 1) as i64; + ux |= (byte as u64) << s; + let mut x = (ux >> 1) as i64; if ux & 1 != 0 { - x = !x + x = -(x + 1) } return Ok(x); } diff --git a/decoder.test.ts b/decoder.test.ts index 29c6d78..1749425 100644 --- a/decoder.test.ts +++ b/decoder.test.ts @@ -149,28 +149,34 @@ describe("Decoder", () => { }); it("Can decode Int32", () => { - const expected = -2147483648; + const expected = 2147483647; + const expectedNegative = -2147483647; - const encoded = new Encoder().int32(expected).bytes; + const encoded = new Encoder().int32(expected).int32(expectedNegative).bytes; const decoder = new Decoder(encoded); const value = decoder.int32(); + const valueNegative = decoder.int32(); expect(value).toBe(expected); + expect(valueNegative).toBe(expectedNegative); expect(decoder.length).toBe(0); expect(() => decoder.int32()).toThrowError(InvalidInt32Error); }); it("Can decode Int64", () => { - const expected = -9223372036854775808n; + const expected = 9223372036854775807n; + const expectedNegative = -9223372036854775807n; - const encoded = new Encoder().int64(expected).bytes; + const encoded = new Encoder().int64(expected).int64(expectedNegative).bytes; const decoder = new Decoder(encoded); const value = decoder.int64(); + const valueNegative = decoder.int64(); expect(value).toBe(expected); + expect(valueNegative).toBe(expectedNegative); expect(decoder.length).toBe(0); expect(() => decoder.int64()).toThrowError(InvalidInt64Error); diff --git a/tests/decoder.rs b/tests/decoder.rs new file mode 100644 index 0000000..e8427c8 --- /dev/null +++ b/tests/decoder.rs @@ -0,0 +1,267 @@ +/* + Copyright 2022 Loophole Labs + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +extern crate polyglot_rs; + +use polyglot_rs::Decoder; +use polyglot_rs::DecodingError; +use polyglot_rs::Encoder; +use polyglot_rs::Kind; +use std::collections::HashMap; +use std::error::Error; +use std::io::Cursor; + +#[test] +fn test_decode_nil() { + let mut encoder = Cursor::new(Vec::with_capacity(512)); + encoder.encode_none().unwrap(); + + let mut decoder = Cursor::new(encoder.get_mut()); + let val = decoder.decode_none(); + assert_eq!(val, true); + assert_eq!(decoder.get_ref().len() - decoder.position() as usize, 0); + let next_val = decoder.decode_none(); + assert_eq!(next_val, false); +} + +#[test] +fn test_decode_array() { + let mut encoder = Cursor::new(Vec::with_capacity(512)); + let m = ["1".to_string(), "2".to_string(), "3".to_string()]; + + encoder.encode_array(m.len(), Kind::String).unwrap(); + for i in m.clone() { + encoder.encode_string(&i).unwrap(); + } + + let mut decoder = Cursor::new(encoder.get_mut()); + let size = decoder.decode_array(Kind::String).unwrap() as usize; + assert_eq!(size, m.len()); + + let mut mv: Vec = Vec::with_capacity(size); + for i in 0..size { + let val = decoder.decode_string().unwrap(); + mv.push(val.to_string()); + assert_eq!(mv[i], m[i]); + } + assert_eq!(mv, m); + + let error = decoder.decode_array(Kind::String).unwrap_err(); + assert_eq!(error, DecodingError::InvalidArray); +} + +#[test] +fn test_decode_map() { + let mut encoder = Cursor::new(Vec::with_capacity(512)); + let mut m: HashMap = HashMap::new(); + m.insert(String::from("1"), 1); + m.insert(String::from("2"), 2); + m.insert(String::from("3"), 3); + + encoder + .encode_map(m.len(), Kind::String, Kind::U32) + .unwrap(); + for (k, v) in m.clone() { + encoder.encode_string(&k).unwrap().encode_u32(v).unwrap(); + } + + let mut decoder = Cursor::new(encoder.get_mut()); + let size = decoder.decode_map(Kind::String, Kind::U32).unwrap() as usize; + assert_eq!(size, m.len()); + + let mut mv = HashMap::new(); + for _ in 0..size { + let k = decoder.decode_string().unwrap(); + let v = decoder.decode_u32().unwrap(); + mv.insert(k, v); + } + assert_eq!(mv, m); + + let error = decoder.decode_map(Kind::String, Kind::U32).unwrap_err(); + assert_eq!(error, DecodingError::InvalidMap); +} + +#[test] +fn test_decode_bytes() { + let mut encoder = Cursor::new(Vec::with_capacity(512)); + let v = "Test String".as_bytes(); + encoder.encode_bytes(v).unwrap(); + + let mut decoder = Cursor::new(encoder.get_mut()); + let bytes = decoder.decode_bytes().unwrap(); + assert_eq!(bytes, v); +} + +#[test] +fn test_decode_string() { + let mut encoder = Cursor::new(Vec::with_capacity(512)); + let v = "Test String".to_string(); + encoder.encode_string(&v).unwrap(); + + let mut decoder = Cursor::new(encoder.get_mut()); + let val = decoder.decode_string().unwrap(); + assert_eq!(val, v); + + let error = decoder.decode_string().unwrap_err(); + assert_eq!(error, DecodingError::InvalidString); +} + +#[test] +fn test_decode_error() { + let mut encoder = Cursor::new(Vec::with_capacity(512)); + let v = "Test String"; + encoder.encode_error(Box::::from(v)).unwrap(); + + let mut decoder = Cursor::new(encoder.get_mut()); + let val = decoder.decode_error().unwrap(); + assert_eq!(val.to_string(), v); + + let error = decoder.decode_error().unwrap_err(); + assert_eq!(error, DecodingError::InvalidError); +} + +#[test] +fn test_decode_bool() { + let mut encoder = Cursor::new(Vec::with_capacity(512)); + encoder.encode_bool(true).unwrap(); + + let mut decoder = Cursor::new(encoder.get_mut()); + let val = decoder.decode_bool().unwrap(); + assert_eq!(val, true); + + let error = decoder.decode_bool().unwrap_err(); + assert_eq!(error, DecodingError::InvalidBool); +} + +#[test] +fn test_decode_u8() { + let mut encoder = Cursor::new(Vec::with_capacity(512)); + let v = 32 as u8; + encoder.encode_u8(v).unwrap(); + + let mut decoder = Cursor::new(encoder.get_mut()); + let val = decoder.decode_u8().unwrap(); + assert_eq!(val, v); + + let error = decoder.decode_u8().unwrap_err(); + assert_eq!(error, DecodingError::InvalidU8); +} + +#[test] +fn test_decode_u16() { + let mut encoder = Cursor::new(Vec::with_capacity(512)); + let v = 1024 as u16; + encoder.encode_u16(v).unwrap(); + + let mut decoder = Cursor::new(encoder.get_mut()); + let val = decoder.decode_u16().unwrap(); + assert_eq!(val, v); + + let error = decoder.decode_u16().unwrap_err(); + assert_eq!(error, DecodingError::InvalidU16); +} + +#[test] +fn test_decode_u32() { + let mut encoder = Cursor::new(Vec::with_capacity(512)); + let v = 4294967290 as u32; + encoder.encode_u32(v).unwrap(); + + let mut decoder = Cursor::new(encoder.get_mut()); + let val = decoder.decode_u32().unwrap(); + assert_eq!(val, v); + + let error = decoder.decode_u32().unwrap_err(); + assert_eq!(error, DecodingError::InvalidU32); +} + +#[test] +fn test_decode_u64() { + let mut encoder = Cursor::new(Vec::with_capacity(512)); + let v = 18446744073709551610 as u64; + encoder.encode_u64(v).unwrap(); + + let mut decoder = Cursor::new(encoder.get_mut()); + let val = decoder.decode_u64().unwrap(); + assert_eq!(val, v); + + let error = decoder.decode_u64().unwrap_err(); + assert_eq!(error, DecodingError::InvalidU64); +} + +#[test] +fn test_decode_i32() { + let mut encoder = Cursor::new(Vec::with_capacity(512)); + let v = 2147483647 as i32; + let vneg = -32 as i32; + encoder.encode_i32(v).unwrap(); + encoder.encode_i32(vneg).unwrap(); + + let mut decoder = Cursor::new(encoder.get_mut()); + let val = decoder.decode_i32().unwrap(); + let valneg = decoder.decode_i32().unwrap(); + assert_eq!(val, v); + assert_eq!(valneg, vneg); + + let error = decoder.decode_i32().unwrap_err(); + assert_eq!(error, DecodingError::InvalidI32); +} + +#[test] +fn test_decode_i64() { + let mut encoder = Cursor::new(Vec::with_capacity(512)); + let v = 9223372036854775807 as i64; + let vneg = -32 as i64; + encoder.encode_i64(v).unwrap(); + encoder.encode_i64(vneg).unwrap(); + + let mut decoder = Cursor::new(encoder.get_mut()); + let val = decoder.decode_i64().unwrap(); + let valneg = decoder.decode_i64().unwrap(); + assert_eq!(val, v); + assert_eq!(valneg, vneg); + + let error = decoder.decode_i64().unwrap_err(); + assert_eq!(error, DecodingError::InvalidI64); +} + +#[test] +fn test_decode_f32() { + let mut encoder = Cursor::new(Vec::with_capacity(512)); + let v = -2147483.648 as f32; + encoder.encode_f32(v).unwrap(); + + let mut decoder = Cursor::new(encoder.get_mut()); + let val = decoder.decode_f32().unwrap(); + assert_eq!(val, v); + + let error = decoder.decode_f32().unwrap_err(); + assert_eq!(error, DecodingError::InvalidF32); +} + +#[test] +fn test_decode_f64() { + let mut encoder = Cursor::new(Vec::with_capacity(512)); + let v = -922337203.477580 as f64; + encoder.encode_f64(v).unwrap(); + + let mut decoder = Cursor::new(encoder.get_mut()); + let val = decoder.decode_f64().unwrap(); + assert_eq!(val, v); + + let error = decoder.decode_f64().unwrap_err(); + assert_eq!(error, DecodingError::InvalidF64); +} diff --git a/tests/encoder.rs b/tests/encoder.rs new file mode 100644 index 0000000..329352b --- /dev/null +++ b/tests/encoder.rs @@ -0,0 +1,175 @@ +/* + Copyright 2022 Loophole Labs + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +extern crate polyglot_rs; + +use polyglot_rs::Encoder; +use polyglot_rs::Kind; +use std::error::Error; +use std::io::Cursor; + +#[test] +fn test_encode_nil() { + let mut encoder = Cursor::new(Vec::with_capacity(512)); + encoder.encode_none().unwrap(); + + assert_eq!(encoder.position(), 1); + assert_eq!(encoder.get_ref()[0], Kind::None as u8); +} + +#[test] +fn test_encode_array() { + let mut encoder = Cursor::new(Vec::with_capacity(512)); + encoder.encode_array(32, Kind::String).unwrap(); + + assert_eq!(encoder.position(), 1 + 1 + 1 + 1); + assert_eq!(encoder.get_ref()[0], Kind::Array as u8); + assert_eq!(encoder.get_ref()[1], Kind::String as u8); + assert_eq!(encoder.get_ref()[2], Kind::U32 as u8); +} + +#[test] +fn test_encode_map() { + let mut encoder = Cursor::new(Vec::with_capacity(512)); + encoder.encode_map(32, Kind::String, Kind::U32).unwrap(); + + assert_eq!(encoder.position(), 1 + 1 + 1 + 1 + 1); + assert_eq!(encoder.get_ref()[0], Kind::Map as u8); + assert_eq!(encoder.get_ref()[1], Kind::String as u8); + assert_eq!(encoder.get_ref()[2], Kind::U32 as u8); + assert_eq!(encoder.get_ref()[3], Kind::U32 as u8); +} + +#[test] +fn test_encode_bytes() { + let mut encoder = Cursor::new(Vec::with_capacity(512)); + let v = "Test String".as_bytes(); + encoder.encode_bytes(v).unwrap(); + + assert_eq!(encoder.position() as usize, 1 + 1 + 1 + v.len()); + assert_eq!(encoder.get_ref()[1 + 1 + 1..].to_owned(), v); +} + +#[test] +fn test_encode_string() { + let mut encoder = Cursor::new(Vec::with_capacity(512)); + let v = "Test String".to_string(); + encoder.encode_string(&v).unwrap(); + + assert_eq!(encoder.position() as usize, 1 + 1 + 1 + v.len()); + assert_eq!(encoder.get_ref()[1 + 1 + 1..].to_owned(), v.as_bytes()); +} + +#[test] +fn test_encode_error() { + let mut encoder = Cursor::new(Vec::with_capacity(512)); + let v = "Test Error"; + encoder.encode_error(Box::::from(v)).unwrap(); + assert_eq!(encoder.position() as usize, 1 + 1 + 1 + 1 + v.len()); + assert_eq!( + encoder.get_ref()[1 + 1 + 1 + 1..].to_owned(), + v.to_string().as_bytes() + ); +} + +#[test] +fn test_encode_bool() { + let mut encoder = Cursor::new(Vec::with_capacity(512)); + encoder.encode_bool(true).unwrap(); + + assert_eq!(encoder.position(), 2); + assert_eq!(encoder.get_ref()[1], 0x1); +} + +#[test] +fn test_encode_u8() { + let mut encoder = Cursor::new(Vec::with_capacity(512)); + encoder.encode_u8(32).unwrap(); + + assert_eq!(encoder.get_ref()[1], 32); +} + +#[test] +fn test_encode_u16() { + let mut encoder = Cursor::new(Vec::with_capacity(512)); + let v = 1024; + let e = [128, 8]; + encoder.encode_u16(v).unwrap(); + + assert_eq!(encoder.get_ref()[1..].to_owned(), e); +} + +#[test] +fn test_encode_u32() { + let mut encoder = Cursor::new(Vec::with_capacity(512)); + let v = 4294967290; + let e = [250, 255, 255, 255, 15]; + encoder.encode_u32(v).unwrap(); + + assert_eq!(encoder.get_ref()[1..].to_owned(), e); +} + +#[test] +fn test_encode_u64() { + let mut encoder = Cursor::new(Vec::with_capacity(512)); + let v = 18446744073709551610; + let e = [250, 255, 255, 255, 255, 255, 255, 255, 255, 1]; + encoder.encode_u64(v).unwrap(); + + assert_eq!(encoder.get_ref()[1..].to_owned(), e); +} + +#[test] +fn test_encode_i32() { + let mut encoder = Cursor::new(Vec::with_capacity(512)); + let v = -2147483648; + let e = [255, 255, 255, 255, 15]; + encoder.encode_i32(v).unwrap(); + + assert_eq!(encoder.get_ref()[1..].to_owned(), e); +} + +#[test] +fn test_encode_i64() { + let mut encoder = Cursor::new(Vec::with_capacity(512)); + let v = -9223372036854775808 as i64; + let e = [255, 255, 255, 255, 255, 255, 255, 255, 255, 1]; + encoder.encode_i64(v).unwrap(); + + assert_eq!(encoder.get_ref()[1..].to_owned(), e); +} + +#[test] +fn test_encode_f32() { + let mut encoder = Cursor::new(Vec::with_capacity(512)); + let v = -214648.34432 as f32; + let e = [0xC8, 0x51, 0x9E, 0x16]; + encoder.encode_f32(v).unwrap(); + + assert_eq!(encoder.position(), 5); + assert_eq!(encoder.get_ref()[1..].to_owned(), e); +} + +#[test] +fn test_encode_f64() { + let mut encoder = Cursor::new(Vec::with_capacity(512)); + let v = -922337203685.2345; + let e = [0xC2, 0x6A, 0xD7, 0xF2, 0x9A, 0xBC, 0xA7, 0x81]; + encoder.encode_f64(v).unwrap(); + + assert_eq!(encoder.position(), 9); + assert_eq!(encoder.get_ref()[1..].to_owned(), e); +}