use std::path::Path;
use anyhow::Result;
use crate::nss_io::file_system;
use crate::struct_set::Hashable;
#[derive(Debug, Clone, PartialEq)]
pub struct Blob {
pub content: Vec<u8>,
}
impl Blob {
pub fn new<P: AsRef<Path>>(path: P) -> Result<Self> {
let content = file_system::read_contet_with_bytes(path.as_ref())?;
Ok(Self { content })
}
pub fn from_rawobject(contnet: &[u8]) -> Result<Self> {
Ok(Self {
content: contnet.to_vec(),
})
}
}
impl std::fmt::Display for Blob {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", String::from_utf8(self.content.clone()).unwrap())
}
}
impl Hashable for Blob {
fn as_bytes(&self) -> Vec<u8> {
let header = format!("blob {}\0", self.content.len());
let store = [header.as_bytes(), &self.content].concat();
store
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::env;
use std::fs;
use std::fs::File;
use std::io::prelude::*;
#[test]
fn test_blob_new() {
let temp_dir = env::temp_dir().join("nss_test_new_blob");
println!("Test Directory: {}", temp_dir.display());
fs::create_dir(&temp_dir).unwrap();
let file_path = temp_dir.join("test_file.txt");
let buffer = b"#[allow(dead_code)]
fn commit(message: &str) -> std::io::Result<()> {
let tree_hash = write_tree()?;
match commit_tree(&tree_hash, message)? {
Some(c) => update_ref(&c)?,
_ => println!(\"Nothing to commit\")
};
Ok(())
}";
let mut file = File::create(&file_path).unwrap();
file.write_all(buffer).unwrap();
let blob = Blob::new(&file_path);
assert!(blob.is_ok());
let blob = blob.unwrap();
assert_eq!(blob.content, buffer);
fs::remove_dir_all(temp_dir).unwrap();
}
#[test]
fn test_blob_from_rawobject() {
let content = b"#[allow(dead_code)]
fn commit(message: &str) -> std::io::Result<()> {
let tree_hash = write_tree()?;
match commit_tree(&tree_hash, message)? {
Some(c) => update_ref(&c)?,
_ => println!(\"Nothing to commit\")
};
Ok(())
}";
let blob = Blob::from_rawobject(content).unwrap();
assert_eq!(blob.content, content.to_vec());
}
#[test]
fn test_blob_as_bytes() {
let content = b"#[allow(dead_code)]
fn commit(message: &str) -> std::io::Result<()> {
let tree_hash = write_tree()?;
match commit_tree(&tree_hash, message)? {
Some(c) => update_ref(&c)?,
_ => println!(\"Nothing to commit\")
};
Ok(())
}";
let blob = Blob {
content: content.to_vec(),
};
let bytes = blob.as_bytes();
let expected_bytes = b"blob 250\0#[allow(dead_code)]
fn commit(message: &str) -> std::io::Result<()> {
let tree_hash = write_tree()?;
match commit_tree(&tree_hash, message)? {
Some(c) => update_ref(&c)?,
_ => println!(\"Nothing to commit\")
};
Ok(())
}";
assert_eq!(bytes, expected_bytes);
}
#[test]
fn test_blob_to_hash() {
let content = b"#[allow(dead_code)]
fn commit(message: &str) -> std::io::Result<()> {
let tree_hash = write_tree()?;
match commit_tree(&tree_hash, message)? {
Some(c) => update_ref(&c)?,
_ => println!(\"Nothing to commit\")
};
Ok(())
}";
let blob = Blob {
content: content.to_vec(),
};
assert_eq!(
blob.to_hash(),
hex::decode("5c73008ba75573c20d6a8a6e557d0556d4a84133".as_bytes()).unwrap()
);
}
#[test]
fn test_blob_display() {
let blob = Blob {
content: b"Hello, world!".to_vec(),
};
let display = format!("{}", blob.to_string());
assert_eq!(display, "Hello, world!");
}
#[test]
fn test_blob_debug() {
let blob = Blob {
content: b"hellow".to_vec(),
};
let debug = format!("{:?}", blob);
let test_debug = "Blob { content: [104, 101, 108, 108, 111, 119] }";
assert_eq!(debug, test_debug)
}
#[test]
fn test_blob_clone() {
let blob = Blob {
content: b"hellow".to_vec(),
};
assert_eq!(blob, blob.clone())
}
}