// This file is part of bsv. // // bsv is free software: you can redistribute it and/or modify it under the // terms of the GNU Affero General Public License as published by the Free // Software Foundation, either version 3 of the License, or (at your option) // any later version. // // bsv is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for // more details. // // You should have received a copy of the Affero GNU General Public License // along with bsv. If not, see . use camino::{Utf8PathBuf}; use cas_core::{ err, Error, ObjectId, Result, Writer, }; use crate::utils::{obj_path, tmp_dir}; pub struct WFile { file: tempfile::NamedTempFile, db_path: Utf8PathBuf, } impl WFile { pub fn new(db_path: Utf8PathBuf) -> Result { let file = tempfile::NamedTempFile::new_in(tmp_dir(&db_path)).or_else(|err| err!("failed to create_file: {}", err))?; Ok(WFile { file, db_path, }) } } impl std::io::Write for WFile { fn write(&mut self, buf: &[u8]) -> std::io::Result { self.file.write(buf) } fn flush(&mut self) -> std::io::Result<()> { self.file.flush() } } impl Writer for WFile { fn finalize(self: Box) -> Result { err!("reader pipline has no digest step") } fn _finalize(self: Box, oid: ObjectId) -> Result { let path = obj_path(&self.db_path, &oid); std::fs::create_dir_all( path.parent().expect("cannot access to object parent directory") ).or_else(|err| err!("failed to create object dir: {}", err))?; self.file.persist(path).or_else(|err| err!("failed to persist file: {}", err))?; Ok(oid) } } #[cfg(test)] mod tests { use std::str::FromStr; use crate::utils::{obj_dir, obj_path}; use super::*; #[test] fn test_wfile() { use std::io::{Read, Write}; let data = b"Hello World!"; let oid = ObjectId::from_str( "7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069" ).expect("invalid object id"); let dir = tempfile::TempDir::new() .expect("failed to create tmp dir"); std::fs::create_dir(tmp_dir(dir.path().try_into().unwrap())).expect("failed to create db/obj dir"); std::fs::create_dir(obj_dir(dir.path().try_into().unwrap())).expect("failed to create db/tmp dir"); { let mut writer = Box::new(WFile::new(dir.path().to_path_buf().try_into().unwrap()).expect("failed to create WFile")); writer.write(data).expect("failed to write to WFile"); let oid2 = writer._finalize(oid.clone()).expect("failed to finalize WFile"); assert_eq!(oid2, oid); } let mut file = std::fs::File::open(obj_path(dir.path().try_into().unwrap(), &oid)).expect("failed to open object file"); let mut buf = Vec::new(); file.read_to_end(&mut buf).expect("failed to read object file"); assert_eq!(buf, data); } }