c2pa-rs

A fork of https://github.com/contentauth/c2pa-rs/
git clone git://archive.git.mtrnord.blog/mtrnords-photography-manager/c2pa-rs.git
Log | Files | Refs | README

patch.rs (2980B)


      1 // Copyright 2022 Adobe. All rights reserved.
      2 // This file is licensed to you under the Apache License,
      3 // Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
      4 // or the MIT license (http://opensource.org/licenses/MIT),
      5 // at your option.
      6 
      7 // Unless required by applicable law or agreed to in writing,
      8 // this software is distributed on an "AS IS" BASIS, WITHOUT
      9 // WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or
     10 // implied. See the LICENSE-MIT and LICENSE-APACHE files for the
     11 // specific language governing permissions and limitations under
     12 // each license.
     13 
     14 use memchr::memmem;
     15 
     16 use crate::error::{Error, Result};
     17 
     18 /**
     19 Patch a sequence bytes with a new set of bytes - the search_bytes are erased and replaced with replace_bytes
     20 This function only patches the first occurrence
     21 returns the location where splice occurred
     22 */
     23 pub fn patch_bytes(data: &mut Vec<u8>, search_bytes: &[u8], replace_bytes: &[u8]) -> Result<usize> {
     24     // patch data bytes in memory
     25 
     26     if let Some(splice_start) = memmem::find(data, search_bytes) {
     27         data.splice(
     28             splice_start..splice_start + search_bytes.len(),
     29             replace_bytes.iter().cloned(),
     30         );
     31         Ok(splice_start)
     32     } else {
     33         Err(Error::NotFound)
     34     }
     35 }
     36 
     37 /**
     38 Patch new content into a file
     39 path - path to file to be patched
     40 search_bytes - bytes to be replaced
     41 replace_bytes - replacement bytes
     42 returns the location where splice occurred
     43 */
     44 #[cfg(all(test, feature = "file_io"))]
     45 pub fn patch_file(
     46     path: &std::path::Path,
     47     search_bytes: &[u8],
     48     replace_bytes: &[u8],
     49 ) -> Result<usize> {
     50     let mut buf = std::fs::read(path).map_err(Error::IoError)?;
     51 
     52     let splice_point = patch_bytes(&mut buf, search_bytes, replace_bytes)?;
     53 
     54     std::fs::write(path, &buf).map_err(Error::IoError)?;
     55 
     56     Ok(splice_point)
     57 }
     58 
     59 #[cfg(test)]
     60 pub mod tests {
     61     #![allow(clippy::unwrap_used)]
     62 
     63     use super::*;
     64 
     65     #[test]
     66     fn test_patch() {
     67         let source = "Hello everyone this is a test".as_bytes();
     68         let mut source_vec = source.to_vec();
     69         let search_bytes = "everyone".as_bytes();
     70         let replace_bytes = "world".as_bytes();
     71         let replace_bytes2 = "universe".as_bytes();
     72         let test_bytes = "test".as_bytes();
     73         let unit_test_bytes = "unit test".as_bytes();
     74 
     75         println!("Original string: {}", String::from_utf8_lossy(&source_vec));
     76 
     77         patch_bytes(&mut source_vec, search_bytes, replace_bytes).unwrap();
     78 
     79         println!(
     80             "Replaced string: {}\n",
     81             String::from_utf8_lossy(&source_vec)
     82         );
     83 
     84         patch_bytes(&mut source_vec, replace_bytes, replace_bytes2).unwrap();
     85 
     86         println!(
     87             "Re-Replaced string: {}\n",
     88             String::from_utf8_lossy(&source_vec)
     89         );
     90 
     91         patch_bytes(&mut source_vec, test_bytes, unit_test_bytes).unwrap();
     92 
     93         println!(
     94             "Pad end of data string: {}\n",
     95             String::from_utf8_lossy(&source_vec)
     96         );
     97     }
     98 }