mirror of
https://github.com/sharkdp/hexyl.git
synced 2026-10-30 09:05:54 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c3e9cb9518 | ||
|
|
3489998c67 | ||
|
|
4594d29f73 | ||
|
|
cc73f01c34 | ||
|
|
6da15cd1e9 | ||
|
|
c82ccd5a59 | ||
|
|
19d2805729 | ||
|
|
06387bba3e | ||
|
|
595803e5e2 | ||
|
|
3793559d6f | ||
|
|
71626c28e9 | ||
|
|
532eab762d | ||
|
|
642eff6061 | ||
|
|
15dc96a946 | ||
|
|
6b2cc80cc1 | ||
|
|
1db77094da | ||
|
|
8c3f2230c6 | ||
|
|
66f8508b57 | ||
|
|
afb249e854 | ||
|
|
9432677d3a | ||
|
|
524a6c607f | ||
|
|
d69a7d8e04 | ||
|
|
b1c8606918 | ||
|
|
d9723592bf | ||
|
|
23fbb5b027 | ||
|
|
4d7004f06b | ||
|
|
c4ed6d9936 | ||
|
|
aab0596ea9 | ||
|
|
7500efffa5 | ||
|
|
80e8026416 | ||
|
|
13452f5174 | ||
|
|
48ff6ff956 | ||
|
|
54cab89821 | ||
|
|
bb6a3c0650 | ||
|
|
09c22e09b9 | ||
|
|
cc5b308fc9 | ||
|
|
153b1cccdf | ||
|
|
7217a60e6e | ||
|
|
13aec946a3 | ||
|
|
e0da7b3f82 | ||
|
|
e29a63358d | ||
|
|
2bdf5d768f | ||
|
|
a7892881f3 | ||
|
|
921a138962 |
No files matched your search
@@ -0,0 +1,315 @@
|
|||||||
|
name: CICD
|
||||||
|
|
||||||
|
env:
|
||||||
|
MIN_SUPPORTED_RUST_VERSION: "1.40.0"
|
||||||
|
CICD_INTERMEDIATES_DIR: "_cicd-intermediates"
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
tags:
|
||||||
|
- '*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
min_version:
|
||||||
|
name: Minimum supported rust version
|
||||||
|
runs-on: ubuntu-18.04
|
||||||
|
steps:
|
||||||
|
- name: Checkout source code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install rust toolchain (v${{ env.MIN_SUPPORTED_RUST_VERSION }})
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: ${{ env.MIN_SUPPORTED_RUST_VERSION }}
|
||||||
|
default: true
|
||||||
|
profile: minimal # minimal component installation (ie, no documentation)
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: test
|
||||||
|
|
||||||
|
build:
|
||||||
|
name: ${{ matrix.job.os }} (${{ matrix.job.target }})
|
||||||
|
runs-on: ${{ matrix.job.os }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
job:
|
||||||
|
- { os: ubuntu-18.04, target: arm-unknown-linux-gnueabihf , use-cross: true }
|
||||||
|
- { os: ubuntu-18.04, target: aarch64-unknown-linux-gnu , use-cross: true }
|
||||||
|
- { os: ubuntu-18.04, target: i686-unknown-linux-gnu , use-cross: true }
|
||||||
|
- { os: ubuntu-18.04, target: i686-unknown-linux-musl , use-cross: true }
|
||||||
|
- { os: ubuntu-18.04, target: x86_64-unknown-linux-gnu }
|
||||||
|
- { os: ubuntu-18.04, target: x86_64-unknown-linux-musl , use-cross: true }
|
||||||
|
- { os: macos-10.15 , target: x86_64-apple-darwin }
|
||||||
|
# - { os: windows-2019, target: i686-pc-windows-gnu } ## disabled; error: linker `i686-w64-mingw32-gcc` not found
|
||||||
|
- { os: windows-2019, target: i686-pc-windows-msvc }
|
||||||
|
- { os: windows-2019, target: x86_64-pc-windows-gnu }
|
||||||
|
- { os: windows-2019, target: x86_64-pc-windows-msvc }
|
||||||
|
steps:
|
||||||
|
- name: Checkout source code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install prerequisites
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
case ${{ matrix.job.target }} in
|
||||||
|
arm-unknown-linux-gnueabihf) sudo apt-get -y update ; sudo apt-get -y install gcc-arm-linux-gnueabihf ;;
|
||||||
|
aarch64-unknown-linux-gnu) sudo apt-get -y update ; sudo apt-get -y install gcc-aarch64-linux-gnu ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
- name: Extract crate information
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "PROJECT_NAME=$(sed -n 's/^name = "\(.*\)"/\1/p' Cargo.toml | head -n1)" >> $GITHUB_ENV
|
||||||
|
echo "PROJECT_VERSION=$(sed -n 's/^version = "\(.*\)"/\1/p' Cargo.toml | head -n1)" >> $GITHUB_ENV
|
||||||
|
echo "PROJECT_MAINTAINER=$(sed -n 's/^authors = \["\(.*\)"\]/\1/p' Cargo.toml)" >> $GITHUB_ENV
|
||||||
|
echo "PROJECT_HOMEPAGE=$(sed -n 's/^homepage = "\(.*\)"/\1/p' Cargo.toml)" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Install Rust toolchain
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: stable
|
||||||
|
target: ${{ matrix.job.target }}
|
||||||
|
override: true
|
||||||
|
profile: minimal # minimal component installation (ie, no documentation)
|
||||||
|
|
||||||
|
- name: Show version information (Rust, cargo, GCC)
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
gcc --version || true
|
||||||
|
rustup -V
|
||||||
|
rustup toolchain list
|
||||||
|
rustup default
|
||||||
|
cargo -V
|
||||||
|
rustc -V
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
use-cross: ${{ matrix.job.use-cross }}
|
||||||
|
command: build
|
||||||
|
args: --release --target=${{ matrix.job.target }}
|
||||||
|
|
||||||
|
- name: Run example
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
use-cross: ${{ matrix.job.use-cross }}
|
||||||
|
command: run
|
||||||
|
args: --release --target=${{ matrix.job.target }} --example=simple
|
||||||
|
|
||||||
|
- name: Strip debug information from executable
|
||||||
|
id: strip
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
# Figure out suffix of binary
|
||||||
|
EXE_suffix=""
|
||||||
|
case ${{ matrix.job.target }} in
|
||||||
|
*-pc-windows-*) EXE_suffix=".exe" ;;
|
||||||
|
esac;
|
||||||
|
|
||||||
|
# Figure out what strip tool to use if any
|
||||||
|
STRIP="strip"
|
||||||
|
case ${{ matrix.job.target }} in
|
||||||
|
arm-unknown-linux-gnueabihf) STRIP="arm-linux-gnueabihf-strip" ;;
|
||||||
|
aarch64-unknown-linux-gnu) STRIP="aarch64-linux-gnu-strip" ;;
|
||||||
|
*-pc-windows-msvc) STRIP="" ;;
|
||||||
|
esac;
|
||||||
|
|
||||||
|
# Setup paths
|
||||||
|
BIN_DIR="${{ env.CICD_INTERMEDIATES_DIR }}/stripped-release-bin/"
|
||||||
|
mkdir -p "${BIN_DIR}"
|
||||||
|
BIN_NAME="${{ env.PROJECT_NAME }}${EXE_suffix}"
|
||||||
|
BIN_PATH="${BIN_DIR}/${BIN_NAME}"
|
||||||
|
|
||||||
|
# Copy the release build binary to the result location
|
||||||
|
cp "target/${{ matrix.job.target }}/release/${BIN_NAME}" "${BIN_DIR}"
|
||||||
|
|
||||||
|
# Also strip if possible
|
||||||
|
if [ -n "${STRIP}" ]; then
|
||||||
|
"${STRIP}" "${BIN_PATH}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Let subsequent steps know where to find the (stripped) bin
|
||||||
|
echo ::set-output name=BIN_PATH::${BIN_PATH}
|
||||||
|
echo ::set-output name=BIN_NAME::${BIN_NAME}
|
||||||
|
|
||||||
|
- name: Set testing options
|
||||||
|
id: test-options
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
# test only library unit tests and binary for arm-type targets
|
||||||
|
unset CARGO_TEST_OPTIONS
|
||||||
|
unset CARGO_TEST_OPTIONS ; case ${{ matrix.job.target }} in arm-* | aarch64-*) CARGO_TEST_OPTIONS="--lib --bin ${PROJECT_NAME}" ;; esac;
|
||||||
|
echo ::set-output name=CARGO_TEST_OPTIONS::${CARGO_TEST_OPTIONS}
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
use-cross: ${{ matrix.job.use-cross }}
|
||||||
|
command: test
|
||||||
|
args: --target=${{ matrix.job.target }} ${{ steps.test-options.outputs.CARGO_TEST_OPTIONS}}
|
||||||
|
|
||||||
|
- name: Create tarball
|
||||||
|
id: package
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
PKG_suffix=".tar.gz" ; case ${{ matrix.job.target }} in *-pc-windows-*) PKG_suffix=".zip" ;; esac;
|
||||||
|
PKG_BASENAME=${PROJECT_NAME}-v${PROJECT_VERSION}-${{ matrix.job.target }}
|
||||||
|
PKG_NAME=${PKG_BASENAME}${PKG_suffix}
|
||||||
|
echo ::set-output name=PKG_NAME::${PKG_NAME}
|
||||||
|
|
||||||
|
PKG_STAGING="${{ env.CICD_INTERMEDIATES_DIR }}/package"
|
||||||
|
ARCHIVE_DIR="${PKG_STAGING}/${PKG_BASENAME}/"
|
||||||
|
mkdir -p "${ARCHIVE_DIR}"
|
||||||
|
|
||||||
|
# Binary
|
||||||
|
cp "${{ steps.strip.outputs.BIN_PATH }}" "$ARCHIVE_DIR"
|
||||||
|
|
||||||
|
# README, LICENSE and CHANGELOG files
|
||||||
|
cp "README.md" "LICENSE-MIT" "LICENSE-APACHE" "CHANGELOG.md" "$ARCHIVE_DIR"
|
||||||
|
|
||||||
|
# base compressed package
|
||||||
|
pushd "${PKG_STAGING}/" >/dev/null
|
||||||
|
case ${{ matrix.job.target }} in
|
||||||
|
*-pc-windows-*) 7z -y a "${PKG_NAME}" "${PKG_BASENAME}"/* | tail -2 ;;
|
||||||
|
*) tar czf "${PKG_NAME}" "${PKG_BASENAME}"/* ;;
|
||||||
|
esac;
|
||||||
|
popd >/dev/null
|
||||||
|
|
||||||
|
# Let subsequent steps know where to find the compressed package
|
||||||
|
echo ::set-output name=PKG_PATH::"${PKG_STAGING}/${PKG_NAME}"
|
||||||
|
|
||||||
|
- name: Create Debian package
|
||||||
|
id: debian-package
|
||||||
|
shell: bash
|
||||||
|
if: startsWith(matrix.job.os, 'ubuntu')
|
||||||
|
run: |
|
||||||
|
COPYRIGHT_YEARS="2018 - "$(date "+%Y")
|
||||||
|
DPKG_STAGING="${{ env.CICD_INTERMEDIATES_DIR }}/debian-package"
|
||||||
|
DPKG_DIR="${DPKG_STAGING}/dpkg"
|
||||||
|
mkdir -p "${DPKG_DIR}"
|
||||||
|
|
||||||
|
DPKG_BASENAME=${PROJECT_NAME}
|
||||||
|
DPKG_CONFLICTS=${PROJECT_NAME}-musl
|
||||||
|
case ${{ matrix.job.target }} in *-musl) DPKG_BASENAME=${PROJECT_NAME}-musl ; DPKG_CONFLICTS=${PROJECT_NAME} ;; esac;
|
||||||
|
DPKG_VERSION=${PROJECT_VERSION}
|
||||||
|
|
||||||
|
unset DPKG_ARCH
|
||||||
|
case ${{ matrix.job.target }} in
|
||||||
|
aarch64-*-linux-*) DPKG_ARCH=arm64 ;;
|
||||||
|
arm-*-linux-*hf) DPKG_ARCH=armhf ;;
|
||||||
|
i686-*-linux-*) DPKG_ARCH=i686 ;;
|
||||||
|
x86_64-*-linux-*) DPKG_ARCH=amd64 ;;
|
||||||
|
*) DPKG_ARCH=notset ;;
|
||||||
|
esac;
|
||||||
|
|
||||||
|
DPKG_NAME="${DPKG_BASENAME}_${DPKG_VERSION}_${DPKG_ARCH}.deb"
|
||||||
|
echo ::set-output name=DPKG_NAME::${DPKG_NAME}
|
||||||
|
|
||||||
|
# Binary
|
||||||
|
install -Dm755 "${{ steps.strip.outputs.BIN_PATH }}" "${DPKG_DIR}/usr/bin/${{ steps.strip.outputs.BIN_NAME }}"
|
||||||
|
|
||||||
|
# README and LICENSE
|
||||||
|
install -Dm644 "README.md" "${DPKG_DIR}/usr/share/doc/${DPKG_BASENAME}/README.md"
|
||||||
|
install -Dm644 "LICENSE-MIT" "${DPKG_DIR}/usr/share/doc/${DPKG_BASENAME}/LICENSE-MIT"
|
||||||
|
install -Dm644 "LICENSE-APACHE" "${DPKG_DIR}/usr/share/doc/${DPKG_BASENAME}/LICENSE-APACHE"
|
||||||
|
install -Dm644 "CHANGELOG.md" "${DPKG_DIR}/usr/share/doc/${DPKG_BASENAME}/changelog"
|
||||||
|
gzip -n --best "${DPKG_DIR}/usr/share/doc/${DPKG_BASENAME}/changelog"
|
||||||
|
|
||||||
|
cat > "${DPKG_DIR}/usr/share/doc/${DPKG_BASENAME}/copyright" <<EOF
|
||||||
|
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||||
|
Upstream-Name: ${{ env.PROJECT_NAME }}
|
||||||
|
Source: ${{ env.PROJECT_HOMEPAGE }}
|
||||||
|
|
||||||
|
Files: *
|
||||||
|
Copyright: ${{ env.PROJECT_MAINTAINER }}
|
||||||
|
Copyright: $COPYRIGHT_YEARS ${{ env.PROJECT_MAINTAINER }}
|
||||||
|
License: Apache-2.0 or MIT
|
||||||
|
|
||||||
|
License: Apache-2.0
|
||||||
|
On Debian systems, the complete text of the Apache-2.0 can be found in the
|
||||||
|
file /usr/share/common-licenses/Apache-2.0.
|
||||||
|
|
||||||
|
License: MIT
|
||||||
|
Permission is hereby granted, free of charge, to any
|
||||||
|
person obtaining a copy of this software and associated
|
||||||
|
documentation files (the "Software"), to deal in the
|
||||||
|
Software without restriction, including without
|
||||||
|
limitation the rights to use, copy, modify, merge,
|
||||||
|
publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software
|
||||||
|
is furnished to do so, subject to the following
|
||||||
|
conditions:
|
||||||
|
.
|
||||||
|
The above copyright notice and this permission notice
|
||||||
|
shall be included in all copies or substantial portions
|
||||||
|
of the Software.
|
||||||
|
.
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||||
|
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||||
|
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||||
|
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||||
|
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
EOF
|
||||||
|
chmod 644 "${DPKG_DIR}/usr/share/doc/${DPKG_BASENAME}/copyright"
|
||||||
|
|
||||||
|
# control file
|
||||||
|
mkdir -p "${DPKG_DIR}/DEBIAN"
|
||||||
|
cat > "${DPKG_DIR}/DEBIAN/control" <<EOF
|
||||||
|
Package: ${DPKG_BASENAME}
|
||||||
|
Version: ${DPKG_VERSION}
|
||||||
|
Section: utils
|
||||||
|
Priority: optional
|
||||||
|
Maintainer: ${{ env.PROJECT_MAINTAINER }}
|
||||||
|
Homepage: ${{ env.PROJECT_HOMEPAGE }}
|
||||||
|
Architecture: ${DPKG_ARCH}
|
||||||
|
Provides: ${{ env.PROJECT_NAME }}
|
||||||
|
Conflicts: ${DPKG_CONFLICTS}
|
||||||
|
Description: command-line tool to generate, analyze, convert and manipulate colors
|
||||||
|
EOF
|
||||||
|
|
||||||
|
DPKG_PATH="${DPKG_STAGING}/${DPKG_NAME}"
|
||||||
|
echo ::set-output name=DPKG_PATH::${DPKG_PATH}
|
||||||
|
|
||||||
|
# build dpkg
|
||||||
|
fakeroot dpkg-deb --build "${DPKG_DIR}" "${DPKG_PATH}"
|
||||||
|
|
||||||
|
- name: "Artifact upload: tarball"
|
||||||
|
uses: actions/upload-artifact@master
|
||||||
|
with:
|
||||||
|
name: ${{ steps.package.outputs.PKG_NAME }}
|
||||||
|
path: ${{ steps.package.outputs.PKG_PATH }}
|
||||||
|
|
||||||
|
- name: "Artifact upload: Debian package"
|
||||||
|
uses: actions/upload-artifact@master
|
||||||
|
if: steps.debian-package.outputs.DPKG_NAME
|
||||||
|
with:
|
||||||
|
name: ${{ steps.debian-package.outputs.DPKG_NAME }}
|
||||||
|
path: ${{ steps.debian-package.outputs.DPKG_PATH }}
|
||||||
|
|
||||||
|
- name: Check for release
|
||||||
|
id: is-release
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
unset IS_RELEASE ; if [[ $GITHUB_REF =~ ^refs/tags/v[0-9].* ]]; then IS_RELEASE='true' ; fi
|
||||||
|
echo ::set-output name=IS_RELEASE::${IS_RELEASE}
|
||||||
|
|
||||||
|
- name: Publish archives and packages
|
||||||
|
uses: softprops/action-gh-release@v1
|
||||||
|
if: steps.is-release.outputs.IS_RELEASE
|
||||||
|
with:
|
||||||
|
files: |
|
||||||
|
${{ steps.package.outputs.PKG_PATH }}
|
||||||
|
${{ steps.debian-package.outputs.DPKG_PATH }}
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
-80
@@ -1,80 +0,0 @@
|
|||||||
language: rust
|
|
||||||
cache: cargo
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
# Stable channel.
|
|
||||||
- os: linux
|
|
||||||
rust: stable
|
|
||||||
env: TARGET=x86_64-unknown-linux-gnu
|
|
||||||
- os: linux
|
|
||||||
rust: stable
|
|
||||||
env: TARGET=x86_64-unknown-linux-musl
|
|
||||||
- os: osx
|
|
||||||
rust: stable
|
|
||||||
env: TARGET=x86_64-apple-darwin
|
|
||||||
- os: windows
|
|
||||||
rust: stable
|
|
||||||
env: TARGET=x86_64-pc-windows-gnu
|
|
||||||
|
|
||||||
# Minimum Rust supported channel.
|
|
||||||
- os: linux
|
|
||||||
rust: 1.36.0
|
|
||||||
env: TARGET=x86_64-unknown-linux-gnu
|
|
||||||
|
|
||||||
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
# needed to build deb packages
|
|
||||||
- fakeroot
|
|
||||||
|
|
||||||
env:
|
|
||||||
global:
|
|
||||||
# Default target on travis-ci.
|
|
||||||
# Used as conditional check in the install stage
|
|
||||||
- HOST=x86_64-unknown-linux-gnu
|
|
||||||
# Used on the deployment script
|
|
||||||
- PROJECT_NAME=hexyl
|
|
||||||
|
|
||||||
install:
|
|
||||||
# prevent target re-add error from rustup
|
|
||||||
- if [[ $TRAVIS_OS_NAME = linux && $HOST != $TARGET ]]; then rustup target add $TARGET; fi
|
|
||||||
|
|
||||||
script:
|
|
||||||
# Incorporate TARGET env var to the build and test process
|
|
||||||
- cargo build --target $TARGET --verbose
|
|
||||||
- cargo test --target $TARGET --verbose
|
|
||||||
- cargo run --target $TARGET --example=simple
|
|
||||||
|
|
||||||
before_deploy:
|
|
||||||
- bash ci/before_deploy.bash
|
|
||||||
|
|
||||||
deploy:
|
|
||||||
provider: releases
|
|
||||||
# NOTE updating the `api_key.secure`
|
|
||||||
# - go to: https://github.com/settings/tokens/new
|
|
||||||
# - generate new token using `public_repo` scope
|
|
||||||
# - encrypt it using: `travis encrypt API_KEY_HERE`
|
|
||||||
# - paste the output below
|
|
||||||
api_key:
|
|
||||||
secure: "XHpyp21JUWI6GkV7APTwPZiJQJkRJ13E/9VALuWvDrNYF00OE8m+T0ZbG+N1WCuwewa2QQChqd5yBDlwJn+LlDPqstie69xjCt7PEhvI5ERZlbT8KUtMLI4bFIudsaa6LS6phWi/6aKb4cfn0nEYmWhpqfVfsn4Hh4F9OyOFSRmMSSXziU3kxLdIBBO4jOfoDYz+4KUX48CtIhmFy6dSb4G22jzVXL3ixGq895lVFlUzfiGJhHXoS+6KsOx1q0eIEMPC6V0VTT1loBNxKpjBPQ1b0KysCim/jRnr9mB3ko/4yWcMtIvCaZxTaQXWsQn9wAEN62x3ruKugZh3LJbtaxSvnH9PMntXZliz1HJw3Hpmn+tGLxAOm+uwHRz2C/T2ibemgmw6F8KjsjdNv7Nc2//ErIbmMvV4OlJjJI2Q3LWjnYa2gqI0L0sMqUz9HAfiY/BXLSxp19LgSvZPuHNVzMfh9ovF+Rdk1I3TyoByS8ZUi2ngnra8bSjmjtWHmkntOksjWNG6iobpjz9UxdWXPWxNJHQbRfEyTJSISpClykcSZWj+E2+tfuB3YvuRUaVOIhA3THdOSsqEesl3jkUeIhQqgRhE+Uq/XqB7MdfZ9ZTX8ZgfGFL0gjygviuWznTb0q5i4t1SgEJ2ie+ykjVyqQWa0dePtaQp8yx2PtzchJs="
|
|
||||||
# for uploading multiple files
|
|
||||||
file_glob: true
|
|
||||||
# NOTE explanation on each env variable
|
|
||||||
# - PROJECT_NAME: name of the project, set on the `env.global` above
|
|
||||||
# - TRAVIS_TAG: tag name that the build is being deployed for, usually the version number
|
|
||||||
# - TARGET: target triple of the build
|
|
||||||
file:
|
|
||||||
- $PROJECT_NAME-$TRAVIS_TAG-$TARGET.*
|
|
||||||
- $PROJECT_NAME*.deb
|
|
||||||
# don't delete artifacts from previous stage
|
|
||||||
skip_cleanup: true
|
|
||||||
on:
|
|
||||||
# deploy only if we push a tag
|
|
||||||
tags: true
|
|
||||||
# deploy only on stable channel that has TARGET env variable sets
|
|
||||||
condition: $TRAVIS_RUST_VERSION = stable && $TARGET != "x86_64-pc-windows-gnu"
|
|
||||||
|
|
||||||
notifications:
|
|
||||||
email:
|
|
||||||
on_success: never
|
|
||||||
@@ -1,3 +1,48 @@
|
|||||||
|
# unreleased
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
|
||||||
|
## Bugfixes
|
||||||
|
|
||||||
|
|
||||||
|
## Other
|
||||||
|
|
||||||
|
|
||||||
|
## Packaging
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# v0.9.0
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
- Breaking change (binary): setting the `-o/--display-offset` flag no longer overrides the value set by `--skip` [#115](https://github.com/sharkdp/hexyl/issues/115). The first displayed address is now the sum of the two values - this matches the behaviour of `xxd`.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Allow relative and negative byte offsets (e.g. `hexyl --skip=-1block`), see #99 (@ErichDonGubler)
|
||||||
|
- Added `-l` as another alias for '-n/--length' (`xxd` compatibility), see #121 and #135 (@TheDoctor314)
|
||||||
|
|
||||||
|
## Bugfixes
|
||||||
|
|
||||||
|
- Argument `--length` silently takes precedence over `--bytes`, see #105
|
||||||
|
- Print warning on empty content, see #107 and #108
|
||||||
|
- Disallow block sizes of zero, see #110
|
||||||
|
- Fix newline appearing in `--version` output, see #131 and #133 (@scimas)
|
||||||
|
|
||||||
|
## Other
|
||||||
|
|
||||||
|
- Better diagnostic messages, see #98 (@ErichDonGubler)
|
||||||
|
|
||||||
|
## Packaging
|
||||||
|
|
||||||
|
- `hexyl` is now available on snapstore, see #116 (@purveshpatel511)
|
||||||
|
|
||||||
# v0.8.0
|
# v0.8.0
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# Contributing
|
||||||
|
|
||||||
|
Thank you for considering to contribute to `hexyl`!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Add an entry to the changelog
|
||||||
|
|
||||||
|
If your contribution changes the behavior of `hexyl` (as opposed to a typo-fix
|
||||||
|
in the documentation), please update the [`CHANGELOG.md`](CHANGELOG.md) file
|
||||||
|
and describe your changes. This makes the release proess much easier and
|
||||||
|
therefore helps to get your changes into a new `hexyl` release faster.
|
||||||
|
|
||||||
|
The top of the `CHANGELOG` contains a *"unreleased"* section with a few
|
||||||
|
subsections (Features, Bugfixes, …). Please add your entry to the subsection
|
||||||
|
that best describes your change
|
||||||
|
|
||||||
|
Entries follow this format:
|
||||||
|
```
|
||||||
|
- Short description of what has been changed, see #123 (@user)
|
||||||
|
```
|
||||||
|
Here, `#123` is the number of the original issue and/or your pull request.
|
||||||
|
Please replace `@user` by your GitHub username.
|
||||||
|
|
||||||
|
|
||||||
|
## Adding a new feature
|
||||||
|
|
||||||
|
Please consider opening a [ticket](https://github.com/sharkdp/hexyl/issues/new)
|
||||||
|
first in order to give us a chance to discuss the feature first.
|
||||||
Generated
+278
-51
@@ -1,139 +1,366 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "0.7.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ansi_term"
|
name = "ansi_term"
|
||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ansi_term"
|
name = "ansi_term"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anyhow"
|
||||||
|
version = "1.0.42"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "595d3cfa7a60d4555cb5067b99f07142a08ea778de5cf993f7b75c7d8fabc486"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "assert_cmd"
|
||||||
|
version = "1.0.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d20831bd004dda4c7c372c19cdabff369f794a95e955b3f13fe460e3e1ae95f"
|
||||||
|
dependencies = [
|
||||||
|
"bstr",
|
||||||
|
"doc-comment",
|
||||||
|
"predicates",
|
||||||
|
"predicates-core",
|
||||||
|
"predicates-tree",
|
||||||
|
"wait-timeout",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atty"
|
name = "atty"
|
||||||
version = "0.2.14"
|
version = "0.2.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hermit-abi 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
"hermit-abi",
|
||||||
"libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc",
|
||||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.2.1"
|
version = "1.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bstr"
|
||||||
|
version = "0.2.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "90682c8d613ad3373e66de8c6411e0ae2ab2571e879d2efbf73558cc66f21279"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
"memchr",
|
||||||
|
"regex-automata",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "2.33.1"
|
version = "2.33.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ansi_term 0.11.0",
|
||||||
"atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
"atty",
|
||||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitflags",
|
||||||
"strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"strsim",
|
||||||
"term_size 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"term_size",
|
||||||
"textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"textwrap",
|
||||||
"unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicode-width",
|
||||||
"vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "difflib"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "doc-comment"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "float-cmp"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e1267f4ac4f343772758f7b1bdcbe767c218bbab93bb432acbf5162bbf85a6c4"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.1.13"
|
version = "0.1.19"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hexyl"
|
name = "hexyl"
|
||||||
version = "0.8.0"
|
version = "0.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ansi_term 0.12.1",
|
||||||
"atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
"anyhow",
|
||||||
"clap 2.33.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"assert_cmd",
|
||||||
"libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
|
"atty",
|
||||||
|
"clap",
|
||||||
|
"libc",
|
||||||
|
"predicates",
|
||||||
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "itertools"
|
||||||
version = "0.2.71"
|
version = "0.10.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.98"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "normalize-line-endings"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "predicates"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c6e46ca79eb4e21e2ec14430340c71250ab69332abf85521c95d3a8bc336aa76"
|
||||||
|
dependencies = [
|
||||||
|
"difflib",
|
||||||
|
"float-cmp",
|
||||||
|
"itertools",
|
||||||
|
"normalize-line-endings",
|
||||||
|
"predicates-core",
|
||||||
|
"regex",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "predicates-core"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "57e35a3326b75e49aa85f5dc6ec15b41108cf5aee58eabb1f274dd18b73c2451"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "predicates-tree"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "15f553275e5721409451eb85e15fd9a860a6e5ab4496eb215987502b5f5391f2"
|
||||||
|
dependencies = [
|
||||||
|
"predicates-core",
|
||||||
|
"treeline",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.27"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-xid",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.1.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.6.25"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.73"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-xid",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "term_size"
|
name = "term_size"
|
||||||
version = "0.3.2"
|
version = "0.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e4129646ca0ed8f45d09b929036bafad5377103edd06e50bf574b353d2b08d9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc",
|
||||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "textwrap"
|
name = "textwrap"
|
||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"term_size 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"term_size",
|
||||||
"unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicode-width",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-width"
|
name = "thiserror"
|
||||||
version = "0.1.7"
|
version = "1.0.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "93119e4feac1cbe6c798c34d3a53ea0026b0b1de6a120deef895137c0529bfe2"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vec_map"
|
name = "thiserror-impl"
|
||||||
version = "0.8.2"
|
version = "1.0.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "060d69a0afe7796bf42e9e2ff91f5ee691fb15c53d38b4b62a9a53eb23164745"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "treeline"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-width"
|
||||||
|
version = "0.1.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-xid"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wait-timeout"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.8"
|
version = "0.3.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi-i686-pc-windows-gnu",
|
||||||
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-i686-pc-windows-gnu"
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-x86_64-pc-windows-gnu"
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
[metadata]
|
|
||||||
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
|
||||||
"checksum ansi_term 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
|
|
||||||
"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
|
||||||
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
|
||||||
"checksum clap 2.33.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129"
|
|
||||||
"checksum hermit-abi 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "91780f809e750b0a89f5544be56617ff6b1227ee485bcb06ebe10cdf89bd3b71"
|
|
||||||
"checksum libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)" = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49"
|
|
||||||
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
|
||||||
"checksum term_size 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1e4129646ca0ed8f45d09b929036bafad5377103edd06e50bf574b353d2b08d9"
|
|
||||||
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
|
||||||
"checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
|
|
||||||
"checksum vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
|
||||||
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
|
|
||||||
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
|
||||||
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
|
||||||
+8
-1
@@ -7,18 +7,25 @@ license = "MIT/Apache-2.0"
|
|||||||
name = "hexyl"
|
name = "hexyl"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
repository = "https://github.com/sharkdp/hexyl"
|
repository = "https://github.com/sharkdp/hexyl"
|
||||||
version = "0.8.0"
|
version = "0.9.0"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ansi_term = "0.12"
|
ansi_term = "0.12"
|
||||||
|
anyhow = "1.0.31"
|
||||||
atty = "0.2"
|
atty = "0.2"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
|
thiserror = "1.0.19"
|
||||||
|
|
||||||
[dependencies.clap]
|
[dependencies.clap]
|
||||||
version = "2"
|
version = "2"
|
||||||
|
default-features = false
|
||||||
features = ["suggestions", "color", "wrap_help"]
|
features = ["suggestions", "color", "wrap_help"]
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
assert_cmd = "1.0"
|
||||||
|
predicates = "2.0"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = true
|
lto = true
|
||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
@@ -1,6 +1,6 @@
|
|||||||

|

|
||||||
|
|
||||||
[](https://travis-ci.org/sharkdp/hexyl)
|
[](https://github.com/sharkdp/hexyl/actions/workflows/CICD.yml)
|
||||||
[](https://crates.io/crates/hexyl)
|
[](https://crates.io/crates/hexyl)
|
||||||

|

|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ If you use an older version of Ubuntu, you can download
|
|||||||
the latest `.deb` package from the release page and install it via:
|
the latest `.deb` package from the release page and install it via:
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
sudo dpkg -i hexyl_0.7.0_amd64.deb # adapt version number and architecture
|
sudo dpkg -i hexyl_0.9.0_amd64.deb # adapt version number and architecture
|
||||||
```
|
```
|
||||||
|
|
||||||
### On Debian
|
### On Debian
|
||||||
@@ -57,24 +57,59 @@ pacman -S hexyl
|
|||||||
xbps-install hexyl
|
xbps-install hexyl
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### On Gentoo Linux
|
||||||
|
|
||||||
|
Available in [dm9pZCAq overlay](https://github.com/gentoo-mirror/dm9pZCAq)
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo eselect repository enable dm9pZCAq
|
||||||
|
sudo emerge --sync dm9pZCAq
|
||||||
|
sudo emerge sys-apps/hexyl::dm9pZCAq
|
||||||
|
```
|
||||||
|
|
||||||
### On macOS
|
### On macOS
|
||||||
|
|
||||||
|
Via [Homebrew](https://brew.sh):
|
||||||
|
|
||||||
```
|
```
|
||||||
brew install hexyl
|
brew install hexyl
|
||||||
```
|
```
|
||||||
|
|
||||||
|
...or via [MacPorts](https://www.macports.org):
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo port install hexyl
|
||||||
|
```
|
||||||
|
|
||||||
### On FreeBSD
|
### On FreeBSD
|
||||||
|
|
||||||
```
|
```
|
||||||
pkg install hexyl
|
pkg install hexyl
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### on Termux
|
||||||
|
```
|
||||||
|
pkg install hexyl
|
||||||
|
```
|
||||||
|
or
|
||||||
|
```
|
||||||
|
apt install hexyl
|
||||||
|
```
|
||||||
|
|
||||||
### Via Nix
|
### Via Nix
|
||||||
|
|
||||||
```
|
```
|
||||||
nix-env -i hexyl
|
nix-env -i hexyl
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Via Guix
|
||||||
|
|
||||||
|
```
|
||||||
|
guix package -i hexyl
|
||||||
|
```
|
||||||
|
|
||||||
|
Or add the `hexyl` package in the list of packages to be installed in your system configuration (e.g., `/etc/config.scm`).
|
||||||
|
|
||||||
### On other distributions
|
### On other distributions
|
||||||
|
|
||||||
Check out the [release page](https://github.com/sharkdp/hexyl/releases) for binary builds.
|
Check out the [release page](https://github.com/sharkdp/hexyl/releases) for binary builds.
|
||||||
@@ -87,11 +122,19 @@ or Windows Terminal since Windows 10 1903).
|
|||||||
|
|
||||||
### Via cargo
|
### Via cargo
|
||||||
|
|
||||||
If you have Rust 1.36 or higher, you can install `hexyl` from source via `cargo`:
|
If you have Rust 1.40 or higher, you can install `hexyl` from source via `cargo`:
|
||||||
```
|
```
|
||||||
cargo install hexyl
|
cargo install hexyl
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Via snap package
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo snap install hexyl
|
||||||
|
```
|
||||||
|
|
||||||
|
[Get it from the Snap Store](https://snapcraft.io/hexyl)
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Licensed under either of
|
Licensed under either of
|
||||||
|
|||||||
+304
-96
@@ -9,14 +9,19 @@ use clap::{App, AppSettings, Arg};
|
|||||||
|
|
||||||
use atty::Stream;
|
use atty::Stream;
|
||||||
|
|
||||||
|
use anyhow::{anyhow, Context, Error as AnyhowError};
|
||||||
|
|
||||||
|
use thiserror::Error as ThisError;
|
||||||
|
|
||||||
use hexyl::{BorderStyle, Input, Printer};
|
use hexyl::{BorderStyle, Input, Printer};
|
||||||
|
|
||||||
fn run() -> Result<(), Box<dyn std::error::Error>> {
|
fn run() -> Result<(), AnyhowError> {
|
||||||
let app = App::new(crate_name!())
|
let app = App::new(crate_name!())
|
||||||
.setting(AppSettings::ColorAuto)
|
.setting(AppSettings::ColorAuto)
|
||||||
.setting(AppSettings::ColoredHelp)
|
.setting(AppSettings::ColoredHelp)
|
||||||
.setting(AppSettings::DeriveDisplayOrder)
|
.setting(AppSettings::DeriveDisplayOrder)
|
||||||
.setting(AppSettings::UnifiedHelpMessage)
|
.setting(AppSettings::UnifiedHelpMessage)
|
||||||
|
.max_term_width(90)
|
||||||
.version(crate_version!())
|
.version(crate_version!())
|
||||||
.about(crate_description!())
|
.about(crate_description!())
|
||||||
.arg(
|
.arg(
|
||||||
@@ -31,7 +36,8 @@ fn run() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
.value_name("N")
|
.value_name("N")
|
||||||
.help(
|
.help(
|
||||||
"Only read N bytes from the input. The N argument can also include a \
|
"Only read N bytes from the input. The N argument can also include a \
|
||||||
unit with a decimal prefix (kB, MB, ..) or binary prefix (kiB, MiB, ..).\n\
|
unit with a decimal prefix (kB, MB, ..) or binary prefix (kiB, MiB, ..). \
|
||||||
|
The short option '-l' can be used as an alias.\n\
|
||||||
Examples: --length=64, --length=4KiB",
|
Examples: --length=64, --length=4KiB",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -41,8 +47,17 @@ fn run() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
.long("bytes")
|
.long("bytes")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.value_name("N")
|
.value_name("N")
|
||||||
|
.conflicts_with("length")
|
||||||
.help("An alias for -n/--length"),
|
.help("An alias for -n/--length"),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("count")
|
||||||
|
.short("l")
|
||||||
|
.takes_value(true)
|
||||||
|
.value_name("N")
|
||||||
|
.hidden(true)
|
||||||
|
.help("Yet another alias for -n/--length"),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("skip")
|
Arg::with_name("skip")
|
||||||
.short("s")
|
.short("s")
|
||||||
@@ -51,7 +66,8 @@ fn run() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
.value_name("N")
|
.value_name("N")
|
||||||
.help(
|
.help(
|
||||||
"Skip the first N bytes of the input. The N argument can also include \
|
"Skip the first N bytes of the input. The N argument can also include \
|
||||||
a unit (see `--length` for details)",
|
a unit (see `--length` for details)\n\
|
||||||
|
A negative value is valid and will seek from the end of the file.",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
@@ -93,7 +109,10 @@ fn run() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
.value_name("STYLE")
|
.value_name("STYLE")
|
||||||
.possible_values(&["unicode", "ascii", "none"])
|
.possible_values(&["unicode", "ascii", "none"])
|
||||||
.default_value("unicode")
|
.default_value("unicode")
|
||||||
.help("Whether to draw a border with Unicode characters, ASCII characters, or none at all"),
|
.help(
|
||||||
|
"Whether to draw a border with Unicode characters, ASCII characters, \
|
||||||
|
or none at all",
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("display_offset")
|
Arg::with_name("display_offset")
|
||||||
@@ -101,39 +120,82 @@ fn run() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
.long("display-offset")
|
.long("display-offset")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.value_name("N")
|
.value_name("N")
|
||||||
.help("Add N bytes to the displayed file position. The N argument can also include \
|
.help(
|
||||||
a unit (see `--length` for details)"),
|
"Add N bytes to the displayed file position. The N argument can also \
|
||||||
|
include a unit (see `--length` for details)\n\
|
||||||
|
A negative value is valid and calculates an offset relative to the \
|
||||||
|
end of the file.",
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
let matches = app.get_matches_safe()?;
|
let matches = app.get_matches_safe()?;
|
||||||
|
|
||||||
let stdin = io::stdin();
|
let stdin = io::stdin();
|
||||||
|
|
||||||
let mut reader: Input = match matches.value_of("FILE") {
|
let mut reader = match matches.value_of("FILE") {
|
||||||
Some(filename) => Input::File(File::open(filename)?),
|
Some(filename) => Input::File(File::open(filename)?),
|
||||||
None => Input::Stdin(stdin.lock()),
|
None => Input::Stdin(stdin.lock()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let block_size = matches
|
let block_size = matches
|
||||||
.value_of("block_size")
|
.value_of("block_size")
|
||||||
.and_then(|bs| bs.parse().ok().and_then(PositiveI64::new))
|
.map(|bs| {
|
||||||
|
bs.parse::<i64>().map_err(|e| anyhow!(e)).and_then(|x| {
|
||||||
|
PositiveI64::new(x).ok_or_else(|| anyhow!("block size argument must be positive"))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.transpose()?
|
||||||
.unwrap_or_else(|| PositiveI64::new(512).unwrap());
|
.unwrap_or_else(|| PositiveI64::new(512).unwrap());
|
||||||
|
|
||||||
let skip_arg = matches
|
let skip_arg = matches
|
||||||
.value_of("skip")
|
.value_of("skip")
|
||||||
.and_then(|s| parse_byte_count(s, block_size));
|
.map(|s| {
|
||||||
|
parse_byte_offset(s, block_size).context(anyhow!(
|
||||||
|
"failed to parse `--skip` arg {:?} as byte count",
|
||||||
|
s
|
||||||
|
))
|
||||||
|
})
|
||||||
|
.transpose()?;
|
||||||
|
|
||||||
if let Some(skip) = skip_arg {
|
let skip_offset = if let Some(ByteOffset { kind, value }) = skip_arg {
|
||||||
reader.seek(SeekFrom::Current(skip.into_inner()))?;
|
let value = value.into_inner();
|
||||||
|
reader
|
||||||
|
.seek(match kind {
|
||||||
|
ByteOffsetKind::ForwardFromBeginning | ByteOffsetKind::ForwardFromLastOffset => {
|
||||||
|
SeekFrom::Current(value)
|
||||||
}
|
}
|
||||||
|
ByteOffsetKind::BackwardFromEnd => SeekFrom::End(value.checked_neg().unwrap()),
|
||||||
|
})
|
||||||
|
.map_err(|_| {
|
||||||
|
anyhow!(
|
||||||
|
"Failed to jump to the desired input position. \
|
||||||
|
This could be caused by a negative offset that is too large or by \
|
||||||
|
an input that is not seek-able (e.g. if the input comes from a pipe)."
|
||||||
|
)
|
||||||
|
})?
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
let length_arg = matches
|
let parse_byte_count = |s| -> Result<u64, AnyhowError> {
|
||||||
|
Ok(parse_byte_offset(s, block_size)?
|
||||||
|
.assume_forward_offset_from_start()?
|
||||||
|
.into())
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut reader = if let Some(length) = matches
|
||||||
.value_of("length")
|
.value_of("length")
|
||||||
.or_else(|| matches.value_of("bytes"));
|
.or_else(|| matches.value_of("bytes"))
|
||||||
|
.or_else(|| matches.value_of("count"))
|
||||||
let mut reader = if let Some(length) = length_arg.and_then(|s| parse_byte_count(s, block_size))
|
.map(|s| {
|
||||||
|
parse_byte_count(s).context(anyhow!(
|
||||||
|
"failed to parse `--length` arg {:?} as byte count",
|
||||||
|
s
|
||||||
|
))
|
||||||
|
})
|
||||||
|
.transpose()?
|
||||||
{
|
{
|
||||||
Box::new(reader.take(length.into()))
|
Box::new(reader.take(length))
|
||||||
} else {
|
} else {
|
||||||
reader.into_inner()
|
reader.into_inner()
|
||||||
};
|
};
|
||||||
@@ -152,19 +214,24 @@ fn run() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
|
|
||||||
let squeeze = !matches.is_present("nosqueezing");
|
let squeeze = !matches.is_present("nosqueezing");
|
||||||
|
|
||||||
let display_offset = matches
|
let display_offset: u64 = matches
|
||||||
.value_of("display_offset")
|
.value_of("display_offset")
|
||||||
.and_then(|s| parse_byte_count(s, block_size))
|
.map(|s| {
|
||||||
.or(skip_arg)
|
parse_byte_count(s).context(anyhow!(
|
||||||
.unwrap_or_default()
|
"failed to parse `--display-offset` arg {:?} as byte count",
|
||||||
|
s
|
||||||
|
))
|
||||||
|
})
|
||||||
|
.transpose()?
|
||||||
|
.unwrap_or(0)
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
let stdout = io::stdout();
|
let stdout = io::stdout();
|
||||||
let mut stdout_lock = stdout.lock();
|
let mut stdout_lock = stdout.lock();
|
||||||
|
|
||||||
let mut printer = Printer::new(&mut stdout_lock, show_color, border_style, squeeze);
|
let mut printer = Printer::new(&mut stdout_lock, show_color, border_style, squeeze);
|
||||||
printer.display_offset(display_offset);
|
printer.display_offset(skip_offset + display_offset);
|
||||||
printer.print_all(&mut reader)?;
|
printer.print_all(&mut reader).map_err(|e| anyhow!(e))?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -178,28 +245,57 @@ fn main() {
|
|||||||
|
|
||||||
if let Err(err) = result {
|
if let Err(err) = result {
|
||||||
if let Some(clap_err) = err.downcast_ref::<clap::Error>() {
|
if let Some(clap_err) = err.downcast_ref::<clap::Error>() {
|
||||||
eprint!("{}", clap_err); // Clap errors already have newlines
|
|
||||||
|
|
||||||
match clap_err.kind {
|
match clap_err.kind {
|
||||||
// The exit code should not indicate an error for --help / --version
|
// The exit code should not indicate an error for --help / --version
|
||||||
clap::ErrorKind::HelpDisplayed | clap::ErrorKind::VersionDisplayed => {
|
clap::ErrorKind::HelpDisplayed => {
|
||||||
|
eprint!("{}", clap_err); // Clap errors already have newlines
|
||||||
|
std::process::exit(0)
|
||||||
|
}
|
||||||
|
clap::ErrorKind::VersionDisplayed => {
|
||||||
|
// Version output in clap 2.33.1 (dep as of now) doesn't have a newline
|
||||||
|
// and the fix is not included even in the latest stable release
|
||||||
|
println!("");
|
||||||
std::process::exit(0)
|
std::process::exit(0)
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
eprintln!("Error: {}", err);
|
eprintln!("Error: {:?}", err);
|
||||||
}
|
}
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Default, Hash, Eq, Ord, PartialEq, PartialOrd)]
|
||||||
|
pub struct NonNegativeI64(i64);
|
||||||
|
|
||||||
|
impl NonNegativeI64 {
|
||||||
|
pub fn new(x: i64) -> Option<Self> {
|
||||||
|
if x.is_negative() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(Self(x))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_inner(self) -> i64 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<u64> for NonNegativeI64 {
|
||||||
|
fn into(self) -> u64 {
|
||||||
|
u64::try_from(self.0)
|
||||||
|
.expect("invariant broken: NonNegativeI64 should contain a non-negative i64 value")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default, Hash, Eq, Ord, PartialEq, PartialOrd)]
|
#[derive(Clone, Copy, Debug, Default, Hash, Eq, Ord, PartialEq, PartialOrd)]
|
||||||
pub struct PositiveI64(i64);
|
pub struct PositiveI64(i64);
|
||||||
|
|
||||||
impl PositiveI64 {
|
impl PositiveI64 {
|
||||||
pub fn new(x: i64) -> Option<Self> {
|
pub fn new(x: i64) -> Option<Self> {
|
||||||
if x.is_negative() {
|
if x < 1 {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(Self(x))
|
Some(Self(x))
|
||||||
@@ -218,34 +314,118 @@ impl Into<u64> for PositiveI64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_byte_count(n: &str, block_size: PositiveI64) -> Option<PositiveI64> {
|
const HEX_PREFIX: &str = "0x";
|
||||||
const HEX_PREFIX: &str = "0x";
|
|
||||||
|
|
||||||
let n = {
|
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||||
let mut chars = n.chars();
|
enum ByteOffsetKind {
|
||||||
match chars.next()? {
|
ForwardFromBeginning,
|
||||||
'+' => chars.as_str(),
|
ForwardFromLastOffset,
|
||||||
'-' => return None,
|
BackwardFromEnd,
|
||||||
_ => n,
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||||
|
struct ByteOffset {
|
||||||
|
value: NonNegativeI64,
|
||||||
|
kind: ByteOffsetKind,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, ThisError)]
|
||||||
|
#[error(
|
||||||
|
"negative offset specified, but only positive offsets (counts) are accepted in this context"
|
||||||
|
)]
|
||||||
|
struct NegativeOffsetSpecifiedError;
|
||||||
|
|
||||||
|
impl ByteOffset {
|
||||||
|
fn assume_forward_offset_from_start(
|
||||||
|
&self,
|
||||||
|
) -> Result<NonNegativeI64, NegativeOffsetSpecifiedError> {
|
||||||
|
let &Self { value, kind } = self;
|
||||||
|
match kind {
|
||||||
|
ByteOffsetKind::ForwardFromBeginning | ByteOffsetKind::ForwardFromLastOffset => {
|
||||||
|
Ok(value)
|
||||||
}
|
}
|
||||||
|
ByteOffsetKind::BackwardFromEnd => Err(NegativeOffsetSpecifiedError),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq, ThisError)]
|
||||||
|
enum ByteOffsetParseError {
|
||||||
|
#[error("no character data found, did you forget to write it?")]
|
||||||
|
Empty,
|
||||||
|
#[error("no digits found after sign, did you forget to write them?")]
|
||||||
|
EmptyAfterSign,
|
||||||
|
#[error(
|
||||||
|
"found {0:?} sign after hex prefix ({:?}); signs should go before it",
|
||||||
|
HEX_PREFIX
|
||||||
|
)]
|
||||||
|
SignFoundAfterHexPrefix(char),
|
||||||
|
#[error("{0:?} is not of the expected form <pos-integer>[<unit>]")]
|
||||||
|
InvalidNumAndUnit(String),
|
||||||
|
#[error("{0:?} is a valid unit, but an integer should come before it")]
|
||||||
|
EmptyWithUnit(String),
|
||||||
|
#[error("invalid unit {0:?}")]
|
||||||
|
InvalidUnit(String),
|
||||||
|
#[error("failed to parse integer part")]
|
||||||
|
ParseNum(#[source] std::num::ParseIntError),
|
||||||
|
#[error("count multipled by the unit overflowed a signed 64-bit integer; are you sure it should be that big?")]
|
||||||
|
UnitMultiplicationOverflow,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_byte_offset(n: &str, block_size: PositiveI64) -> Result<ByteOffset, ByteOffsetParseError> {
|
||||||
|
use ByteOffsetParseError::*;
|
||||||
|
|
||||||
|
let (n, kind) = {
|
||||||
|
let mut chars = n.chars();
|
||||||
|
let next_char = chars.next();
|
||||||
|
let check_empty_after_sign = || {
|
||||||
|
if chars.clone().next().is_none() {
|
||||||
|
Err(EmptyAfterSign)
|
||||||
|
} else {
|
||||||
|
Ok(chars.as_str())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
match next_char {
|
||||||
|
Some('+') => (
|
||||||
|
check_empty_after_sign()?,
|
||||||
|
ByteOffsetKind::ForwardFromLastOffset,
|
||||||
|
),
|
||||||
|
Some('-') => (check_empty_after_sign()?, ByteOffsetKind::BackwardFromEnd),
|
||||||
|
None => return Err(Empty),
|
||||||
|
_ => (n, ByteOffsetKind::ForwardFromBeginning),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let into_byte_offset = |value| {
|
||||||
|
Ok(ByteOffset {
|
||||||
|
value: NonNegativeI64::new(value).unwrap(),
|
||||||
|
kind,
|
||||||
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
if n.starts_with(HEX_PREFIX) {
|
if n.starts_with(HEX_PREFIX) {
|
||||||
let n = &n[HEX_PREFIX.len()..];
|
let n = &n[HEX_PREFIX.len()..];
|
||||||
match n.chars().next() {
|
let mut chars = n.chars();
|
||||||
Some('+') | Some('-') => return None,
|
match chars.next() {
|
||||||
|
Some(c @ '+') | Some(c @ '-') => {
|
||||||
|
return if chars.next().is_none() {
|
||||||
|
Err(EmptyAfterSign)
|
||||||
|
} else {
|
||||||
|
Err(SignFoundAfterHexPrefix(c))
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
return i64::from_str_radix(n, 16).ok().and_then(PositiveI64::new);
|
return i64::from_str_radix(n, 16)
|
||||||
|
.map(into_byte_offset)
|
||||||
|
.map_err(ParseNum)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (n, unit_multiplier) = match n.chars().position(|c| !c.is_ascii_digit()) {
|
let (num, unit) = match n.chars().position(|c| !c.is_ascii_digit()) {
|
||||||
Some(unit_begin_idx) => {
|
Some(unit_begin_idx) => {
|
||||||
let (n, raw_unit) = n.split_at(unit_begin_idx);
|
let (n, raw_unit) = n.split_at(unit_begin_idx);
|
||||||
let raw_unit = raw_unit.to_lowercase();
|
let raw_unit_lower = raw_unit.to_lowercase();
|
||||||
(
|
let multiplier = [
|
||||||
n,
|
|
||||||
[
|
|
||||||
("b", 1),
|
("b", 1),
|
||||||
("kb", 1000i64.pow(1)),
|
("kb", 1000i64.pow(1)),
|
||||||
("mb", 1000i64.pow(2)),
|
("mb", 1000i64.pow(2)),
|
||||||
@@ -260,93 +440,121 @@ fn parse_byte_count(n: &str, block_size: PositiveI64) -> Option<PositiveI64> {
|
|||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
.find_map(|(unit, multiplier)| {
|
.find_map(|(unit, multiplier)| {
|
||||||
if unit == raw_unit {
|
if unit == raw_unit_lower {
|
||||||
Some(multiplier)
|
Some(multiplier)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
})?,
|
})
|
||||||
)
|
.ok_or_else(|| InvalidUnit(raw_unit.to_owned()));
|
||||||
|
(n, multiplier.map(|m| (Some(raw_unit), m)))
|
||||||
}
|
}
|
||||||
None => (n, 1),
|
None => (n, Ok((None, 1))),
|
||||||
};
|
};
|
||||||
|
|
||||||
n.parse::<i64>()
|
match (num.parse::<i64>(), unit) {
|
||||||
.ok()?
|
(Ok(num), Ok((_raw_unit, unit_multiplier))) => num
|
||||||
.checked_mul(unit_multiplier)
|
.checked_mul(unit_multiplier)
|
||||||
.and_then(PositiveI64::new)
|
.ok_or_else(|| UnitMultiplicationOverflow)
|
||||||
|
.and_then(into_byte_offset),
|
||||||
|
(Ok(_), Err(e)) => Err(e),
|
||||||
|
(Err(e), Ok((raw_unit, _unit_multiplier))) => match raw_unit {
|
||||||
|
Some(raw_unit) if num.is_empty() => Err(EmptyWithUnit(raw_unit.to_owned())),
|
||||||
|
_ => Err(ParseNum(e)),
|
||||||
|
},
|
||||||
|
(Err(_), Err(_)) => Err(InvalidNumAndUnit(n.to_owned())),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_byte_count() {
|
fn test_parse_byte_offset() {
|
||||||
|
use ByteOffsetParseError::*;
|
||||||
|
|
||||||
macro_rules! success {
|
macro_rules! success {
|
||||||
($input: expr, $expected: expr) => {
|
($input: expr, $expected_kind: ident $expected_value: expr) => {
|
||||||
success!($input, 512, $expected)
|
success!($input, $expected_kind $expected_value; block_size: 512)
|
||||||
};
|
};
|
||||||
($input: expr, $block_size: expr, $expected: expr) => {
|
($input: expr, $expected_kind: ident $expected_value: expr; block_size: $block_size: expr) => {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_byte_count($input, PositiveI64::new($block_size).unwrap()),
|
parse_byte_offset($input, PositiveI64::new($block_size).unwrap()),
|
||||||
Some(PositiveI64::new($expected).unwrap())
|
Ok(
|
||||||
|
ByteOffset {
|
||||||
|
value: NonNegativeI64::new($expected_value).unwrap(),
|
||||||
|
kind: ByteOffsetKind::$expected_kind,
|
||||||
|
}
|
||||||
|
),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! error {
|
macro_rules! error {
|
||||||
($input: expr) => {
|
($input: expr, $expected_err: expr) => {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_byte_count($input, PositiveI64::new(512).unwrap()),
|
parse_byte_offset($input, PositiveI64::new(512).unwrap()),
|
||||||
None
|
Err($expected_err),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
success!("0", 0);
|
success!("0", ForwardFromBeginning 0);
|
||||||
success!("1", 1);
|
success!("1", ForwardFromBeginning 1);
|
||||||
success!("1", 1);
|
success!("1", ForwardFromBeginning 1);
|
||||||
success!("100", 100);
|
success!("100", ForwardFromBeginning 100);
|
||||||
success!("+100", 100);
|
success!("+100", ForwardFromLastOffset 100);
|
||||||
|
|
||||||
success!("1KB", 1000);
|
success!("0x0", ForwardFromBeginning 0);
|
||||||
success!("2MB", 2000000);
|
success!("0xf", ForwardFromBeginning 15);
|
||||||
success!("3GB", 3000000000);
|
success!("0xdeadbeef", ForwardFromBeginning 3_735_928_559);
|
||||||
success!("4TB", 4000000000000);
|
|
||||||
success!("+4TB", 4000000000000);
|
|
||||||
|
|
||||||
success!("1GiB", 1073741824);
|
success!("1KB", ForwardFromBeginning 1000);
|
||||||
success!("2TiB", 2199023255552);
|
success!("2MB", ForwardFromBeginning 2000000);
|
||||||
success!("+2TiB", 2199023255552);
|
success!("3GB", ForwardFromBeginning 3000000000);
|
||||||
|
success!("4TB", ForwardFromBeginning 4000000000000);
|
||||||
|
success!("+4TB", ForwardFromLastOffset 4000000000000);
|
||||||
|
|
||||||
success!("0xff", 255);
|
success!("1GiB", ForwardFromBeginning 1073741824);
|
||||||
success!("0xEE", 238);
|
success!("2TiB", ForwardFromBeginning 2199023255552);
|
||||||
success!("+0xFF", 255);
|
success!("+2TiB", ForwardFromLastOffset 2199023255552);
|
||||||
|
|
||||||
success!("1block", 512, 512);
|
success!("0xff", ForwardFromBeginning 255);
|
||||||
success!("2block", 512, 1024);
|
success!("0xEE", ForwardFromBeginning 238);
|
||||||
success!("1block", 4, 4);
|
success!("+0xFF", ForwardFromLastOffset 255);
|
||||||
success!("2block", 4, 8);
|
|
||||||
|
success!("1block", ForwardFromBeginning 512; block_size: 512);
|
||||||
|
success!("2block", ForwardFromBeginning 1024; block_size: 512);
|
||||||
|
success!("1block", ForwardFromBeginning 4; block_size: 4);
|
||||||
|
success!("2block", ForwardFromBeginning 8; block_size: 4);
|
||||||
|
|
||||||
// empty string is invalid
|
// empty string is invalid
|
||||||
error!("");
|
error!("", Empty);
|
||||||
// These are also bad.
|
// These are also bad.
|
||||||
error!("+");
|
error!("+", EmptyAfterSign);
|
||||||
error!("-");
|
error!("-", EmptyAfterSign);
|
||||||
error!("K");
|
error!("K", InvalidNumAndUnit("K".to_owned()));
|
||||||
error!("k");
|
error!("k", InvalidNumAndUnit("k".to_owned()));
|
||||||
error!("m");
|
error!("m", InvalidNumAndUnit("m".to_owned()));
|
||||||
error!("block");
|
error!("block", EmptyWithUnit("block".to_owned()));
|
||||||
// leading/trailing space is invalid
|
// leading/trailing space is invalid
|
||||||
error!(" 0");
|
error!(" 0", InvalidNumAndUnit(" 0".to_owned()));
|
||||||
error!("0 ");
|
error!("0 ", InvalidUnit(" ".to_owned()));
|
||||||
// Negatives make no sense for byte counts
|
// Signs after the hex prefix make no sense
|
||||||
error!("-1");
|
error!("0x-12", SignFoundAfterHexPrefix('-'));
|
||||||
error!("0x-12");
|
|
||||||
// This was previously accepted but shouldn't be.
|
// This was previously accepted but shouldn't be.
|
||||||
error!("0x+12");
|
error!("0x+12", SignFoundAfterHexPrefix('+'));
|
||||||
// invalid suffix
|
// invalid suffix
|
||||||
error!("1234asdf");
|
error!("1234asdf", InvalidUnit("asdf".to_owned()));
|
||||||
// bad numbers
|
// bad numbers
|
||||||
error!("asdf1234");
|
error!("asdf1234", InvalidNumAndUnit("asdf1234".to_owned()));
|
||||||
error!("a1s2d3f4");
|
error!("a1s2d3f4", InvalidNumAndUnit("a1s2d3f4".to_owned()));
|
||||||
// multiplication overflows u64
|
// multiplication overflows u64
|
||||||
error!("20000000TiB");
|
error!("20000000TiB", UnitMultiplicationOverflow);
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
match parse_byte_offset("99999999999999999999", PositiveI64::new(512).unwrap()) {
|
||||||
|
// We can't check against the kind of the `ParseIntError`, so we'll just make sure it's the
|
||||||
|
// same as trying to do the parse directly.
|
||||||
|
Err(ParseNum(e)) => e == "99999999999999999999".parse::<i64>().unwrap_err(),
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
+8
-1
@@ -408,7 +408,7 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
|
|||||||
pub fn print_all<Reader: Read>(
|
pub fn print_all<Reader: Read>(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut reader: Reader,
|
mut reader: Reader,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
let mut buffer = [0; BUFFER_SIZE];
|
let mut buffer = [0; BUFFER_SIZE];
|
||||||
'mainloop: loop {
|
'mainloop: loop {
|
||||||
let size = reader.read(&mut buffer)?;
|
let size = reader.read(&mut buffer)?;
|
||||||
@@ -428,8 +428,14 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
|
|||||||
|
|
||||||
// Finish last line
|
// Finish last line
|
||||||
self.print_textline().ok();
|
self.print_textline().ok();
|
||||||
|
|
||||||
if !self.header_was_printed() {
|
if !self.header_was_printed() {
|
||||||
self.header();
|
self.header();
|
||||||
|
writeln!(
|
||||||
|
self.writer,
|
||||||
|
"│ │ No content to print │ │ │ │"
|
||||||
|
)
|
||||||
|
.ok();
|
||||||
}
|
}
|
||||||
self.footer();
|
self.footer();
|
||||||
|
|
||||||
@@ -459,6 +465,7 @@ mod tests {
|
|||||||
let input = io::empty();
|
let input = io::empty();
|
||||||
let expected_string = "\
|
let expected_string = "\
|
||||||
┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐
|
┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐
|
||||||
|
│ │ No content to print │ │ │ │
|
||||||
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘
|
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘
|
||||||
"
|
"
|
||||||
.to_owned();
|
.to_owned();
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
ascii text eol=lf
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
0123456789abcde
|
||||||
Whitespace-only changes.
Executable
BIN
Binary file not shown.
@@ -0,0 +1,205 @@
|
|||||||
|
use assert_cmd::Command;
|
||||||
|
|
||||||
|
fn hexyl() -> Command {
|
||||||
|
let mut cmd = Command::cargo_bin("hexyl").unwrap();
|
||||||
|
cmd.current_dir("tests/examples");
|
||||||
|
cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
mod basic {
|
||||||
|
use super::hexyl;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn can_print_simple_ascii_file() {
|
||||||
|
hexyl()
|
||||||
|
.arg("ascii")
|
||||||
|
.arg("--color=never")
|
||||||
|
.assert()
|
||||||
|
.success()
|
||||||
|
.stdout(
|
||||||
|
"┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐\n\
|
||||||
|
│00000000│ 30 31 32 33 34 35 36 37 ┊ 38 39 61 62 63 64 65 0a │01234567┊89abcde_│\n\
|
||||||
|
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘\n",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn can_read_input_from_stdin() {
|
||||||
|
hexyl()
|
||||||
|
.arg("--color=never")
|
||||||
|
.write_stdin("abc")
|
||||||
|
.assert()
|
||||||
|
.success()
|
||||||
|
.stdout(
|
||||||
|
"┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐\n\
|
||||||
|
│00000000│ 61 62 63 ┊ │abc ┊ │\n\
|
||||||
|
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘\n",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn fails_on_non_existing_input() {
|
||||||
|
hexyl().arg("non-existing").assert().failure();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn prints_warning_on_empty_content() {
|
||||||
|
hexyl()
|
||||||
|
.arg("empty")
|
||||||
|
.arg("--color=never")
|
||||||
|
.assert()
|
||||||
|
.success()
|
||||||
|
.stdout(
|
||||||
|
"┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐\n\
|
||||||
|
│ │ No content to print │ │ │ │\n\
|
||||||
|
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘\n",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod length {
|
||||||
|
use super::hexyl;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn length_restricts_output_size() {
|
||||||
|
hexyl()
|
||||||
|
.arg("hello_world_elf64")
|
||||||
|
.arg("--color=never")
|
||||||
|
.arg("--length=32")
|
||||||
|
.assert()
|
||||||
|
.success()
|
||||||
|
.stdout(
|
||||||
|
"┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐\n\
|
||||||
|
│00000000│ 7f 45 4c 46 02 01 01 00 ┊ 00 00 00 00 00 00 00 00 │•ELF•••0┊00000000│\n\
|
||||||
|
│00000010│ 02 00 3e 00 01 00 00 00 ┊ 00 10 40 00 00 00 00 00 │•0>0•000┊0•@00000│\n\
|
||||||
|
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘\n",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn fail_if_length_and_bytes_options_are_used_simultaneously() {
|
||||||
|
hexyl()
|
||||||
|
.arg("hello_world_elf64")
|
||||||
|
.arg("--length=32")
|
||||||
|
.arg("--bytes=10")
|
||||||
|
.assert()
|
||||||
|
.failure();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod skip {
|
||||||
|
use super::hexyl;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn basic() {
|
||||||
|
hexyl()
|
||||||
|
.arg("ascii")
|
||||||
|
.arg("--color=never")
|
||||||
|
.arg("--skip=2")
|
||||||
|
.arg("--length=4")
|
||||||
|
.assert()
|
||||||
|
.success()
|
||||||
|
.stdout(
|
||||||
|
"┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐\n\
|
||||||
|
│00000002│ 32 33 34 35 ┊ │2345 ┊ │\n\
|
||||||
|
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘\n",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn prints_warning_when_skipping_past_the_end() {
|
||||||
|
hexyl()
|
||||||
|
.arg("ascii")
|
||||||
|
.arg("--color=never")
|
||||||
|
.arg("--skip=1000")
|
||||||
|
.assert()
|
||||||
|
.success()
|
||||||
|
.stdout(
|
||||||
|
"┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐\n\
|
||||||
|
│ │ No content to print │ │ │ │\n\
|
||||||
|
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘\n",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn negative_offset() {
|
||||||
|
hexyl()
|
||||||
|
.arg("ascii")
|
||||||
|
.arg("--color=never")
|
||||||
|
.arg("--skip=-4")
|
||||||
|
.arg("--length=3")
|
||||||
|
.assert()
|
||||||
|
.success()
|
||||||
|
.stdout(
|
||||||
|
"┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐\n\
|
||||||
|
│0000000c│ 63 64 65 ┊ │cde ┊ │\n\
|
||||||
|
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘\n",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn fails_if_negative_offset_is_too_large() {
|
||||||
|
hexyl()
|
||||||
|
.arg("ascii")
|
||||||
|
.arg("--color=never")
|
||||||
|
.arg("--skip=-1MiB")
|
||||||
|
.assert()
|
||||||
|
.failure()
|
||||||
|
.stderr(predicates::str::contains("Failed to jump"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod display_offset {
|
||||||
|
use super::hexyl;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn basic() {
|
||||||
|
hexyl()
|
||||||
|
.arg("ascii")
|
||||||
|
.arg("--color=never")
|
||||||
|
.arg("--display-offset=0xc0ffee")
|
||||||
|
.assert()
|
||||||
|
.success()
|
||||||
|
.stdout(
|
||||||
|
"┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐\n\
|
||||||
|
│00c0ffee│ 30 31 32 33 34 35 36 37 ┊ 38 39 61 62 63 64 65 0a │01234567┊89abcde_│\n\
|
||||||
|
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘\n",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn display_offset_and_skip() {
|
||||||
|
hexyl()
|
||||||
|
.arg("hello_world_elf64")
|
||||||
|
.arg("--color=never")
|
||||||
|
.arg("--display-offset=0x20")
|
||||||
|
.arg("--skip=0x10")
|
||||||
|
.arg("--length=0x10")
|
||||||
|
.assert()
|
||||||
|
.success()
|
||||||
|
.stdout(
|
||||||
|
"┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐\n\
|
||||||
|
│00000030│ 02 00 3e 00 01 00 00 00 ┊ 00 10 40 00 00 00 00 00 │•0>0•000┊0•@00000│\n\
|
||||||
|
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘\n",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod blocksize {
|
||||||
|
use super::hexyl;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn fails_for_zero_or_negative_blocksize() {
|
||||||
|
hexyl()
|
||||||
|
.arg("ascii")
|
||||||
|
.arg("--block-size=0")
|
||||||
|
.assert()
|
||||||
|
.failure();
|
||||||
|
|
||||||
|
hexyl()
|
||||||
|
.arg("ascii")
|
||||||
|
.arg("--block-size=-16")
|
||||||
|
.assert()
|
||||||
|
.failure();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user