# Library uses file-based mmap to store key-values

[![Crates.io](https://img.shields.io/crates/l/MMKV)](https://crates.io/crates/mmkv)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/yangkx1024/MMKV/pulls)
[![Crates.io](https://img.shields.io/crates/v/MMKV)](https://crates.io/crates/mmkv)
[![Crates.io](https://img.shields.io/crates/d/MMKV)](https://crates.io/crates/mmkv)
[![Cargo Test](https://github.com/yangkx-1024/MMKV/actions/workflows/rust.yml/badge.svg)](https://github.com/yangkx-1024/MMKV/actions/workflows/rust.yml)
[![Android Build Check](https://github.com/yangkx-1024/MMKV/actions/workflows/android.yml/badge.svg)](https://github.com/yangkx-1024/MMKV/actions/workflows/android.yml)
[![Swift Test](https://github.com/yangkx-1024/MMKV/actions/workflows/swift.yml/badge.svg)](https://github.com/yangkx-1024/MMKV/actions/workflows/swift.yml)

This is a Rust version of [MMKV](https://github.com/Tencent/MMKV).

By default, this lib uses [CRC8](https://github.com/mrhooray/crc-rs) to check data integrity.

If include feature `encryption`, this lib will encrypt the data
with [AES-EAX](https://github.com/RustCrypto/AEADs/tree/master/eax).

MMKV is thread-safe but cannot guarantee cross-process data consistency.
If you want to use it in a cross-process scenario, please ensure that there is no competing write.

## How to use

Add dependency:

`cargo add mmkv`

And use `MMKV` directly:

```rust
use mmkv::{LogLevel, MMKV};

fn main() {
    // Set the log level of the library
    MMKV::set_log_level(LogLevel::Verbose);
    let temp_dir = std::env::temp_dir();
    let dir = temp_dir.join("test1");
    let _ = std::fs::create_dir(&dir);
    // Initialize it with a directory, the library will crate a file,
    // named "mini_mmkv" under this dir.
    let mmkv = MMKV::new(dir.to_str().unwrap());
    // Put and get result, for most case should be Ok(()),
    // if something wrong, it contains the useful info.
    let ret = mmkv.put("key1", 1);
    println!("{:?}", ret); // Ok(())
    // Get result with key
    println!("{:?}", mmkv.get::<i32>("key1")); // Ok(1)
    // Put and unwrap the result
    mmkv.put("key1", "value").unwrap();
    println!("{:?}", mmkv.get::<i32>("key1")); // Err(TypeMissMatch)
    println!("{:?}", mmkv.get::<String>("key1")); // Ok("value")

    let dir = temp_dir.join("test2");
    let _ = std::fs::create_dir(&dir);
    // Create another instance with different path
    let new_mmkv = MMKV::new(dir.to_str().unwrap());
    new_mmkv.put("key1", true).unwrap();
    println!("{:?}", new_mmkv.get::<bool>("key1")); // Ok(true)
    // clear all data to free disk space
    new_mmkv.clear_data();
}
```

## Use with encryption feature

Add dependency:

`cargo add mmkv --features encryption`

Then init `MMKV` with an encryption credential:

`let mmkv = MMKV::new(".", "88C51C536176AD8A8EE4A06F62EE897E")`

Encryption will greatly reduce the efficiency of reading and writing, and will also increase the file size, use at your
own risk!

## Use in Android projects

Add lib dependency to gradle:

```kotlin
dependencies {
    implementation("net.yangkx:mmkv:0.4.0")
    // Or another one with encryption feature
    // implementation("net.yangkx:mmkv-encrypt:0.4.0")
}
```

You can find all versions in the [Releases](https://github.com/yangkx-1024/MMKV/releases).

Use the kotlin API:

```kotlin
class MyApplication : Application() {

    companion object {
        lateinit var mmkv: MMKV
    }

    override fun onCreate() {
        super.onCreate()
        MMKV.setLogLevel(LogLevel.VERBOSE)
        val dir = this.getDir("mmkv", Context.MODE_PRIVATE)
        mmkv = MMKV(dir.absolutePath)
        // If you are using mmkv with encryption
        // mmkv = MMKV(dir.absolutePath, "88C51C536176AD8A8EE4A06F62EE897E")
    }
}

class MainActivity : AppCompatActivity() {

    private val mmkv: MMKV
        get() = MyApplication.mmkv

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        mmkv.putString("first_key", "first value")
        mmkv.putInt("second_key", 1024)
        mmkv.putBool("third_key", true)
        binding.string.text = mmkv.getString("first_key", "default")
        binding.integer.text = mmkv.getInt("second_key", 0).toString()
        binding.bool.text = mmkv.getBool("third_key", false).toString()
    }
}
```

Check the [android](https://github.com/yangkx1024/MMKV/tree/main/android) demo for more detail.

## Use in iOS project

1. Add this repo as swift package dependency to your Xcode project.

2. Init MMKV instance before use the API, for example:

   ```swift
   import Foundation
   import MMKV

   class MMKVManager {
       static var inst = initMMKV()
   }

   func initMMKV() -> MMKV {
       let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
       let documentsDirectory = paths[0]
       let docURL = URL(string: documentsDirectory)!
       let dataPath = docURL.appendingPathComponent("mmkv")
       if !FileManager.default.fileExists(atPath: dataPath.path) {
           do {
               try FileManager.default.createDirectory(atPath: dataPath.path, withIntermediateDirectories: true, attributes: nil)
           } catch {
               print(error.localizedDescription)
           }
       }
       return MMKV(dataPath.path)
   }
   ```

3. Use `MMKV.shared` to access API directly:

    ```swift
    import SwiftUI
    import MMKV

    struct ContentView: View {
        @State var textContent: String = "Hello, world!"
        var body: some View {
            Text(textContent)
                .onTapGesture {
                    let value = MMKVManager.inst.getInt32(key: "int_key").unwrap(defalutValue: 0)
                    MMKVManager.inst.putInt32(key: "int_key", value: value + 1).unwrap(defalutValue: ())
                    textContent = MMKVManager.inst.getInt32(key: "int_key").unwrap(defalutValue: 0).formatted()
                }
        }
    }
    ```

Check the [ios](https://github.com/yangkx1024/MMKV/tree/main/ios) demo for more detail.
