Get unixfs demo working.

This commit is contained in:
David Craven 2019-03-03 20:22:10 +01:00
parent d185b83b6c
commit 3d89305fa3
No known key found for this signature in database
GPG Key ID: DF438712EA50DBB1
7 changed files with 79 additions and 8 deletions

1
examples/block.data Normal file
View File

@ -0,0 +1 @@
Here is some data

View File

@ -1,5 +1,6 @@
#![feature(async_await, await_macro, futures_api)]
use ipfs::{Block, Ipfs, IpfsOptions, TestTypes};
use std::convert::TryInto;
fn main() {
let options = IpfsOptions::<TestTypes>::default();
@ -17,7 +18,16 @@ fn main() {
// Retrive a Block
let block = await!(ipfs.get_block(Block::from("block-want\n").cid())).unwrap();
let string: String = block.into();
println!("block: {:?}", string);
let contents: String = block.into();
println!("block contents: {:?}", contents);
// Add a file
await!(ipfs.add("./examples/block.data".into())).unwrap();
// Get a file
let path = "/QmSy5pnHk1EnvE5dmJSyFKG5unXLGjPpBuJJCBQkBTvBaW".try_into().unwrap();
let file = await!(ipfs.get(path)).unwrap();
let contents: String = file.into();
println!("file contents: {:?}", contents);
});
}

View File

@ -5,6 +5,7 @@ use crate::repo::{Repo, RepoTypes};
use cid::Codec;
use core::future::Future;
#[derive(Clone)]
pub struct IpldDag<Types: RepoTypes> {
repo: Repo<Types>,
}

View File

@ -24,13 +24,13 @@ pub(crate) fn encode(data: Ipld) -> Result<Vec<u8>, Error> {
Ok(pb_node.into_bytes())
}
struct PbLink {
pub(crate) struct PbLink {
pub cid: Cid,
pub name: String,
pub size: u64,
}
struct PbNode {
pub(crate) struct PbNode {
pub links: Vec<PbLink>,
pub data: Vec<u8>,
}

View File

@ -1,6 +1,7 @@
use crate::block::Cid;
use crate::error::Error;
use crate::ipld::IpldError;
use std::convert::TryFrom;
#[derive(Clone, Debug, PartialEq)]
pub struct IpldPath {
@ -18,6 +19,9 @@ impl IpldPath {
pub fn from(cid: Cid, string: &str) -> Result<Self, Error> {
let mut path = IpldPath::new(cid);
if string.is_empty() {
return Ok(path);
}
for sub_path in string.split("/") {
if sub_path == "" {
return Err(IpldError::InvalidPath(string.to_owned()).into());
@ -69,6 +73,14 @@ impl IpldPath {
}
}
impl TryFrom<&str> for IpldPath {
type Error = Error;
fn try_from(string: &str) -> Result<Self, Self::Error> {
IpldPath::from_str(string)
}
}
impl From<Cid> for IpldPath {
fn from(cid: Cid) -> Self {
IpldPath::new(cid)
@ -157,7 +169,7 @@ mod tests {
#[test]
fn test_from_errors() {
let cid = Block::from("hello").cid().to_owned();
assert!(IpldPath::from(cid.clone(), "").is_err());
assert!(IpldPath::from(cid.clone(), "").is_ok());
assert!(IpldPath::from(cid.clone(), "/").is_err());
assert!(IpldPath::from(cid.clone(), "/abc").is_err());
assert!(IpldPath::from(cid.clone(), "abc/").is_err());

View File

@ -34,6 +34,7 @@ pub use self::p2p::SwarmTypes;
use self::p2p::{create_swarm, SwarmOptions, TSwarm};
pub use self::repo::RepoTypes;
use self::repo::{create_repo, RepoOptions, Repo, RepoEvent};
use self::unixfs::File;
static IPFS_LOG: &str = "info";
static IPFS_PATH: &str = ".rust-ipfs";
@ -180,6 +181,21 @@ impl<Types: IpfsTypes> Ipfs<Types> {
self.dag.get(path)
}
/// Adds a file into the ipfs repo.
pub fn add(&self, path: PathBuf) -> impl Future<Output=Result<Cid, Error>> {
let dag = self.dag.clone();
async move {
let file = await!(File::new(path))?;
let cid = await!(file.put_unixfs_v1(&dag))?;
Ok(cid)
}
}
/// Gets a file from the ipfs repo.
pub fn get(&self, path: IpldPath) -> impl Future<Output=Result<File, Error>> {
File::get_unixfs_v1(&self.dag, path)
}
/// Start daemon.
pub fn start_daemon(&mut self) -> IpfsFuture<Types> {
IpfsFuture {

View File

@ -1,15 +1,40 @@
use crate::block::Cid;
use crate::error::Error;
use crate::ipld::{Ipld, IpldDag};
use crate::ipld::{Ipld, IpldDag, IpldPath, formats::pb::PbNode};
use crate::repo::RepoTypes;
use core::future::Future;
use futures::compat::*;
use std::collections::HashMap;
use std::convert::TryInto;
use std::path::PathBuf;
pub struct File {
data: Vec<u8>,
}
impl File {
pub fn new(path: PathBuf) -> impl Future<Output=Result<Self, Error>> {
async move {
let file = await!(tokio::fs::File::open(path).compat())?;
let (_, data) = await!(tokio::io::read_to_end(file, Vec::new()).compat())?;
Ok(File {
data
})
}
}
pub fn get_unixfs_v1<T: RepoTypes>(dag: &IpldDag<T>, path: IpldPath) ->
impl Future<Output=Result<Self, Error>> {
let future = dag.get(path);
async move {
let ipld = await!(future)?;
let pb_node: PbNode = ipld.try_into()?;
Ok(File {
data: pb_node.data,
})
}
}
pub fn put_unixfs_v1<T: RepoTypes>(&self, dag: &IpldDag<T>) ->
impl Future<Output=Result<Cid, Error>>
{
@ -38,6 +63,12 @@ impl From<&str> for File {
}
}
impl Into<String> for File {
fn into(self) -> String {
String::from_utf8_lossy(&self.data).to_string()
}
}
#[cfg(test)]
mod tests {
use super::*;
@ -47,12 +78,12 @@ mod tests {
fn test_file_cid() {
let repo = create_mock_repo();
let dag = IpldDag::new(repo);
let file = File::from("Here is some data\n");
let file = File::from("\u{8}\u{2}\u{12}\u{12}Here is some data\n\u{18}\u{12}");
let cid = Cid::from("QmSy5pnHk1EnvE5dmJSyFKG5unXLGjPpBuJJCBQkBTvBaW").unwrap();
tokio::run_async(async move {
let cid2 = await!(file.put_unixfs_v1(&dag)).unwrap();
assert_eq!(cid, cid2);
assert_eq!(cid.to_string(), cid2.to_string());
});
}
}