Skip to content

Commit

Permalink
Position API (#31)
Browse files Browse the repository at this point in the history
The position API is a compiletime function finding the position of a substring (needle) in a larger string (haystack).
Its use case is pooling string literals together in a single obfstr instance where the original string can be sliced given its position in the larger pool.
  • Loading branch information
CasualX authored Jan 31, 2021
1 parent 3f33863 commit e9a301c
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 2 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "obfstr"
version = "0.2.2"
version = "0.2.3"
edition = "2018"
license = "MIT"

Expand Down
54 changes: 53 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Compiletime string constant obfuscation.
#![feature(min_const_generics)]
#![no_std]

use core::{char, fmt, str};
use core::{char, fmt, ops, str};

//----------------------------------------------------------------

Expand Down Expand Up @@ -107,6 +107,58 @@ pub const SEED: u64 = splitmix(hash(env!("OBFSTR_SEED")) as u64);

//----------------------------------------------------------------

/// Finds the position of the needle in the haystack at compiletime.
///
/// Produces a const-eval error if the needle is not a substring of the haystack.
///
/// ```
/// assert_eq!(obfstr::position!("haystack", "st"), 3..5);
///# assert_eq!(obfstr::position!("haystack", "haystack"), 0..8);
///# assert_eq!(obfstr::position!("haystack", "ck"), 6..8);
/// ```
#[macro_export]
macro_rules! position {
($haystack:expr, $needle:expr) => {{
const POSITION: ::core::ops::Range<usize> = $crate::position($haystack, $needle);
POSITION
}};
}

/// Finds the position of the needle in the haystack at compiletime.
///
/// Produces a const-eval error if the needle is not a substring of the haystack.
///
/// ```
/// const POSITION: std::ops::Range<usize> = obfstr::position("haystack", "st");
/// assert_eq!(POSITION, 3..5);
/// ```
pub const fn position(haystack: &str, needle: &str) -> ops::Range<usize> {
const fn check(haystack: &[u8], needle: &[u8], offset: usize) -> bool {
let mut i = 0;
while i < needle.len() {
if haystack[offset + i] != needle[i] {
return false;
}
i += 1;
}
return true;
}
let mut offset = 0;
let haystack = haystack.as_bytes();
let needle = needle.as_bytes();
while offset + needle.len() <= haystack.len() {
if check(haystack, needle, offset) {
return offset..offset + needle.len();
}
offset += 1;
}
// Compile error if substring not found
let _ = haystack[haystack.len()];
return 0..0;
}

//----------------------------------------------------------------

/// Wide string constant, returns an array of words.
///
/// The type of the returned constant is `&'static [u16; LEN]`.
Expand Down

0 comments on commit e9a301c

Please sign in to comment.