implemented snap compression
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing

This commit is contained in:
2019-09-06 15:22:58 +02:00
parent 22dc00e3bf
commit bc86883044
4 changed files with 628 additions and 19 deletions

View File

@@ -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"))))