sqlite_compressions/
bsdiffraw.rs

1use std::io::Cursor;
2
3use rusqlite::Error::UserFunctionError;
4
5use crate::common_diff::{register_differ, Differ};
6use crate::rusqlite::{Connection, Result};
7
8/// Register the `bsdiffraw` and `bspatchraw` SQL functions with the given `SQLite` connection.
9/// The `bsdiffraw` function takes two arguments, and returns the [BSDiff delta](https://github.com/mendsley/bsdiff#readme) (blob) of the binary difference.
10/// The arguments can be either a string or a blob.
11/// If any of the arguments are `NULL`, the result is `NULL`.
12///
13/// # Example
14///
15/// ```
16/// # use sqlite_compressions::rusqlite::{Connection, Result};
17/// # use sqlite_compressions::register_bsdiffraw_functions;
18/// # fn main() -> Result<()> {
19/// let db = Connection::open_in_memory()?;
20/// register_bsdiffraw_functions(&db)?;
21/// let result: String = db.query_row("SELECT hex(bsdiffraw('abc013479zz', 'abc23456789zzf'))", [], |r| r.get(0))?;
22/// assert_eq!(result.as_str(), "03000000000000000B00000000000000070000000000000000000032333435363738397A7A66");
23/// let result: String = db.query_row("SELECT hex(bspatchraw('abc013479zz', bsdiffraw('abc013479zz', 'abc23456789zzf')))", [], |r| r.get(0))?;
24/// assert_eq!(result.as_str(), "61626332333435363738397A7A66");
25/// let result: Vec<u8> = db.query_row("SELECT bspatchraw('013479', bsdiffraw('013479', '23456789'))", [], |r| r.get(0))?;
26/// let expected = b"23456789";
27/// assert_eq!(result, expected);
28/// # Ok(())
29/// # }
30/// ```
31pub fn register_bsdiffraw_functions(conn: &Connection) -> Result<()> {
32    register_differ::<BsdiffRawDiffer>(conn)
33}
34
35pub struct BsdiffRawDiffer;
36
37impl Differ for BsdiffRawDiffer {
38    fn diff_name() -> &'static str {
39        "bsdiffraw"
40    }
41
42    fn patch_name() -> &'static str {
43        "bspatchraw"
44    }
45
46    fn diff(source: &[u8], target: &[u8]) -> Result<Vec<u8>> {
47        let mut patch = Vec::new();
48        bsdiff::diff(source, target, &mut patch).map_err(|e| UserFunctionError(e.into()))?;
49        Ok(patch)
50    }
51
52    fn patch(source: &[u8], patch: &[u8]) -> Result<Vec<u8>> {
53        let mut target = Vec::new();
54        bsdiff::patch(source, &mut Cursor::new(patch), &mut target)
55            .map_err(|e| UserFunctionError(e.into()))?;
56        Ok(target)
57    }
58}
59
60#[cfg(test)]
61mod tests {
62    use super::*;
63
64    #[test]
65    fn test_diff() {
66        let source = b"abc013479zz";
67        let target = b"abc23456789zzf";
68        let patch = BsdiffRawDiffer::diff(source, target).unwrap();
69        let expected = b"\x03\x00\x00\x00\x00\x00\x00\x00\x0B\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x32\x33\x34\x35\x36\x37\x38\x39\x7A\x7A\x66";
70        assert_eq!(patch, expected);
71    }
72
73    #[test]
74    fn test_patch() {
75        let source = b"abc013479zz";
76        let patch = b"\x03\x00\x00\x00\x00\x00\x00\x00\x0B\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x32\x33\x34\x35\x36\x37\x38\x39\x7A\x7A\x66";
77        let target = BsdiffRawDiffer::patch(source, patch).unwrap();
78        let expected = b"abc23456789zzf";
79        assert_eq!(target, expected);
80    }
81}