From: Ian Jackson Date: Mon, 23 Nov 2020 01:41:26 +0000 (+0000) Subject: sip multilib X-Git-Tag: otter-0.2.0~383 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=4188461cb5ae5b2ded32f84f91d3b9cc6ee5f842;p=otter.git sip multilib Signed-off-by: Ian Jackson --- diff --git a/src/cmdlistener.rs b/src/cmdlistener.rs index 35a956dc..20acfe2f 100644 --- a/src/cmdlistener.rs +++ b/src/cmdlistener.rs @@ -16,6 +16,7 @@ use pwd::Passwd; pub use crate::from_instance_lock_error; pub use std::os::unix::net::UnixStream; +type SE = SpecError; type CSE = anyhow::Error; use MgmtCommand::*; @@ -483,15 +484,31 @@ fn execute_game_insn<'cs, 'igr, 'ig : 'igr>( let (ig_g, modperm, _) = cs.check_acl_modify_pieces(ag, ig)?; let ig = &mut **ig_g; let gs = &mut ig.gs; - let count = count.unwrap_or(1); - if count > CREATE_PIECES_MAX { throw!(ME::LimitExceeded) } + let implicit : u32 = info.count() + .try_into().map_err( + |_| SE::InternalError(format!("implicit item count out of range")) + )?; + let count : Box> = match count { + Some(explicit) if implicit == 1 => { + Box::new((0..explicit).map(|_| 0)) + }, + Some(explicit) if implicit != explicit => { + throw!(SpecError::InconsistentPieceCount) + }, + None | Some(_) => { + Box::new(0..implicit) + }, + }; + + let count_len = count.len(); + if count.len() > CREATE_PIECES_MAX as usize { throw!(ME::LimitExceeded) } let posd = posd.unwrap_or(DEFAULT_POS_DELTA); - let mut updates = Vec::with_capacity(count as usize); + let mut updates = Vec::with_capacity(count_len); let mut pos = pos.unwrap_or(DEFAULT_POS_START); let mut z = gs.max_z.clone_mut(); - for _ in 0..count { - let p = info.load()?; + for piece_i in count { + let p = info.load(piece_i as usize)?; let face = face.unwrap_or_default(); if p.nfaces() <= face.into() { throw!(SpecError::FaceNotFound); @@ -517,7 +534,7 @@ fn execute_game_insn<'cs, 'igr, 'ig : 'igr>( (U{ pcs: updates, log: vec![ LogEntry { - html: Html(format!("{} added {} pieces", &who.0, count)), + html: Html(format!("{} added {} pieces", &who.0, count_len)), }], raw: None }, Fine, ig_g) diff --git a/src/gamestate.rs b/src/gamestate.rs index 65848b8b..b9395a4b 100644 --- a/src/gamestate.rs +++ b/src/gamestate.rs @@ -141,7 +141,8 @@ pub struct PieceRenderInstructions { #[typetag::serde(tag="type")] pub trait PieceSpec : Debug { - fn load(&self) -> Result,SpecError>; + fn count(&self) -> usize { 1 } + fn load(&self, i: usize) -> Result,SpecError>; } // ========== implementations ========== diff --git a/src/pieces.rs b/src/pieces.rs index ec97620f..fdf43230 100644 --- a/src/pieces.rs +++ b/src/pieces.rs @@ -157,7 +157,7 @@ impl SimpleShape { #[typetag::serde] impl PieceSpec for piece_specs::Disc { #[throws(SpecError)] - fn load(&self) -> Box { + fn load(&self, _: usize) -> Box { let outline = Box::new(shapelib::Circle { diam: self.diam as f64 }); let path = svg_circle_path(self.diam as f64)?; let itemname = self.itemname.clone() @@ -170,7 +170,7 @@ impl PieceSpec for piece_specs::Disc { #[typetag::serde] impl PieceSpec for piece_specs::Square { #[throws(SpecError)] - fn load(&self) -> Box { + fn load(&self, _: usize) -> Box { let xy = match *self.size.as_slice() { [s,] => PosC([s,s]), [x,y] => PosC([x,y]), diff --git a/src/shapelib.rs b/src/shapelib.rs index 0daae466..d15ad41d 100644 --- a/src/shapelib.rs +++ b/src/shapelib.rs @@ -122,6 +122,12 @@ pub struct ItemSpec { pub item: String, } +#[derive(Debug,Clone,Serialize,Deserialize)] +pub struct MultiSpec { + pub lib: String, + pub items: Vec, +} + define_index_type!{ pub struct DescId = u8; } define_index_type!{ pub struct SvgId = u8; } @@ -271,11 +277,23 @@ impl Contents { #[typetag::serde(name="Lib")] impl PieceSpec for ItemSpec { - fn load(&self) -> Result,SpecError> { + fn load(&self, _: usize) -> Result,SpecError> { self.load() } } +#[typetag::serde(name="LibList")] +impl PieceSpec for MultiSpec { + fn count(&self) -> usize { self.items.len() } + fn load(&self, i: usize) -> Result,SpecError> { + let item = self.items.get(i).ok_or_else( + || SE::InternalError(format!("item {:?} from {:?}", i, &self)) + )?.clone(); + let lib = self.lib.clone(); + ItemSpec { lib, item }.load() + } +} + #[throws(LibraryLoadError)] fn resolve_inherit<'r>(depth: u8, groups: &toml::value::Table, group_name: &str, group: &'r toml::Value) diff --git a/src/spec.rs b/src/spec.rs index 212be8d9..98e2a5e0 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -57,6 +57,7 @@ pub enum SpecError { LibraryItemNotFound, AclInvalidAccountGlob, AclEntryOverlappingAllowDeny, + InconsistentPieceCount, } display_as_debug!{SpecError}