Browse Source

Add object reader & writer.

deprecated_bsvfs
Draklaw 5 years ago
parent
commit
82a9ddb603
  1. 61
      Cargo.lock
  2. 23
      bsv/src_bak/core/error.rs
  3. 5
      bsv/src_bak/core/mod.rs
  4. 21
      bsv/src_bak/core/object.rs
  5. 17
      bsv/src_bak/core/object_db.rs
  6. 16
      bsv/src_bak/core/object_type.rs
  7. 7
      bsv/src_bak/main.rs
  8. 3
      libbsv/Cargo.toml
  9. 5
      libbsv/src/core/error.rs
  10. 10
      libbsv/src/core/object_id.rs
  11. 61
      libbsv/src/simple_db/mod.rs
  12. 161
      libbsv/src/simple_db/object.rs
  13. 76
      libbsv/src/simple_db/simple_db.rs

61
Cargo.lock

@ -61,6 +61,15 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "block-buffer"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
dependencies = [
"generic-array",
]
[[package]] [[package]]
name = "bsv" name = "bsv"
version = "0.1.0" version = "0.1.0"
@ -92,6 +101,21 @@ dependencies = [
"vec_map", "vec_map",
] ]
[[package]]
name = "cpuid-bool"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634"
[[package]]
name = "digest"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
dependencies = [
"generic-array",
]
[[package]] [[package]]
name = "error-chain" name = "error-chain"
version = "0.12.4" version = "0.12.4"
@ -102,6 +126,16 @@ dependencies = [
"version_check", "version_check",
] ]
[[package]]
name = "generic-array"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817"
dependencies = [
"typenum",
"version_check",
]
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.1.15" version = "0.1.15"
@ -143,8 +177,10 @@ dependencies = [
name = "libbsv" name = "libbsv"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"digest",
"error-chain", "error-chain",
"serde", "serde",
"sha2",
"tempfile", "tempfile",
"toml", "toml",
"uuid", "uuid",
@ -178,6 +214,12 @@ version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ab52be62400ca80aa00285d25253d7f7c437b7375c4de678f5405d3afe82ca5" checksum = "1ab52be62400ca80aa00285d25253d7f7c437b7375c4de678f5405d3afe82ca5"
[[package]]
name = "opaque-debug"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]] [[package]]
name = "ppv-lite86" name = "ppv-lite86"
version = "0.2.9" version = "0.2.9"
@ -284,6 +326,19 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "sha2"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2933378ddfeda7ea26f48c555bdad8bb446bf8a3d17832dc83e380d444cfb8c1"
dependencies = [
"block-buffer",
"cfg-if",
"cpuid-bool",
"digest",
"opaque-debug",
]
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.8.0" version = "0.8.0"
@ -333,6 +388,12 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "typenum"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
[[package]] [[package]]
name = "unicode-width" name = "unicode-width"
version = "0.1.8" version = "0.1.8"

23
bsv/src_bak/core/error.rs

@ -0,0 +1,23 @@
use std::result;
#[derive(Debug, PartialEq, Eq)]
pub enum Error {
InvalidObjectIdSize,
InvalidObjectIdCharacter,
}
impl Error {
fn message(&self) -> String {
match self {
Error::InvalidObjectIdSize =>
"invalid size for object id string".to_string(),
Error::InvalidObjectIdCharacter =>
"invalid character in object id string".to_string(),
}
}
}
pub type Result<T> = result::Result<T, Error>;

5
bsv/src_bak/core/mod.rs

@ -0,0 +1,5 @@
pub mod error;
pub mod object_id;
pub mod object_type;
pub mod object;
pub mod object_db;

21
bsv/src_bak/core/object.rs

@ -0,0 +1,21 @@
use super::object_id::ObjectId;
use super::object_type::ObjectType;
/// An object in an ObjectDb.
///
/// An Objects is fundamentaly an arbitrary blob of data. It has a unique identifier, a size and
/// a type.
#[derive(Debug)]
pub struct Object {
pub id: ObjectId,
pub otype: ObjectType,
pub size: usize,
}
impl Object {
fn new(object_id: ObjectId, otype: ObjectType, size: usize) -> Object {
Object { id: object_id, otype, size }
}
}

17
bsv/src_bak/core/object_db.rs

@ -0,0 +1,17 @@
use std::io;
use super::error::Result;
use super::object_id::ObjectId;
use super::object_type::ObjectType;
use super::object::Object;
pub trait ObjectDb {
fn object_exists(&self, oid: &ObjectId) -> Result<bool>;
fn get_object(&self, oid: &ObjectId) -> Result<Option<Object>>;
fn open_object(&self, oid: &ObjectId) -> Result<Box<dyn io::Read>>;
fn compute_object_id(&self, otype: ObjectType, reader: &dyn io::Read) -> Result<ObjectId>;
fn add_object(&mut self, otype: ObjectType, reader: &dyn io::Read) -> Result<Object>;
fn delete_object(&mut self, oid: &ObjectId) -> Result<()>;
}

