Mostly implement simple-cas.
This commit is contained in:
106
cas-simple/src/wfile.rs
Normal file
106
cas-simple/src/wfile.rs
Normal file
@@ -0,0 +1,106 @@
|
||||
// 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.
|
||||
//
|
||||
// cdb 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 cdb. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
use std::path::{PathBuf};
|
||||
|
||||
use cas_core::{
|
||||
Error, ObjectId, Result, Writer,
|
||||
};
|
||||
|
||||
use crate::utils::{obj_path, tmp_dir};
|
||||
|
||||
|
||||
pub struct WFile {
|
||||
file: tempfile::NamedTempFile,
|
||||
db_path: PathBuf,
|
||||
}
|
||||
|
||||
impl WFile {
|
||||
pub fn new(db_path: PathBuf) -> Result<Self> {
|
||||
let file = tempfile::NamedTempFile::new_in(tmp_dir(&db_path)).or_else(|err|
|
||||
Err(Error::error(format!("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<usize> {
|
||||
self.file.write(buf)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> std::io::Result<()> {
|
||||
self.file.flush()
|
||||
}
|
||||
}
|
||||
|
||||
impl Writer for WFile {
|
||||
fn finalize(self: Box<Self>) -> Result<ObjectId> {
|
||||
Err(Error::error("reader pipline has no digest step"))
|
||||
}
|
||||
|
||||
fn _finalize(self: Box<Self>, oid: ObjectId) -> Result<ObjectId> {
|
||||
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(Error::error(format!("failed to create object dir: {}", err))))?;
|
||||
self.file.persist(path).or_else(|err|
|
||||
Err(Error::error(format!("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())).expect("failed to create db/obj dir");
|
||||
std::fs::create_dir(obj_dir(dir.path())).expect("failed to create db/tmp dir");
|
||||
|
||||
{
|
||||
let mut writer = Box::new(WFile::new(dir.path().to_path_buf()).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(), &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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user