rust API ok

master
Avril 4 years ago
parent 5a9a8d97d6
commit 10e5b7fb44
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -1,14 +1,19 @@
[package] [package]
name = "khash" name = "khash"
description = "Kana hashes" description = "Kana hashes"
version = "1.2.0" version = "2.0.0"
authors = ["Avril <flanchan@cumallover.me>"] authors = ["Avril <flanchan@cumallover.me>"]
edition = "2018" edition = "2018"
license = "GPL-3.0-or-later" license = "GPL-3.0-or-later"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib] [lib]
crate-type = ["cdylib", "staticlib"] crate-type = ["rlib", "cdylib", "staticlib"]
[features]
default = ["ffi"]
ffi = []
[profile.release] [profile.release]
opt-level = 3 opt-level = 3

@ -0,0 +1,166 @@
//! FFI exported functions
use super::*;
/// Calculate the length in bytes of a kana hash output.
///
/// # Note
/// Does not consume `salt`
#[no_mangle]
pub unsafe extern "C" fn khash_length(context: *const c_void, bin: *const c_void, sz: size_t, out_len: *mut size_t) -> i32
{
let context = context as *const ctx::CContext;
no_unwind!{
try error::Error::Unknown;
let context = ctx::Context::clone_from_raw(context);
let bin = HeapArray::<u8>::from_raw_copied(bin as *const u8, usize::from(sz));
let string = c_try!(generate(&context, &bin));
*out_len = string.bytes().len().into();
GENERIC_SUCCESS
}
}
/// Compute and write a kana hash output to a string.
///
/// # Note
/// Consumes `salt`
#[no_mangle]
pub unsafe extern "C" fn khash_do(context: *mut c_void, bin: *const c_void, sz: size_t, out_str: *mut c_char, str_len: size_t) -> i32
{
let context = context as *mut ctx::CContext;
no_unwind!{
try error::Error::Unknown;
let context = ctx::Context::from_raw(context);
let bin = HeapArray::<u8>::from_raw_copied(bin as *const u8, usize::from(sz));
let string: Vec<u8> = c_try!(generate(&context, &bin)).bytes().collect();
libc::memcpy(out_str as *mut c_void, &string[0] as *const u8 as *const c_void, std::cmp::min(str_len, string.len()));
GENERIC_SUCCESS
}
}
/// Free a context
#[no_mangle]
pub unsafe extern "C" fn khash_free_context(context: *mut c_void) -> i32
{
let context = context as *mut ctx::CContext;
no_unwind!{
drop(ctx::Context::from_raw(context));
GENERIC_SUCCESS
}
}
/// Create a new context
#[no_mangle]
pub unsafe extern "C" fn khash_new_context(algo: u8, salt_type: u8, bin: *const c_void, sz: size_t, nptr: *mut c_void) -> i32
{
let nptr = nptr as *mut ctx::CContext;
no_unwind!{
try error::Error::Unknown;
let salt = match salt_type {
salt::SALT_TYPE_SPECIFIC => {
let bin = HeapArray::<u8>::from_raw_copied(bin as *const u8, usize::from(sz));
salt::Salt::unfixed(&bin[..])
},
salt::SALT_TYPE_DEFAULT => {
salt::Salt::default()
},
salt::SALT_TYPE_RANDOM => {
match salt::Salt::random() {
Ok(v) => v,
Err(e) => return i32::from(error::Error::RNG(e)),
}
},
_ => {
salt::Salt::None
},
};
let context = ctx::Context::new(algo.into(), salt);
*nptr = context.into_raw();
GENERIC_SUCCESS
}
}
/// Clone a context
#[no_mangle]
pub unsafe extern "C" fn khash_clone_context(raw: *const c_void, out: *mut c_void) -> i32
{
let raw = raw as *const ctx::CContext;
let out = out as *mut ctx::CContext;
no_unwind!{
*out = ctx::Context::clone_from_raw(raw).into_raw();
GENERIC_SUCCESS
}
}
/// Free a salt allocated with `khash_new_salt`
#[no_mangle]
pub unsafe extern "C" fn khash_free_salt(salt: *mut c_void) -> i32
{
let salt = salt as *mut salt::FFI;
no_unwind!{
drop(salt::from_raw(salt));
GENERIC_SUCCESS
}
}
/// Create a new salt
#[no_mangle]
pub unsafe extern "C" fn khash_new_salt(salt_type: u8, bin: *const c_void, sz: size_t, nptr: *mut c_void) -> i32
{
let nptr = nptr as *mut salt::FFI;
no_unwind!{
try error::Error::Unknown;
match salt_type {
salt::SALT_TYPE_SPECIFIC => {
let bin = HeapArray::<u8>::from_raw_copied(bin as *const u8, usize::from(sz));
*nptr = salt::into_raw(salt::Salt::unfixed(&bin[..]));
},
salt::SALT_TYPE_DEFAULT => {
*nptr = salt::into_raw(salt::Salt::default());
},
salt::SALT_TYPE_RANDOM => {
*nptr = salt::into_raw(match salt::Salt::random() {
Ok(v) => v,
Err(e) => return i32::from(error::Error::RNG(e)),
})
},
_ => {
*nptr = salt::into_raw(salt::Salt::None);
},
}
GENERIC_SUCCESS
}
}
/// Clone a salt
#[no_mangle]
pub unsafe extern "C" fn khash_clone_salt(salt: *const c_void, out: *mut c_void) -> i32
{
let salt = salt as *const salt::FFI;
let out = out as *mut salt::FFI;
no_unwind!{
*out = salt::into_raw(salt::clone_from_raw(salt));
GENERIC_SUCCESS
}
}
/// Find the maximum length possible for a given algorithm's output.
#[no_mangle]
pub unsafe extern "C" fn khash_max_length(algo: u8, _input_sz: libc::size_t, max_len: *mut libc::size_t) -> i32
{
no_unwind!{
let hash_sz = match ctx::Algorithm::from(algo) {
ctx::Algorithm::Crc32 => std::mem::size_of::<hash::Crc32Checksum>(),
ctx::Algorithm::Crc64 => std::mem::size_of::<hash::Crc64Checksum>(),
ctx::Algorithm::Sha256 => std::mem::size_of::<hash::Sha256Hash>(),
ctx::Algorithm::Sha256Truncated => std::mem::size_of::<hash::Sha256Truncated>(),
};
*max_len = std::mem::size_of::<char>() * hash_sz;
GENERIC_SUCCESS
}
}

