# `azathoth_transformers`
A `no_std`-compatible data transformation library for the [Azathoth C2 systems](https://github.com/AzathothC2/).
## Features
- **Chainable transformer pipelines**: Can be used to chain multiple transformers together to create a pipeline of data
transformation
- **Reverse-able**: Each type that implements the `Transformer` trait must also implement a `reverse` function for it
- **`no_std` by default**: doesn't link the `std` crate, thus lowering the fingerprint
## Installation
Manually adding to `Cargo.toml`:
```toml
[dependencies]
azathoth_transformers = "0.1.0"
```
With `std` and `serde` support:
```toml
[dependencies]
azathoth_transformers = { version = "0.1.0", features = ["std"] }
```
Using `cargo`:
```shell
cargo add azathoth_transformers
```
With `std` and `serde` support:
```shell
cargo add azathoth_transformers -F std
```
## Quickstart
```rust
use azathoth_transformers::{TransformerPipeline, TransformerExt, TransformerError};
use azathoth_transformers::basic::{AppendTransformer, PrependTransformer};
fn main() -> Result<(), TransformerError> {
let mut pipeline = TransformerPipeline::new();
pipeline.add(AppendTransformer::new(" world"));
pipeline.add(PrependTransformer::new("abc "));
let result = pipeline.apply("hello").unwrap();
assert_eq!(result, b"abc hello world");
let reversed = pipeline.reverse(result).unwrap();
assert_eq!(reversed, b"hello");
Ok(())
}
```
## Default Transformers
The crate comes with a few basic transformers that I thought would be nice to have
| `AppendTransformer` | Appends a suffix to the data |
| `PrependTransformer` | Prepends a prefix to the data |
| `XorTransformer` | Basic XOR encoding with a key |
## Implementing Custom Transformers
Implementing custom transformers is pretty straight-forward:
```rust
use azathoth_transformers::{Transformer, TransformerError};
#[derive(Clone)]
struct UppercaseTransformer;
impl Transformer for UppercaseTransformer {
fn apply_bytes(&mut self, data: &[u8]) -> Result<Vec<u8>, TransformerError> {
Ok(data.iter().map(|b| b.to_ascii_uppercase()).collect())
}
fn reverse_bytes(&mut self, data: &[u8]) -> Result<Vec<u8>, TransformerError> {
Ok(data.iter().map(|b| b.to_ascii_lowercase()).collect())
}
fn name(&self) -> Option<&'static str> {
"uppercase"
}
fn box_clone(&self) -> Box<dyn Transformer> {
Box::new(self.clone())
}
}
```
## License
MIT