implemented snap compression
This commit is contained in:
82
src/main.rs
82
src/main.rs
@@ -3,10 +3,11 @@ extern crate iron;
|
||||
extern crate rand;
|
||||
extern crate snap;
|
||||
|
||||
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
|
||||
use chrono::*;
|
||||
use iron::method::Method;
|
||||
use iron::prelude::*;
|
||||
use iron::modifiers::Redirect;
|
||||
use iron::prelude::*;
|
||||
use iron::url::Url;
|
||||
use rand::Rng;
|
||||
use std::fs;
|
||||
@@ -23,7 +24,7 @@ struct Snippet<'a> {
|
||||
|
||||
#[allow(dead_code)]
|
||||
struct SnippetMeta {
|
||||
created: DateTime<UTC>,
|
||||
created: DateTime<Utc>,
|
||||
compression: Option<String>,
|
||||
}
|
||||
|
||||
@@ -53,20 +54,60 @@ impl<'a> Snippet<'a> {
|
||||
self.storage.directory.join(&self.id)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn metadata(&self) -> Result<SnippetMeta, io::Error> {
|
||||
unimplemented!();
|
||||
pub fn metadata(&self) -> Result<SnippetMeta, io::Error> {
|
||||
let mut file = File::open(self.path())?;
|
||||
self.metadata_via_handle(&mut file)
|
||||
}
|
||||
|
||||
fn metadata_via_handle(&self, hdl: &mut impl Read) -> Result<SnippetMeta, io::Error> {
|
||||
let timestamp = hdl.read_i64::<BigEndian>()?;
|
||||
let comp_len = hdl.read_u16::<BigEndian>()? as usize;
|
||||
let mut comp = Vec::with_capacity(comp_len);
|
||||
comp.resize(comp_len, 0u8);
|
||||
hdl.read_exact(&mut comp)?;
|
||||
let comp = String::from_utf8(comp).unwrap();
|
||||
Ok(SnippetMeta {
|
||||
created: Utc.timestamp_millis(timestamp),
|
||||
compression: Some(comp).filter(|_| comp_len > 0),
|
||||
})
|
||||
}
|
||||
|
||||
fn contents(&self) -> Result<String, io::Error> {
|
||||
let mut file = File::open(self.path())?;
|
||||
let mut text = String::new();
|
||||
file.read_to_string(&mut text)?;
|
||||
Ok(text)
|
||||
let meta = self.metadata_via_handle(&mut file)?;
|
||||
fn read_string(r: &mut impl Read) -> Result<String, io::Error> {
|
||||
let mut text = String::new();
|
||||
r.read_to_string(&mut text)?;
|
||||
Ok(text)
|
||||
}
|
||||
dbg!((&meta.compression, &meta.created));
|
||||
match meta.compression {
|
||||
Some(ref comp) if comp == "snap" => {
|
||||
let mut r = snap::Reader::new(&mut file);
|
||||
read_string(&mut r)
|
||||
}
|
||||
_ => read_string(&mut file),
|
||||
}
|
||||
}
|
||||
|
||||
fn write(self, content: &str) -> Result<Snippet<'a>, io::Error> {
|
||||
fs::write(self.path(), content).map(|_| self)
|
||||
let mut file = File::create(self.path())?;
|
||||
file.write_i64::<BigEndian>(Utc::now().timestamp())?;
|
||||
let comp = if content.len() > 2048 {
|
||||
Some("snap")
|
||||
} else {
|
||||
None
|
||||
};
|
||||
file.write_u16::<BigEndian>(comp.map(|s| s.len() as u16).unwrap_or(0u16))?;
|
||||
file.write(comp.map(|s| s.as_bytes()).unwrap_or(&[0u8; 0]))?;
|
||||
match comp {
|
||||
Some(ref comp) if comp == &"snap" => {
|
||||
let mut w = snap::Writer::new(&mut file);
|
||||
w.write_all(content.as_bytes())?
|
||||
}
|
||||
_ => file.write_all(content.as_bytes())?,
|
||||
};
|
||||
Ok(Snippet::new(&self.id, self.storage))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,21 +153,23 @@ fn handle(req: &mut Request) -> IronResult<Response> {
|
||||
Vec<u8>,
|
||||
io::Error,
|
||||
>>(
|
||||
)).map_err(|err| IronError::new(err, ""))?;
|
||||
))
|
||||
.map_err(|err| IronError::new(err, ""))?;
|
||||
String::from_utf8(bytes)
|
||||
.map_err(|err| IronError::new(err, "Invalid utf8"))?
|
||||
};
|
||||
Snippet::random(&storage)
|
||||
.write(&*text)
|
||||
.map_err(|err| IronError::new(err, "Failed to save snippet"))
|
||||
Snippet::random(&storage).write(&*text).map_err(|err| {
|
||||
let msg = format!("Failed to save snippet: {:?}", &err);
|
||||
IronError::new(err, msg)
|
||||
})
|
||||
};
|
||||
snip.map(|snip| {
|
||||
let mut snip_url: Url = req.url.clone().into();
|
||||
snip_url.set_path(&*("/".to_string() + &*snip.id));
|
||||
Response::with((
|
||||
iron::status::TemporaryRedirect,
|
||||
Redirect(iron::Url::from_generic_url(snip_url).unwrap())),
|
||||
)
|
||||
Redirect(iron::Url::from_generic_url(snip_url).unwrap()),
|
||||
))
|
||||
/*Response::with((
|
||||
iron::status::Ok,
|
||||
format!(
|
||||
@@ -145,8 +188,13 @@ fn handle(req: &mut Request) -> IronResult<Response> {
|
||||
(Method::Get, Some(id)) => {
|
||||
let att = storage.open(&id).map(|snip| snip.contents()).map(|res| {
|
||||
Response::with(
|
||||
res.map(|text| (iron::status::Ok, text))
|
||||
.unwrap_or((iron::status::InternalServerError, "..".to_string())),
|
||||
match res.map(|text| (iron::status::Ok, text)).map_err(|err| {
|
||||
let msg = format!("Failed to load snippet: {:?}", &err);
|
||||
msg
|
||||
}) {
|
||||
Ok(res) => res,
|
||||
Err(e) => (iron::status::InternalServerError, e),
|
||||
},
|
||||
)
|
||||
});
|
||||
Ok(att.unwrap_or(Response::with((iron::status::NotFound, "Not here sry"))))
|
||||
|
Reference in New Issue
Block a user