@ -1,3 +1,4 @@
//! Contains contexts used for algorithms
use crate::*; use crate::*;
use std::{ use std::{
io::{ io::{
@ -17,7 +18,7 @@ pub enum Algorithm
impl Default for Algorithm impl Default for Algorithm
{ {
fn default() -> Self #[inline] fn default() -> Self
{ {
Self::Sha256Truncated Self::Sha256Truncated
} }
@ -53,7 +54,6 @@ impl Context
&self.salt &self.salt
} }
pub(crate) fn compute<R: Read>(&self, mut from: R) -> Result<(usize, Box<[u8]>), error::Error> pub(crate) fn compute<R: Read>(&self, mut from: R) -> Result<(usize, Box<[u8]>), error::Error>
{ {
fn provide<P,R>(input: &mut R, salt: &salt::Salt, output: &mut usize) -> Result<Vec<u8>, error::Error> fn provide<P,R>(input: &mut R, salt: &salt::Salt, output: &mut usize) -> Result<Vec<u8>, error::Error>

@ -1,3 +1,4 @@
//! Error for kana-hash functions
use std::{ use std::{
fmt, fmt,
io, io,
@ -6,6 +7,7 @@ use std::{
/// An error value used by all kana-hash functions. /// An error value used by all kana-hash functions.
#[derive(Debug)] #[derive(Debug)]
#[non_exhaustive]
pub enum Error pub enum Error
{ {
/// There was an IO error reading or writing a buffer. /// There was an IO error reading or writing a buffer.

@ -1,5 +1,8 @@
//#![feature(const_generics)] #![cfg_attr(nightly, feature(test))]
#![allow(dead_code)] #![allow(dead_code)]
#[cfg(nightly)] extern crate test;
use std::{ use std::{
io::{ io::{
Read, Read,
@ -13,6 +16,7 @@ type HASHER = hash::Crc64Checksum;
mod tests { mod tests {
use super::*; use super::*;
use std::collections::HashMap; use std::collections::HashMap;
#[cfg(nightly)]
use test::{Bencher, black_box,}; use test::{Bencher, black_box,};
#[test] #[test]
fn distrubution() fn distrubution()
@ -223,6 +227,12 @@ pub fn generate<T: AsRef<[u8]>>(context: &ctx::Context, bytes: T) -> Result<Stri
} }
} }
/// Generate kana hash from a stream
#[inline] pub fn generate_stream<T: Read+?Sized>(context: &ctx::Context, from: &mut T) -> Result<(usize, String), error::Error>
{
compute(context, from)
}
use std::ffi::c_void; use std::ffi::c_void;
use libc::{ use libc::{
size_t, size_t,
@ -237,165 +247,7 @@ use malloc_array::{
// FFI section // FFI section
/// Calculate the length in bytes of a kana hash output. #[cfg(feature="ffi")]
/// mod c;
/// # Note #[cfg(feature="ffi")]
/// Does not consume `salt` pub use c::*;
#[no_mangle]
pub unsafe extern "C" fn khash_length(context: *const c_void, bin: *const c_void, sz: size_t, out_len: *mut size_t) -> i32
{
let context = context as *const ctx::CContext;
no_unwind!{
try error::Error::Unknown;
let context = ctx::Context::clone_from_raw(context);
let bin = HeapArray::<u8>::from_raw_copied(bin as *const u8, usize::from(sz));
let string = c_try!(generate(&context, &bin));
*out_len = string.bytes().len().into();
GENERIC_SUCCESS
}
}
/// Compute and write a kana hash output to a string.
///
/// # Note
/// Consumes `salt`
#[no_mangle]
pub unsafe extern "C" fn khash_do(context: *mut c_void, bin: *const c_void, sz: size_t, out_str: *mut c_char, str_len: size_t) -> i32
{
let context = context as *mut ctx::CContext;
no_unwind!{
try error::Error::Unknown;
let context = ctx::Context::from_raw(context);
let bin = HeapArray::<u8>::from_raw_copied(bin as *const u8, usize::from(sz));
let string: Vec<u8> = c_try!(generate(&context, &bin)).bytes().collect();
libc::memcpy(out_str as *mut c_void, &string[0] as *const u8 as *const c_void, std::cmp::min(str_len, string.len()));
GENERIC_SUCCESS
}
}
/// Free a context
#[no_mangle]
pub unsafe extern "C" fn khash_free_context(context: *mut c_void) -> i32
{
let context = context as *mut ctx::CContext;
no_unwind!{
drop(ctx::Context::from_raw(context));
GENERIC_SUCCESS
}
}
/// Create a new context
#[no_mangle]
pub unsafe extern "C" fn khash_new_context(algo: u8, salt_type: u8, bin: *const c_void, sz: size_t, nptr: *mut c_void) -> i32
{
let nptr = nptr as *mut ctx::CContext;
no_unwind!{
try error::Error::Unknown;
let salt = match salt_type {
salt::SALT_TYPE_SPECIFIC => {
let bin = HeapArray::<u8>::from_raw_copied(bin as *const u8, usize::from(sz));
salt::Salt::unfixed(&bin[..])
},
salt::SALT_TYPE_DEFAULT => {
salt::Salt::default()
},
salt::SALT_TYPE_RANDOM => {
match salt::Salt::random() {
Ok(v) => v,
Err(e) => return i32::from(error::Error::RNG(e)),
}
},
_ => {
salt::Salt::None
},
};
let context = ctx::Context::new(algo.into(), salt);
*nptr = context.into_raw();
GENERIC_SUCCESS
}
}
/// Clone a context
#[no_mangle]
pub unsafe extern "C" fn khash_clone_context(raw: *const c_void, out: *mut c_void) -> i32
{
let raw = raw as *const ctx::CContext;
let out = out as *mut ctx::CContext;
no_unwind!{
*out = ctx::Context::clone_from_raw(raw).into_raw();
GENERIC_SUCCESS
}
}
/// Free a salt allocated with `khash_new_salt`
#[no_mangle]
pub unsafe extern "C" fn khash_free_salt(salt: *mut c_void) -> i32
{
let salt = salt as *mut salt::FFI;
no_unwind!{
drop(salt::from_raw(salt));
GENERIC_SUCCESS
}
}
/// Create a new salt
#[no_mangle]
pub unsafe extern "C" fn khash_new_salt(salt_type: u8, bin: *const c_void, sz: size_t, nptr: *mut c_void) -> i32
{
let nptr = nptr as *mut salt::FFI;
no_unwind!{
try error::Error::Unknown;
match salt_type {
salt::SALT_TYPE_SPECIFIC => {
let bin = HeapArray::<u8>::from_raw_copied(bin as *const u8, usize::from(sz));
*nptr = salt::into_raw(salt::Salt::unfixed(&bin[..]));
},
salt::SALT_TYPE_DEFAULT => {
*nptr = salt::into_raw(salt::Salt::default());
},
salt::SALT_TYPE_RANDOM => {
*nptr = salt::into_raw(match salt::Salt::random() {
Ok(v) => v,
Err(e) => return i32::from(error::Error::RNG(e)),
})
},
_ => {
*nptr = salt::into_raw(salt::Salt::None);
},
}
GENERIC_SUCCESS
}
}
/// Clone a salt
#[no_mangle]
pub unsafe extern "C" fn khash_clone_salt(salt: *const c_void, out: *mut c_void) -> i32
{
let salt = salt as *const salt::FFI;
let out = out as *mut salt::FFI;
no_unwind!{
*out = salt::into_raw(salt::clone_from_raw(salt));
GENERIC_SUCCESS
}
}
/// Find the maximum length possible for a given algorithm's output.
#[no_mangle]
pub unsafe extern "C" fn khash_max_length(algo: u8, _input_sz: libc::size_t, max_len: *mut libc::size_t) -> i32
{
no_unwind!{
let hash_sz = match ctx::Algorithm::from(algo) {
ctx::Algorithm::Crc32 => std::mem::size_of::<hash::Crc32Checksum>(),
ctx::Algorithm::Crc64 => std::mem::size_of::<hash::Crc64Checksum>(),
ctx::Algorithm::Sha256 => std::mem::size_of::<hash::Sha256Hash>(),
ctx::Algorithm::Sha256Truncated => std::mem::size_of::<hash::Sha256Truncated>(),
};
*max_len = std::mem::size_of::<char>() * hash_sz;
GENERIC_SUCCESS
}
}

@ -20,6 +20,7 @@ impl Digest {
return d; return d;
} }
let sign0 = from[0] & 0x80 != 0;//unsafe { *reinterpret::value::<i8>(from) < 0 }; let sign0 = from[0] & 0x80 != 0;//unsafe { *reinterpret::value::<i8>(from) < 0 };
let range = &map::KANA_SIGN[sign0 as usize]; let range = &map::KANA_SIGN[sign0 as usize];
let kana = &map::KANA[range.clone()]; let kana = &map::KANA[range.clone()];
@ -34,6 +35,7 @@ impl Digest {
Some(_) if xor & 8 == 0 && map::KANA_SWAP2[range.start() + oneesan].is_some() => map::KANA_SWAP2[range.start()+oneesan].unwrap(), Some(_) if xor & 8 == 0 && map::KANA_SWAP2[range.start() + oneesan].is_some() => map::KANA_SWAP2[range.start()+oneesan].unwrap(),
_ => kana[oneesan], _ => kana[oneesan],
}); });
if from.len() > 1 { if from.len() > 1 {
if let Some(imoutos) = map::sub(range.start()+oneesan) { if let Some(imoutos) = map::sub(range.start()+oneesan) {
if let Some(imouto) = imoutos[usize::from(from[1]) % map::KANA_SUB.len()] if let Some(imouto) = imoutos[usize::from(from[1]) % map::KANA_SUB.len()]

Loading…
Cancel
Save