From 7606207e46991dc62e4e5e54763160ae4970701b Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Tue, 4 May 2021 21:28:43 +0100 Subject: [PATCH] bundles: Reorganise file to tidy it up Signed-off-by: Ian Jackson --- src/bundles.rs | 272 ++++++++++++++++++++++++++----------------------- 1 file changed, 144 insertions(+), 128 deletions(-) diff --git a/src/bundles.rs b/src/bundles.rs index 131e69a9..293e2c74 100644 --- a/src/bundles.rs +++ b/src/bundles.rs @@ -4,6 +4,8 @@ use crate::prelude::*; +//---------- public types ---------- + pub use crate::prelude::Sha512Trunc256 as Digester; pub type DigestWrite = crate::utils::DigestWrite; @@ -22,51 +24,27 @@ impl Kind { pub fn only() -> Self { Kind::Zip } } #[derive(Serialize,Deserialize)] #[serde(transparent)] pub struct Index(u16); -impl From for usize { - fn from(i: Index) -> usize { i.0.into() } -} -impl TryFrom for Index { - type Error = TryFromIntError; - #[throws(Self::Error)] - fn try_from(i: usize) -> Index { Index(i.try_into()?) } -} -impl Display for Index { - #[throws(fmt::Error)] - fn fmt(&self, f: &mut Formatter) { - write!(f, "{:05}", self.0)?; - } -} -impl FromStr for Index { - type Err = std::num::ParseIntError; - #[throws(Self::Err)] - fn from_str(s: &str) -> Index { Index(u16::from_str(s)?) } -} -hformat_as_display!{Id} - -const BUNDLES_MAX: Index = Index(64); #[derive(Copy,Clone,Debug,Hash,PartialEq,Eq,Ord,PartialOrd)] #[derive(Serialize,Deserialize)] pub struct Id { pub index: Index, pub kind: Kind, } -impl Authorisation { - pub fn bundles(self) -> Authorisation { self.therefore_ok() } -} - #[derive(Debug,Clone)] pub struct InstanceBundles { // todo: this vec is needed during loading only! bundles: Vec>, } +//---------- private definitions ---------- + +const BUNDLES_MAX: Index = Index(64); + #[derive(Debug,Clone,Serialize,Deserialize)] pub struct Note { pub kind: Kind, pub state: State, } -type BadBundle = String; // todo: make this a newtype - #[derive(Debug,Clone,Serialize,Deserialize)] pub enum State { Uploading, @@ -79,29 +57,13 @@ pub struct Loaded { meta: BundleMeta, } -impl Display for State { - #[throws(fmt::Error)] - fn fmt(&self, f: &mut Formatter) { - match self { - State::Loaded(Loaded{ meta }) => { - let BundleMeta { title } = meta; - write!(f, "Loaded {:?}", title)?; - } - other => write!(f, "{:?}", other)?, - } - } +pub struct Uploading { + instance: Arc, + id: Id, + file: DigestWrite>, } -pub fn b_dir(instance: &InstanceName) -> String { - savefilename(instance, "b-", "") -} -fn b_file(instance: &InstanceName, index: Index, suffix: S) -> String -where S: Display + Debug -{ - format!("{}/{}.{}", - savefilename(instance, "b-", ""), - index, suffix) -} +type BadBundle = String; // todo: make this a newtype #[derive(Error,Debug)] pub enum LoadError { @@ -111,34 +73,59 @@ pub enum LoadError { display_as_debug!{LoadError} use LoadError as LE; -impl From for LoadError { - fn from(ze: ZipError) -> LoadError { - LE::BadBundle(format!("bad zipfile: {}", ze)) +#[derive(Debug,Copy,Clone,Error)] +#[error("{0}")] +#[repr(transparent)] +pub struct NotBundle(&'static str); + +#[derive(Error,Debug)] +enum IncorporateError { + #[error("NotBundle({0})")] NotBundle(#[from] NotBundle), + #[error("{0}")] IE(#[from] IE), +} + +//---------- straightformward impls ---------- + +impl From for usize { + fn from(i: Index) -> usize { i.0.into() } +} +impl TryFrom for Index { + type Error = TryFromIntError; + #[throws(Self::Error)] + fn try_from(i: usize) -> Index { Index(i.try_into()?) } +} +impl Display for Index { + #[throws(fmt::Error)] + fn fmt(&self, f: &mut Formatter) { + write!(f, "{:05}", self.0)?; } } +impl FromStr for Index { + type Err = std::num::ParseIntError; + #[throws(Self::Err)] + fn from_str(s: &str) -> Index { Index(u16::from_str(s)?) } +} +hformat_as_display!{Id} -#[ext(pub)] -impl ZipArchive where R: Read + io::Seek { - #[throws(LoadError)] - fn by_name_caseless<'a>(&'a mut self, name: &str) -> ZipFile<'a> - { - fn search<'a,R>(za: &'a mut ZipArchive, name: &str) - -> Result - where R: Read + io::Seek - { - for i in 0..za.len() { - let m = za.by_index(i); - if matches!(m, Err(ZipError::FileNotFound)) { continue } - let m = m?; - if m.name_raw().eq_ignore_ascii_case(name.as_bytes()) { return Ok(i) } - } - return Err(LE::BadBundle(format!("bundle missing {}", name))); - } - let i = search(self, name)?; - self.by_index(i)? +impl From<&'static str> for NotBundle { + fn from(s: &'static str) -> NotBundle { + unsafe { mem::transmute(s) } } } +//---------- pathname handling (including Id leafname) ---------- + +pub fn b_dir(instance: &InstanceName) -> String { + savefilename(instance, "b-", "") +} +fn b_file(instance: &InstanceName, index: Index, suffix: S) -> String +where S: Display + Debug +{ + format!("{}/{}.{}", + savefilename(instance, "b-", ""), + index, suffix) +} + impl Display for Id { #[throws(fmt::Error)] fn fmt(&self, f: &mut fmt::Formatter) { @@ -146,6 +133,19 @@ impl Display for Id { } } +impl FromStr for Id { + type Err = NotBundle; + #[throws(NotBundle)] + fn from_str(fleaf: &str) -> Id { + let [lhs, rhs] = fleaf.splitn(2, '.') + .collect::>() + .into_inner().map_err(|_| "no dot")?; + let index = lhs.parse().map_err(|_| "bad index")?; + let kind = rhs.parse().map_err(|_| "bad extension")?; + Id { index, kind } + } +} + impl Id { fn path_tmp(&self, instance: &InstanceName) -> String { b_file(instance, self.index, "tmp") @@ -185,26 +185,83 @@ impl Id { } } -#[derive(Debug,Copy,Clone,Error)] -#[error("{0}")] -#[repr(transparent)] -pub struct NotBundle(&'static str); -impl From<&'static str> for NotBundle { - fn from(s: &'static str) -> NotBundle { - unsafe { mem::transmute(s) } +//---------- displaing/presenting/authorising ---------- + +impl Authorisation { + pub fn bundles(self) -> Authorisation { self.therefore_ok() } +} + +impl Display for State { + #[throws(fmt::Error)] + fn fmt(&self, f: &mut Formatter) { + match self { + State::Loaded(Loaded{ meta }) => { + let BundleMeta { title } = meta; + write!(f, "Loaded {:?}", title)?; + } + other => write!(f, "{:?}", other)?, + } } } -#[derive(Error,Debug)] -enum IncorporateError { - #[error("NotBundle({0})")] NotBundle(#[from] NotBundle), - #[error("{0}")] IE(#[from] IE), +#[ext(pub)] +impl MgmtBundleList { + #[throws(IE)] + fn info_pane(&self, ig: &Instance) -> Html { + #[derive(Serialize,Debug)] + struct RenderPane { + bundles: Vec, + } + #[derive(Serialize,Debug)] + struct RenderBundle { + id: Html, + url: Html, + title: Html, + } + let bundles = self.iter().filter_map(|(&id, state)| { + if_let!{ State::Loaded(Loaded { meta }) = state; else return None; } + let BundleMeta { title } = meta; + let title = Html::from_txt(title); + let token = id.token(ig); + let url = hformat!("/_/bundle/{}/{}?{}", &*ig.name, &id, &token); + let id = hformat!("{}", id); + Some(RenderBundle { id, url, title }) + }).collect(); + + Html::from_html_string( + nwtemplates::render("bundles-info-pane.tera", &RenderPane { bundles })? + ) + } } -pub struct Uploading { - instance: Arc, - id: Id, - file: DigestWrite>, +//---------- loading ---------- + +impl From for LoadError { + fn from(ze: ZipError) -> LoadError { + LE::BadBundle(format!("bad zipfile: {}", ze)) + } +} + +#[ext(pub)] +impl ZipArchive where R: Read + io::Seek { + #[throws(LoadError)] + fn by_name_caseless<'a>(&'a mut self, name: &str) -> ZipFile<'a> + { + fn search<'a,R>(za: &'a mut ZipArchive, name: &str) + -> Result + where R: Read + io::Seek + { + for i in 0..za.len() { + let m = za.by_index(i); + if matches!(m, Err(ZipError::FileNotFound)) { continue } + let m = m?; + if m.name_raw().eq_ignore_ascii_case(name.as_bytes()) { return Ok(i) } + } + return Err(LE::BadBundle(format!("bundle missing {}", name))); + } + let i = search(self, name)?; + self.by_index(i)? + } } #[throws(IE)] @@ -258,18 +315,7 @@ fn load_bundle(ib: &mut InstanceBundles, ig: &mut Instance, *slot = Some(Note { kind: id.kind, state }); } -impl FromStr for Id { - type Err = NotBundle; - #[throws(NotBundle)] - fn from_str(fleaf: &str) -> Id { - let [lhs, rhs] = fleaf.splitn(2, '.') - .collect::>() - .into_inner().map_err(|_| "no dot")?; - let index = lhs.parse().map_err(|_| "bad index")?; - let kind = rhs.parse().map_err(|_| "bad extension")?; - Id { index, kind } - } -} +//---------- scanning/incorporating/uploading ---------- #[throws(IncorporateError)] fn incorporate_bundle(ib: &mut InstanceBundles, ig: &mut Instance, @@ -381,36 +427,6 @@ impl Uploading { } } -#[ext(pub)] -impl MgmtBundleList { - #[throws(IE)] - fn info_pane(&self, ig: &Instance) -> Html { - #[derive(Serialize,Debug)] - struct RenderPane { - bundles: Vec, - } - #[derive(Serialize,Debug)] - struct RenderBundle { - id: Html, - url: Html, - title: Html, - } - let bundles = self.iter().filter_map(|(&id, state)| { - if_let!{ State::Loaded(Loaded { meta }) = state; else return None; } - let BundleMeta { title } = meta; - let title = Html::from_txt(title); - let token = id.token(ig); - let url = hformat!("/_/bundle/{}/{}?{}", &*ig.name, &id, &token); - let id = hformat!("{}", id); - Some(RenderBundle { id, url, title }) - }).collect(); - - Html::from_html_string( - nwtemplates::render("bundles-info-pane.tera", &RenderPane { bundles })? - ) - } -} - impl InstanceBundles { #[throws(MgmtError)] pub fn finish_upload(&mut self, ig: &mut Instance, -- 2.30.2