Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pull] master from dermesser:master #1

Open
wants to merge 108 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
108 commits
Select commit Hold shift + click to select a range
c9e1a80
Upgrade to edition 2018
dermesser Feb 21, 2020
3e6e503
Implement VarIntAsyncReader
dermesser Feb 21, 2020
3d44c91
Export VarIntAsyncReader
dermesser Feb 22, 2020
87f02e0
Add example for async code
dermesser Feb 22, 2020
5bdbfab
Also fix reader.rs for 2018 edition
dermesser Feb 22, 2020
f2331b4
Fix use of tokio: no use of futures anymore
dermesser Feb 22, 2020
f7d55af
reader: Fix bug in new reader implementation
dermesser Feb 22, 2020
6476b18
Update example to be more robust
dermesser Feb 22, 2020
d30b81c
reader: Improvement on f7d55af
dermesser Feb 22, 2020
aea6076
Update crate version to 1.1.0 without releasing yet
dermesser Feb 22, 2020
70271d0
example: Be sensible and use buffered reader.
dermesser Feb 22, 2020
954f060
Enable switching between tokio/futures Async traits
dermesser Feb 22, 2020
35ccb08
Implement FixedIntAsyncReader
dermesser Feb 22, 2020
a1f3d1b
Use read_exact for fixed int reader
dermesser Feb 22, 2020
65319ca
Use read_exact in fixed int reader
dermesser Feb 22, 2020
9dbfd03
Publish v1.0.8
dermesser Feb 22, 2020
7e8aea9
Implement remaining asynchronous reader/writer types
dermesser Feb 22, 2020
bbeccbc
Add test for asynchronous reader/writer methods on FixedInt
dermesser Feb 22, 2020
7a09651
Fix clippy warnings too
dermesser Feb 22, 2020
c034dab
Stop using decode_var_vec, replace with easier alternative
dermesser Feb 22, 2020
b4be043
Run rustfmt
dermesser Feb 22, 2020
7fe4c3a
Optimize dependencies: Use only required features
dermesser Feb 23, 2020
d99c9af
Merge branch 'async'
dermesser Feb 23, 2020
9aa9279
Restructure feature selection to disable async by default and select …
dermesser Feb 23, 2020
fd2f2bf
Fix Travis build script
dermesser Feb 23, 2020
1fd8112
Publish v1.1.0
dermesser Feb 24, 2020
0e4f4e2
Show async features on docs.rs
dermesser Feb 24, 2020
587cb93
Release v1.1.1 - show async features in docs.rs
dermesser Feb 24, 2020
bc0864e
Only compile async tests when an async feature is enabled
dermesser Feb 27, 2020
abb8282
Bump version: 1.1.2
dermesser Feb 27, 2020
509841a
Make async-trait dependency optional
dermesser Feb 29, 2020
0105f7b
Bump version: 1.1.3
dermesser Feb 29, 2020
4b8e92c
Attempt to fix #7
dermesser Mar 4, 2020
5cf2a44
Merge branch 'thrift_decode_test'
dermesser Mar 5, 2020
fd9e22d
Bump version -> 1.1.4
dermesser Mar 5, 2020
75ea790
examples: Add interactive encoder
dermesser Mar 16, 2020
c742e40
Address #8 and encode small integers faster
dermesser Mar 16, 2020
b831d14
Further simplify faster encoding
dermesser Mar 17, 2020
de958c3
Use faster decoding technique for signed integers too
dermesser Mar 17, 2020
944df67
Merge branch 'varint-optimize'
dermesser Mar 17, 2020
f5b7f99
Publish v1.1.5 with optimized varint encoding
dermesser Mar 17, 2020
24953ef
Return error for unterminated varint (Fix #9)
yihuang Jul 1, 2020
71d0d5c
Merge pull request #10 from yihuang/issue9
dermesser Aug 30, 2020
782c0ed
Publish v1.2.0 with new API
dermesser Aug 30, 2020
3e43a52
Fix wrong type in VarIntAsyncReader
dermesser Aug 30, 2020
6de0d9f
rustfmt
dermesser Aug 30, 2020
05ed973
v1.2.1: Fix broken build
dermesser Aug 30, 2020
40d4d6c
Publish v2.0.0
dermesser Sep 1, 2020
0788a3c
Upgrade tokio to v0.3
devashishdxt Oct 16, 2020
f33dda7
Merge branch 'devashishdxt-tokio-upgrade'
dermesser Oct 16, 2020
f221891
Increment version: v2.1
dermesser Oct 16, 2020
e4ac3d4
Travis-CI: Also test futures_async and default features
dermesser Oct 16, 2020
3cd15e5
Make examples conform to canonical example structure
dermesser Oct 21, 2020
736e35b
Add examples to travis CI config
dermesser Oct 21, 2020
6686a69
Test code on OS X and Windows too.
dermesser Oct 21, 2020
74d12b4
Restructure Travis CI config
dermesser Oct 21, 2020
a0e9935
Move language statement into job section
dermesser Oct 21, 2020
f938f73
Simplify Travis configuration
dermesser Oct 21, 2020
3b64d7f
Merge branch 'travis-all-os'
dermesser Oct 21, 2020
debc56d
Fix VarInt decoding with extra bytes at the end
jamesbornholt Oct 21, 2020
8ec9a9e
Merge pull request #13 from jamesbornholt/master
dermesser Oct 22, 2020
d867acd
Publish v2.1.1
dermesser Oct 22, 2020
19df52d
README: Point to v2.0 branch
dermesser Oct 22, 2020
ca30e46
Slightly extend documentation
dermesser Oct 28, 2020
9b0af21
Finally add (micro-)benchmarks
dermesser Oct 28, 2020
ac7e5a7
Bench: Encode different integers to make caching harder for CPU/compiler
dermesser Oct 28, 2020
f4c9fc1
Shorten varint impl of i64 by reusing u64 functionality
dermesser Oct 31, 2020
7c61d89
varint: Make more methods inline
dermesser Oct 31, 2020
c2c6ef0
varint: Undo codesharing where it hurt efficiency
dermesser Oct 31, 2020
776fd34
Add Github Actions configuration
dermesser Dec 10, 2020
fb7f5fa
Replace build status badge
dermesser Dec 10, 2020
ac8a811
update tokio => 1.0
Jan 6, 2021
31a3031
fix tokio use path
Jan 6, 2021
5e61738
fix warning
Jan 6, 2021
80fd0d4
Also run CI on pull requests
dermesser Jan 6, 2021
a2beb9f
Merge pull request #16 from shuoli84/master
dermesser Jan 6, 2021
01ef274
Release v3.0.0 with tokio 1.0
dermesser Jan 6, 2021
0b70c71
Set license instead of license-file in Cargo.toml
dermesser Jan 10, 2021
79b21e0
Release v3.0.1
dermesser Jan 10, 2021
6579286
Use write_all instead of write in Writer types
dermesser Feb 15, 2021
14cd007
Release v3.0.2
dermesser Feb 15, 2021
422691d
for #21: Respect size limits of varints of different sizes
dermesser Jan 28, 2022
38d19c5
Fix wrong invocation of VarIntProcessor::new()
dermesser Jan 28, 2022
4e35909
Replace unaligned pointer deref with read_unaligned
saethlin Jan 31, 2022
0b63de9
Add regression test
dermesser Feb 22, 2022
8f590d5
Merge pull request #23 from saethlin/master
dermesser Feb 22, 2022
51be5aa
Merge pull request #22 from dermesser/better-size-limit
dermesser Feb 22, 2022
ff6877a
Bump version to v3.0.3
dermesser Feb 22, 2022
f80445a
For #24: respect endianness
dermesser May 21, 2022
46f5f3e
on #24: partially revert previous commit as I double-fixed the issue
dermesser May 22, 2022
ed0de30
Impl FixedInt for i8/u8 and fix size for isize/usize
changrui0608 Jun 19, 2022
919dfb3
Merge pull request #25 from raaay0608/master
dermesser Jun 22, 2022
ab48af6
Publish v3.0.4
dermesser Jun 22, 2022
6da6d58
Add convenient endianness conversion for #26
dermesser Jun 23, 2022
b2bcc61
Mitigate UB
jorgecarleitao Aug 13, 2022
9ca9fbe
Proposal
jorgecarleitao Aug 13, 2022
60d869e
Merge pull request #30 from jorgecarleitao/fix_ub
dermesser Sep 30, 2022
f6e00a5
Revise API for fixed integer coding
dermesser Sep 30, 2022
7800f23
Consolidate fixed integer API methods
dermesser Sep 30, 2022
ecb5668
CI: implement features/platform matrix
dermesser Sep 30, 2022
0250d52
Correctly configure matrix
dermesser Sep 30, 2022
6a86e90
feat: remove not required `Send` bound
dignifiedquire Jun 28, 2023
f8a2339
Merge pull request #32 from dignifiedquire/feat-no-send-bound
dermesser Jun 30, 2023
6120c78
Release v4.0.0
dermesser Jun 30, 2023
4f57046
Fix clippy warnings
dermesser Aug 31, 2023
d6a6d1a
Change assert! to debug_assert! in hot paths
dermesser Aug 1, 2024
8ebf708
Release v4.0.1
dermesser Aug 1, 2024
5ef95f8
Release v4.0.2
dermesser Aug 1, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
on: [push, pull_request]

name: Actions CI

jobs:
build_and_test:
name: integer-encoding-rs
strategy:
fail-fast: false
matrix:
features: ["tokio_async", "futures_async", ""]
platform: [ubuntu-latest, windows-latest, macos-latest]
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
- uses: actions-rs/cargo@v1
with:
command: check
args: --no-default-features --features=${{ matrix.features }}
- uses: actions-rs/cargo@v1
with:
command: test
args: --no-default-features --features=${{ matrix.features }}
17 changes: 13 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
language: rust

# Test on the latest versions of all channels.
os:
- linux
- osx
- windows
dist: focal
rust:
- stable
- beta
- nightly
- stable
- nightly

# Test on the latest versions of all channels.
script:
- cargo test --features tokio_async --verbose
- cargo test --features futures_async --verbose
- cargo test --verbose
- cargo build --examples
# Run this build on the "container-based infrastructure"
# See http://docs.travis-ci.com/user/workers/container-based-infrastructure/.
sudo: false
34 changes: 32 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,41 @@
[package]
name = "integer-encoding"
version = "1.0.7"
version = "4.0.2"
authors = ["Lewin Bormann <[email protected]>"]
description = "varint+zigzag and fixedint integer encoding/decoding (https://developers.google.com/protocol-buffers/docs/encoding)"
repository = "https://github.com/dermesser/integer-encoding-rs"
documentation = "https://docs.rs/integer-encoding/"
license-file = "LICENSE"
license = "MIT"
keywords = ["integer", "varint", "zigzag", "protobuf", "serialize"]
edition = "2018"

[dependencies]
async-trait = { version = "0.1", optional = true }
tokio = { version = "1.0", features = ["io-util"], optional = true }
futures-util = { version = "0.3", optional = true, features = ["io"] }

[dev-dependencies]
tokio = { version = "1.0", features = ["fs", "rt-multi-thread", "macros"] }
bencher = "~0.1"

[[example]]
name = "encode_varint_from_stdin"
required-features = ["tokio_async"]

[[example]]
name = "read_write_file"
required-features = ["tokio_async"]

[[bench]]
name = "main"
harness = false

[features]
# Enable one of these features if you want to use the AsyncRead/AsyncWrite traits from
# the futures crate instead of those from tokio.
tokio_async = ["tokio", "async-trait"]
futures_async = ["futures-util", "async-trait"]

[package.metadata.docs.rs]
features = ["tokio_async"]

1 change: 1 addition & 0 deletions LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ The MIT License (MIT)

Copyright (c) 2016 Google Inc. ([email protected]) -- though not an official
Google product or in any way related!
Copyright (c) 2018-2020 Lewin Bormann ([email protected])

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
Expand Down
22 changes: 19 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# integer-encoding-rs

[![crates.io](https://img.shields.io/crates/v/integer-encoding.svg)](https://crates.io/crates/integer-encoding)
[![Build Status](https://travis-ci.org/dermesser/integer-encoding-rs.svg?branch=master)](https://travis-ci.org/dermesser/integer-encoding-rs)
[![Actions CI](https://github.com/dermesser/integer-encoding-rs/workflows/Actions%20CI/badge.svg)](https://github.com/dermesser/integer-encoding-rs/actions)

[full documentation](https://docs.rs/integer-encoding/)

Expand All @@ -10,11 +10,27 @@ representations.

The format is described here: [Google's protobuf integer encoding technique](https://developers.google.com/protocol-buffers/docs/encoding).

Please feel free to use `cargo bench` to determine the rate at which your
machine can encode and decode varints and fixedints. Note that one iteration
comprises each eight rounds of encoding (or decoding) a signed and an unsigned
integer each -- divide the resulting benchmark time by 16 in order to have a
rough estimate of time per operation. The integers are very large, so the
results represent the worst case.

## Crate

If you use Tokio v0.2 and you use the asynchronous types in this crate (feature
`tokio_async`), you may be interested in the `v2.0` branch. It is still
maintained with the occasional fix for edge cases and depends on Tokio v0.2.

## FixedInt

`FixedInt` casts integers to bytes by either copying the underlying memory or
performing a transmutation. The encoded values use machine endianness
(little-endian on x86).
performing a transmutation. The encoded values use are little-endian.

However, a trait method is implemented for all integer types allowing convenient conversion between
little and big endian. That is, if you receive a big-endian on the wire and decode it, it will first
be interpreted as little-endian; converting will recover the correct value.

## VarInt

Expand Down
175 changes: 175 additions & 0 deletions benches/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
use bencher::Bencher;

use integer_encoding::*;

fn encode_v(b: &mut Bencher) {
let my_u64s = [
9494929199119074561,
3823923198123425321,
2595862268225688522,
1231230009321245673,
2909812083312547546,
3492011001874124465,
4848848884210156473,
4012941340125654654,
] as [u64; 8];
let my_i64s = [
-122193043711204545,
2446312246543212452,
-445854216865433664,
3242135654513135465,
-543122132545464312,
3613543123031434343,
-431231254654543211,
7854615463131234543,
] as [i64; 8];

let mut dst = [0 as u8; 10];

b.iter(|| {
// 8x each.
my_u64s[0].encode_var(&mut dst);
my_u64s[1].encode_var(&mut dst);
my_u64s[2].encode_var(&mut dst);
my_u64s[3].encode_var(&mut dst);
my_u64s[4].encode_var(&mut dst);
my_u64s[5].encode_var(&mut dst);
my_u64s[6].encode_var(&mut dst);
my_u64s[7].encode_var(&mut dst);

my_i64s[0].encode_var(&mut dst);
my_i64s[1].encode_var(&mut dst);
my_i64s[2].encode_var(&mut dst);
my_i64s[3].encode_var(&mut dst);
my_i64s[4].encode_var(&mut dst);
my_i64s[5].encode_var(&mut dst);
my_i64s[6].encode_var(&mut dst);
my_i64s[7].encode_var(&mut dst);
});
}

fn decode_v(b: &mut Bencher) {
let my_u64s = [
9494929199119074561,
3823923198123425321,
2595862268225688522,
1231230009321245673,
2909812083312547546,
3492011001874124465,
4848848884210156473,
4012941340125654654,
] as [u64; 8];
let my_i64s = [
-122193043711204545,
2446312246543212452,
-445854216865433664,
3242135654513135465,
-543122132545464312,
3613543123031434343,
-431231254654543211,
7854615463131234543,
] as [i64; 8];

let u64_src = [
my_u64s[0].encode_var_vec(),
my_u64s[1].encode_var_vec(),
my_u64s[2].encode_var_vec(),
my_u64s[3].encode_var_vec(),
my_u64s[4].encode_var_vec(),
my_u64s[5].encode_var_vec(),
my_u64s[6].encode_var_vec(),
my_u64s[7].encode_var_vec(),
] as [Vec<u8>; 8];
let i64_src = [
my_i64s[0].encode_var_vec(),
my_i64s[1].encode_var_vec(),
my_i64s[2].encode_var_vec(),
my_i64s[3].encode_var_vec(),
my_i64s[4].encode_var_vec(),
my_i64s[5].encode_var_vec(),
my_i64s[6].encode_var_vec(),
my_i64s[7].encode_var_vec(),
] as [Vec<u8>; 8];

b.iter(|| {
// 8x each.
u64::decode_var(&u64_src[0]).unwrap();
u64::decode_var(&u64_src[1]).unwrap();
u64::decode_var(&u64_src[2]).unwrap();
u64::decode_var(&u64_src[3]).unwrap();
u64::decode_var(&u64_src[4]).unwrap();
u64::decode_var(&u64_src[5]).unwrap();
u64::decode_var(&u64_src[6]).unwrap();
u64::decode_var(&u64_src[7]).unwrap();

i64::decode_var(&i64_src[0]).unwrap();
i64::decode_var(&i64_src[1]).unwrap();
i64::decode_var(&i64_src[2]).unwrap();
i64::decode_var(&i64_src[3]).unwrap();
i64::decode_var(&i64_src[4]).unwrap();
i64::decode_var(&i64_src[5]).unwrap();
i64::decode_var(&i64_src[6]).unwrap();
i64::decode_var(&i64_src[7]).unwrap();
});
}

bencher::benchmark_group!(varint_benches, encode_v, decode_v);

fn encode_f(b: &mut Bencher) {
let my_u64 = 94949291991190 as u64;
let my_i64 = -12219304371120 as i64;

let mut dst = [0 as u8; 8];

b.iter(|| {
// 8x each.
my_u64.encode_fixed(&mut dst);
my_u64.encode_fixed(&mut dst);
my_u64.encode_fixed(&mut dst);
my_u64.encode_fixed(&mut dst);
my_u64.encode_fixed(&mut dst);
my_u64.encode_fixed(&mut dst);
my_u64.encode_fixed(&mut dst);

my_i64.encode_fixed(&mut dst);
my_i64.encode_fixed(&mut dst);
my_i64.encode_fixed(&mut dst);
my_i64.encode_fixed(&mut dst);
my_i64.encode_fixed(&mut dst);
my_i64.encode_fixed(&mut dst);
my_i64.encode_fixed(&mut dst);
my_i64.encode_fixed(&mut dst);
});
}

fn decode_f(b: &mut Bencher) {
let my_u64 = 94949291991190 as u64;
let my_i64 = -12219304371120 as i64;

let u64_src = my_u64.encode_fixed_vec();
let i64_src = my_i64.encode_fixed_vec();

b.iter(|| {
// 8x each.
u64::decode_fixed(&u64_src);
u64::decode_fixed(&u64_src);
u64::decode_fixed(&u64_src);
u64::decode_fixed(&u64_src);
u64::decode_fixed(&u64_src);
u64::decode_fixed(&u64_src);
u64::decode_fixed(&u64_src);

i64::decode_fixed(&i64_src);
i64::decode_fixed(&i64_src);
i64::decode_fixed(&i64_src);
i64::decode_fixed(&i64_src);
i64::decode_fixed(&i64_src);
i64::decode_fixed(&i64_src);
i64::decode_fixed(&i64_src);
i64::decode_fixed(&i64_src);
});
}

bencher::benchmark_group!(fixedint_benches, encode_f, decode_f);

bencher::benchmark_main!(varint_benches, fixedint_benches);
14 changes: 14 additions & 0 deletions coverage.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/bash

set -x

KCOV=kcov
KCOV_OPTS="--exclude-pattern=/.cargo,/glibc,/usr/lib,/usr/include"
KCOV_OUT="./kcov-out/"

export RUSTFLAGS="-C link-dead-code"

TEST_BIN=$(cargo test 2>&1 > /dev/null | awk '/^ Running target\/debug\/deps\// { print $2 }')

echo $TEST_BIN
${KCOV} ${KCOV_OPTS} ${KCOV_OUT} ${TEST_BIN} && xdg-open ${KCOV_OUT}/index.html
37 changes: 37 additions & 0 deletions examples/encode_varint_from_stdin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use integer_encoding::VarInt;

use std::io::{self, BufRead};
use std::str::FromStr;

fn binencode(b: &[u8]) -> String {
let mut s = String::new();
for byte in b {
s.push_str(&format!("{:08b} ", byte));
}
s
}

fn main() {
let stdin = io::BufReader::new(io::stdin());

println!("Enter decimal numbers here:\n");
for l in stdin.lines() {
if l.is_err() {
break;
}
let l = l.unwrap();
match i64::from_str(&l) {
Ok(i) => println!(
"fixed: {:b} encoded (unsigned): {} encoded (signed): {}",
i,
if i >= 0 {
binencode(&(i as u64).encode_var_vec())
} else {
"-".to_string()
},
binencode(&i.encode_var_vec())
),
Err(e) => println!("{:?}", e),
}
}
}
Loading