16
bsv/src_bak/core/object_type.rs

@ -0,0 +1,16 @@
/// Describe the type of an Object.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ObjectType {
name: String,
}
impl ObjectType {
fn new(name: &str) -> ObjectType {
ObjectType {
name: name.to_string(),
}
}
}

7
bsv/src_bak/main.rs

@ -0,0 +1,7 @@
mod core;
mod object_db;
fn main() {
println!("Hello, world!");
}

3
libbsv/Cargo.toml

@ -11,3 +11,6 @@ serde = "1.0.106"
toml = "0.5.6" toml = "0.5.6"
uuid = { version = "0.8.1", features = ["serde", "v4"] } uuid = { version = "0.8.1", features = ["serde", "v4"] }
tempfile = "3.1.0" tempfile = "3.1.0"
digest = "0.9.0"
sha2 = "0.9.1"
flate2 = "1.0.17"

5
libbsv/src/core/error.rs

@ -42,5 +42,10 @@ error_chain! {
description("Object id contains invalid character") description("Object id contains invalid character")
display("Object id contains invalid character") display("Object id contains invalid character")
} }
InvalidObjectType(otype: [u8; 4]) {
description("Object has an invalid object type")
display("Object has an invalid object type {:?}", otype)
}
} }
} }

10
libbsv/src/core/object_id.rs

