Skip to content

Commit

Permalink
[Rust]: Setup CI steps (#3035)
Browse files Browse the repository at this point in the history
  • Loading branch information
satoshiotomakan committed Mar 31, 2023
1 parent 342634d commit 1a214be
Show file tree
Hide file tree
Showing 24 changed files with 275 additions and 109 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:
- tools/install-dependencies
pull_request:
branches: [ master ]
paths:
paths:
- Dockerfile
- tools/install-dependencies

Expand Down
65 changes: 65 additions & 0 deletions .github/workflows/linux-ci-rust.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
name: Linux CI Rust

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

env:
SCCACHE_GHA_ENABLED: "true"
RUSTC_WRAPPER: "sccache"

jobs:
build:
permissions:
contents: read
checks: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install system dependencies
run: |
tools/install-sys-dependencies-linux
- name: Run sccache-cache
uses: mozilla-actions/sccache-action@v0.0.3

- name: Cache Rust
uses: Swatinem/rust-cache@v2
with:
workspaces: |
rust
- name: Install Rust dependencies
run: |
tools/install-rust-dependencies dev
- name: Check code formatting
run: |
cargo fmt --check
working-directory: rust

- name: Check Clippy warnings
run: |
cargo clippy -- -D warnings
working-directory: rust

- name: Run tests
run: |
cargo llvm-cov nextest --profile ci --no-fail-fast --lcov --output-path coverage.info
working-directory: rust

- name: Rust Test Report
uses: dorny/test-reporter@v1
if: success() || failure()
continue-on-error: true
with:
name: Rust Tests
path: |
rust/target/nextest/ci/junit.xml
reporter: java-junit

- name: Gather and check Rust code coverage
run: |
tools/check-coverage rust/coverage.stats rust/coverage.info
2 changes: 2 additions & 0 deletions rust/.config/nextest.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[profile.ci.junit]
path = "junit.xml"
1 change: 1 addition & 0 deletions rust/coverage.stats
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
83.9
7 changes: 7 additions & 0 deletions rust/rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Put a trailing comma after a block based match arm (non-block arms are not affected)
# https://github.com/rust-lang/rustfmt/blob/master/Configurations.md#match_block_trailing_comma
match_block_trailing_comma = true

# Use field initialize shorthand if possible.
# https://github.com/rust-lang/rustfmt/blob/master/Configurations.md#use_field_init_shorthand
use_field_init_shorthand = true
14 changes: 11 additions & 3 deletions rust/tw_encoding/src/base32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
// terms governing use, modification, and redistribution, is contained in the
// file LICENSE at the root of the source code distribution tree.

use std::collections::HashMap;

const ALPHABET_RFC4648: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";

pub fn encode(input: &[u8], alphabet: Option<&[u8]>, padding: bool) -> Result<String, String> {
Expand All @@ -21,13 +23,15 @@ pub fn encode(input: &[u8], alphabet: Option<&[u8]>, padding: bool) -> Result<St
buffer_size += 8;

while buffer_size >= 5 {
result.push(char::from(alphabet[(buffer >> (buffer_size - 5)) as usize & 31]));
let value = alphabet[(buffer >> (buffer_size - 5)) as usize & 31];
result.push(char::from(value));
buffer_size -= 5;
}
}

if buffer_size > 0 {
result.push(char::from(alphabet[(buffer << (5 - buffer_size)) as usize & 31]));
let value = alphabet[(buffer << (5 - buffer_size)) as usize & 31];
result.push(char::from(value));
}

if padding {
Expand All @@ -45,7 +49,11 @@ pub fn decode(input: &str, alphabet: Option<&[u8]>, padding: bool) -> Result<Vec
let mut output = Vec::new();
let mut buffer: u32 = 0;
let mut bits_left = 0;
let alphabet_map: std::collections::HashMap<u8, u32> = alphabet.iter().enumerate().map(|(i, &c)| (c, i as u32)).collect();
let alphabet_map: HashMap<u8, u32> = alphabet
.iter()
.enumerate()
.map(|(i, &c)| (c, i as u32))
.collect();
let input = if padding {
input.trim_end_matches('=')
} else {
Expand Down
39 changes: 22 additions & 17 deletions rust/tw_encoding/src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
// terms governing use, modification, and redistribution, is contained in the
// file LICENSE at the root of the source code distribution tree.

#![allow(clippy::missing_safety_doc)]

use crate::{base32, base58, base64, hex};
use bs58::Alphabet;
use std::ffi::{c_char, CStr, CString};
Expand Down Expand Up @@ -32,13 +34,13 @@ impl From<Base58Alphabet> for &Alphabet {
/// \param padding whether the padding bytes should be included.
/// \return *non-null* C-compatible, nul-terminated string.
#[no_mangle]
pub extern "C" fn encode_base32(
pub unsafe extern "C" fn encode_base32(
input: *const u8,
input_len: usize,
alphabet: *const c_char,
padding: bool,
) -> *mut c_char {
let input = unsafe { std::slice::from_raw_parts(input, input_len) };
let input = std::slice::from_raw_parts(input, input_len);

let alphabet = get_alphabet(alphabet);

Expand All @@ -54,12 +56,12 @@ pub extern "C" fn encode_base32(
/// \param padding whether the padding bytes should be trimmed when decoding.
/// \return C-compatible byte array.
#[no_mangle]
pub extern "C" fn decode_base32(
pub unsafe extern "C" fn decode_base32(
input: *const c_char,
alphabet: *const c_char,
padding: bool,
) -> CByteArray {
let input = unsafe { CStr::from_ptr(input).to_str().unwrap() };
let input = CStr::from_ptr(input).to_str().unwrap();
let alphabet = get_alphabet(alphabet);

base32::decode(input, alphabet, padding)
Expand All @@ -73,7 +75,7 @@ pub extern "C" fn decode_base32(
/// \param alphabet alphabet type.
/// \return *non-null* C-compatible, nul-terminated string.
#[no_mangle]
pub extern "C" fn encode_base58(
pub unsafe extern "C" fn encode_base58(
input: *const u8,
input_len: usize,
alphabet: Base58Alphabet,
Expand All @@ -89,8 +91,11 @@ pub extern "C" fn encode_base58(
/// \param alphabet alphabet type.
/// \return C-compatible byte array.
#[no_mangle]
pub extern "C" fn decode_base58(input: *const c_char, alphabet: Base58Alphabet) -> CByteArray {
let input = unsafe { CStr::from_ptr(input).to_str().unwrap() };
pub unsafe extern "C" fn decode_base58(
input: *const c_char,
alphabet: Base58Alphabet,
) -> CByteArray {
let input = CStr::from_ptr(input).to_str().unwrap();

base58::decode(input, alphabet.into())
.map(CByteArray::from)
Expand All @@ -103,8 +108,8 @@ pub extern "C" fn decode_base58(input: *const c_char, alphabet: Base58Alphabet)
/// \param is_url whether to use the [URL safe alphabet](https://www.rfc-editor.org/rfc/rfc3548#section-4).
/// \return *non-null* C-compatible, nul-terminated string.
#[no_mangle]
pub extern "C" fn encode_base64(data: *const u8, len: usize, is_url: bool) -> *mut c_char {
let data = unsafe { std::slice::from_raw_parts(data, len) };
pub unsafe extern "C" fn encode_base64(data: *const u8, len: usize, is_url: bool) -> *mut c_char {
let data = std::slice::from_raw_parts(data, len);
let encoded = base64::encode(data, is_url);
CString::new(encoded).unwrap().into_raw()
}
Expand All @@ -114,11 +119,11 @@ pub extern "C" fn encode_base64(data: *const u8, len: usize, is_url: bool) -> *m
/// \param is_url whether to use the [URL safe alphabet](https://www.rfc-editor.org/rfc/rfc3548#section-4).
/// \return C-compatible byte array.
#[no_mangle]
pub extern "C" fn decode_base64(data: *const c_char, is_url: bool) -> CByteArray {
pub unsafe extern "C" fn decode_base64(data: *const c_char, is_url: bool) -> CByteArray {
if data.is_null() {
return CByteArray::null();
}
let c_str = unsafe { CStr::from_ptr(data) };
let c_str = CStr::from_ptr(data);
let str_slice = c_str.to_str().unwrap();
base64::decode(str_slice, is_url)
.map(CByteArray::from)
Expand All @@ -129,19 +134,19 @@ pub extern "C" fn decode_base64(data: *const c_char, is_url: bool) -> CByteArray
/// \param data *optional* C-compatible, nul-terminated string.
/// \return C-compatible byte array.
#[no_mangle]
pub extern "C" fn decode_hex(data: *const c_char) -> CByteArray {
pub unsafe extern "C" fn decode_hex(data: *const c_char) -> CByteArray {
if data.is_null() {
return CByteArray {
data: std::ptr::null_mut(),
size: 0,
};
}
let c_str = unsafe { CStr::from_ptr(data) };
let c_str = CStr::from_ptr(data);
let hex_string = c_str.to_str().unwrap();

return hex::decode(hex_string)
hex::decode(hex_string)
.map(CByteArray::from)
.unwrap_or_else(|_| CByteArray::null());
.unwrap_or_else(|_| CByteArray::null())
}

/// Encodes the octets `data` as a hex string using lowercase characters.
Expand All @@ -150,8 +155,8 @@ pub extern "C" fn decode_hex(data: *const c_char) -> CByteArray {
/// \param prefixed whether to add `0x` prefix.
/// \return *non-null* C-compatible, nul-terminated string.
#[no_mangle]
pub extern "C" fn encode_hex(data: *const u8, len: usize, prefixed: bool) -> *mut c_char {
let data = unsafe { std::slice::from_raw_parts(data, len) };
pub unsafe extern "C" fn encode_hex(data: *const u8, len: usize, prefixed: bool) -> *mut c_char {
let data = std::slice::from_raw_parts(data, len);
let encoded = hex::encode(data, prefixed);
CString::new(encoded).unwrap().into_raw()
}
Expand Down
6 changes: 3 additions & 3 deletions rust/tw_encoding/tests/base32_ffi_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ fn test_base32_encode_helper(input: &[u8], expected: &str, alphabet: Option<&str
.map(|alphabet| CString::new(alphabet).unwrap().into_raw())
.unwrap_or_else(std::ptr::null_mut);

let result_ptr = encode_base32(input.as_ptr(), input.len(), alphabet, padding);
let result_ptr = unsafe { encode_base32(input.as_ptr(), input.len(), alphabet, padding) };
let result = unsafe { CString::from_raw(result_ptr) };
assert_eq!(result.to_str().unwrap(), expected);
}
Expand All @@ -29,7 +29,7 @@ fn test_base32_decode_helper(input: &str, expected: &[u8], alphabet: Option<&str
.map(|alphabet| CString::new(alphabet).unwrap().into_raw())
.unwrap_or_else(std::ptr::null_mut);

let decoded_ptr = decode_base32(input.as_ptr(), alphabet, padding);
let decoded_ptr = unsafe { decode_base32(input.as_ptr(), alphabet, padding) };
let decoded_slice = unsafe { std::slice::from_raw_parts(decoded_ptr.data, decoded_ptr.size) };
assert_eq!(decoded_slice, expected);
}
Expand All @@ -39,9 +39,9 @@ fn test_base32_encode() {
let input = b"Hello, world!";
let alphabet = "abcdefghijklmnopqrstuvwxyz234567";

test_base32_encode_helper(input, "JBSWY3DPFQQHO33SNRSCC===", None, true);
test_base32_encode_helper(input, "JBSWY3DPFQQHO33SNRSCC", None, false);
test_base32_encode_helper(input, "jbswy3dpfqqho33snrscc===", Some(alphabet), true);
test_base32_encode_helper(input, "JBSWY3DPFQQHO33SNRSCC===", None, true);
test_base32_encode_helper(input, "jbswy3dpfqqho33snrscc", Some(alphabet), false);
}

Expand Down
4 changes: 2 additions & 2 deletions rust/tw_encoding/tests/base58_ffi_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ fn test_base58_encode() {
let data = b"Hello, world!";
let expected = "72k1xXWG59wUsYv7h2";

let result_ptr = encode_base58(data.as_ptr(), data.len(), Base58Alphabet::Bitcoin);
let result_ptr = unsafe { encode_base58(data.as_ptr(), data.len(), Base58Alphabet::Bitcoin) };
let result = unsafe { CString::from_raw(result_ptr) };
assert_eq!(result.to_str().unwrap(), expected);
}
Expand All @@ -23,7 +23,7 @@ fn test_base58_decode() {
let expected = b"Hello, world!";

let input = CString::new(data).unwrap();
let decoded_ptr = decode_base58(input.as_ptr(), Base58Alphabet::Bitcoin);
let decoded_ptr = unsafe { decode_base58(input.as_ptr(), Base58Alphabet::Bitcoin) };
let decoded_slice = unsafe { std::slice::from_raw_parts(decoded_ptr.data, decoded_ptr.size) };
assert_eq!(decoded_slice, expected);
}
6 changes: 3 additions & 3 deletions rust/tw_encoding/tests/base64_ffi_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ fn test_decode_base64_url() {
let encoded_c_str = CString::new(encoded).unwrap();
let encoded_ptr = encoded_c_str.as_ptr();

let decoded_ptr = decode_base64(encoded_ptr, true);
let decoded_ptr = unsafe { decode_base64(encoded_ptr, true) };
let decoded_slice = unsafe { std::slice::from_raw_parts(decoded_ptr.data, decoded_ptr.size) };

assert_eq!(decoded_slice, expected);
Expand All @@ -45,7 +45,7 @@ fn test_decode_base64() {
let encoded_c_str = CString::new(encoded).unwrap();
let encoded_ptr = encoded_c_str.as_ptr();

let decoded_ptr = decode_base64(encoded_ptr, false);
let decoded_ptr = unsafe { decode_base64(encoded_ptr, false) };
let decoded_slice = unsafe { std::slice::from_raw_parts(decoded_ptr.data, decoded_ptr.size) };

assert_eq!(decoded_slice, expected);
Expand All @@ -56,6 +56,6 @@ fn test_decode_base64_invalid() {
let invalid_encoded = "_This_is_an_invalid_base64_";
let encoded_c_str = CString::new(invalid_encoded).unwrap();
let encoded_ptr = encoded_c_str.as_ptr();
let decoded_ptr = decode_base64(encoded_ptr, false);
let decoded_ptr = unsafe { decode_base64(encoded_ptr, false) };
assert_eq!(decoded_ptr.data.is_null(), true);
}
4 changes: 2 additions & 2 deletions rust/tw_encoding/tests/hex_ffi_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ fn test_decode_hex() {
let encoded_c_str = CString::new(encoded).unwrap();
let encoded_ptr = encoded_c_str.as_ptr();

let decoded_ptr = decode_hex(encoded_ptr);
let decoded_ptr = unsafe { decode_hex(encoded_ptr) };
let decoded_slice = unsafe { std::slice::from_raw_parts(decoded_ptr.data, decoded_ptr.size) };

assert_eq!(decoded_slice.is_empty(), false);
Expand All @@ -43,7 +43,7 @@ fn test_decode_hex_with_prefix() {
let encoded_c_str = CString::new(encoded).unwrap();
let encoded_ptr = encoded_c_str.as_ptr();

let decoded_ptr = decode_hex(encoded_ptr);
let decoded_ptr = unsafe { decode_hex(encoded_ptr) };
let decoded_slice = unsafe { std::slice::from_raw_parts(decoded_ptr.data, decoded_ptr.size) };

assert_eq!(decoded_slice.is_empty(), false);
Expand Down
3 changes: 1 addition & 2 deletions rust/tw_hash/src/blake2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ use blake2b_ref::Blake2bBuilder;
pub fn blake2_b(input: &[u8], hash_size: usize) -> Vec<u8> {
let mut hasher = Blake2bVar::new(hash_size).unwrap();
hasher.update(input);
let mut buf = Vec::with_capacity(hash_size);
buf.resize(hash_size, 0);
let mut buf = vec![0; hash_size];
hasher.finalize_variable(&mut buf).unwrap();
buf
}
Expand Down
Loading

0 comments on commit 1a214be

Please sign in to comment.