@ -30,9 +30,9 @@ pub struct ObjectId {
impl ObjectId { impl ObjectId {
pub fn new(id: Vec<u8>) -> ObjectId { pub fn new(id: &[u8]) -> ObjectId {
ObjectId { ObjectId {
id id: id.into(),
} }
} }
@ -82,7 +82,7 @@ mod tests {
#[test] #[test]
fn object_id_display() { fn object_id_display() {
let obj = ObjectId::new(vec![ let obj = ObjectId::new(&[
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
]); ]);
@ -91,7 +91,7 @@ mod tests {
#[test] #[test]
fn object_id_debug() { fn object_id_debug() {
let obj = ObjectId::new(vec![ let obj = ObjectId::new(&[
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
]); ]);
@ -101,7 +101,7 @@ mod tests {
#[test] #[test]
fn str_to_object_id() { fn str_to_object_id() {
let obj = ObjectId::from_str("0001020304050607").unwrap(); let obj = ObjectId::from_str("0001020304050607").unwrap();
let obj_ref = ObjectId::new(vec![ let obj_ref = ObjectId::new(&[
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
]); ]);

61
libbsv/src/simple_db/mod.rs

@ -14,63 +14,8 @@
// along with cdb. If not, see <https://www.gnu.org/licenses/>. // along with cdb. If not, see <https://www.gnu.org/licenses/>.
use std::path::{Path, PathBuf}; pub mod simple_db;
pub mod object;
use crate::core::error::*;
use crate::core::object_id::ObjectId;
pub use simple_db::SimpleDb;
const OBJECTS_FOLDER: &str = "objects";
#[derive(Debug)]
pub struct SimpleDb {
path: PathBuf,
}
impl SimpleDb {
pub fn new(path: &Path) -> Result<SimpleDb> {
Ok(SimpleDb {
path: path.into(),
})
}
pub fn has_object(&self, oid: &ObjectId) -> bool {
let obj_path = self.path_from_id(oid);
if let Ok(metadata) = std::fs::metadata(obj_path) {
metadata.is_file()
}
else {
false
}
}
fn path_from_id(&self, oid: &ObjectId) -> PathBuf {
let oid_str = oid.to_string();
let mut path = self.path.clone();
path.push(OBJECTS_FOLDER);
path.push(oid_str.get(..4).unwrap()); // unwrap is ok here because we know oid_str is a
path.push(oid_str.get(4..).unwrap()); // hexadecimal number (i.e. ascii only).
path
}
}
#[cfg(test)]
mod tests {
use super::ObjectId;
use super::SimpleDb;
#[test]
fn simple_db_path_from_id() {
let db = SimpleDb::new(std::path::Path::new(".bsv")).unwrap();
let oid = ObjectId::from_str("0001020304050607").unwrap();
let path = db.path_from_id(&oid);
assert_eq!(path, std::path::PathBuf::from(".bsv/objects/0001/020304050607"));
}
}

161
libbsv/src/simple_db/object.rs

@ -0,0 +1,161 @@
// 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/>.
extern crate digest;
extern crate sha2;
extern crate flate2;
use std::io::{Read, Write, copy};
use digest::Digest;
use crate::core::error::*;
use crate::core::ObjectId;
type ObjectType = [u8; 4];
pub const TYPE_BLOB: &ObjectType = b"blob";
pub const TYPE_TREE: &ObjectType = b"tree";
pub struct ObjectWriter<'a, W: Write, D: Digest> {
writer: &'a mut W,
digest: D,
}
impl<'a, W: Write, D: Digest> ObjectWriter<'a, W, D> {
pub fn new(writer: &'a mut W, otype: &ObjectType, size: u64)
-> Result<ObjectWriter<'a, W, D>> {
let mut digest = D::new();
digest.update(otype);
digest.update(&size.to_be_bytes());
writer.write_all(otype)?;
writer.write_all(&size.to_be_bytes())?;
Ok(ObjectWriter {
writer,
digest,
})
}
pub fn close(self) -> Result<ObjectId> {
Ok(ObjectId::new(&self.digest.finalize()))
}
}
impl<'a, W: Write, D: Digest> Write for ObjectWriter<'a, W, D> {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
let size = self.writer.write(buf)?;
self.digest.update(&buf[..size]);
Ok(size)
}
fn flush(&mut self) -> std::io::Result<()> {
self.writer.flush()
}
}
pub fn write_object<'a, R, W>(reader: &mut R, writer: &'a mut W,
otype: &ObjectType, size: u64)
-> Result<ObjectId> where
R: Read,
W: Write {
let mut owriter: ObjectWriter<W, sha2::Sha224>
= ObjectWriter::new(writer, otype, size)?;
copy(reader, &mut owriter)?;
owriter.close()
}
pub struct ObjectReader<R: Read> {
reader: R,
}
impl<R: Read> ObjectReader<R> {
pub fn new(mut reader: R)
-> Result<(ObjectType, u64, ObjectReader<R>)> {
let mut buffer = [0u8; 12];
reader.read_exact(&mut buffer)?;
let otype = {
let mut otype = [0; 4];
otype.copy_from_slice(&buffer[0..4]);
otype
};
let size = {
let mut size_bytes = [0; 8];
size_bytes.copy_from_slice(&buffer[4..12]);
u64::from_be_bytes(size_bytes)
};
Ok((
otype,
size,
ObjectReader {
reader,
}
))
}
pub fn close(self) -> Result<()> {
Ok(())
}
}
impl<R: Read> Read for ObjectReader<R> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
self.reader.read(buf)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn object_read_write() {
use std::io::{Cursor, Seek, SeekFrom};
let payload = b"Hello World!";
let mut source = Cursor::new(payload);
let mut fake_file = Cursor::new(vec![]);
let mut output = vec![];
write_object(&mut source, &mut fake_file, TYPE_BLOB, payload.len() as u64).unwrap();
fake_file.seek(SeekFrom::Start(0)).unwrap();
let (otype, size, mut reader) = ObjectReader::new(fake_file).unwrap();
let read_size = reader.read_to_end(&mut output).unwrap();
assert_eq!(otype, *TYPE_BLOB);
assert_eq!(size, payload.len() as u64);
assert_eq!(read_size, payload.len());
assert_eq!(output, payload);
}
}

76
libbsv/src/simple_db/simple_db.rs

@ -0,0 +1,76 @@
// 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::{Path, PathBuf};
use crate::core::error::*;
use crate::core::ObjectId;
const OBJECTS_FOLDER: &str = "objects";
#[derive(Debug)]
pub struct SimpleDb {
path: PathBuf,
}
impl SimpleDb {
pub fn new(path: &Path) -> Result<SimpleDb> {
Ok(SimpleDb {
path: path.into(),
})
}
pub fn has_object(&self, oid: &ObjectId) -> bool {
let obj_path = self.path_from_id(oid);
if let Ok(metadata) = std::fs::metadata(obj_path) {
metadata.is_file()
}
else {
false
}
}
fn path_from_id(&self, oid: &ObjectId) -> PathBuf {
let oid_str = oid.to_string();
let mut path = self.path.clone();
path.push(OBJECTS_FOLDER);
path.push(oid_str.get(..4).unwrap()); // unwrap is ok here because we know oid_str is a
path.push(oid_str.get(4..).unwrap()); // hexadecimal number (i.e. ascii only).
path
}
}
#[cfg(test)]
mod tests {
use super::ObjectId;
use super::SimpleDb;
#[test]
fn simple_db_path_from_id() {
let db = SimpleDb::new(std::path::Path::new(".bsv")).unwrap();
let oid = ObjectId::from_str("0001020304050607").unwrap();
let path = db.path_from_id(&oid);
assert_eq!(path, std::path::PathBuf::from(".bsv/objects/0001/020304050607"));
}
}
Loading…
Cancel
Save