cosmic_space/
command.rs

1use core::str::FromStr;
2
3use nom::combinator::all_consuming;
4use serde::{Deserialize, Serialize};
5
6use cosmic_macros_primitive::Autobox;
7use cosmic_nom::{new_span, Trace};
8use direct::create::{Create, CreateCtx, CreateVar};
9use direct::delete::{DeleteCtx, DeleteVar};
10use direct::get::{Get, GetCtx, GetVar};
11use direct::read::{Read, ReadCtx, ReadVar};
12use direct::select::{SelectCtx, SelectVar};
13use direct::set::{Set, SetCtx, SetVar};
14use direct::write::{Write, WriteCtx, WriteVar};
15
16use crate::parse::error::result;
17use crate::parse::{command_line, Env};
18use crate::substance::{Bin, ChildSubstance};
19use crate::util::ToResolved;
20use crate::wave::core::cmd::CmdMethod;
21use crate::{Delete, Select, SpaceErr};
22
23pub mod common {
24    use std::collections::hash_map::Iter;
25    use std::collections::HashMap;
26    use std::convert::{TryFrom, TryInto};
27    use std::ops::{Deref, DerefMut};
28
29    use serde::{Deserialize, Serialize};
30
31    use crate::err::SpaceErr;
32    use crate::loc::Variable;
33    use crate::parse::model::Var;
34    use crate::substance::{Substance, SubstanceMap};
35
36    #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, strum_macros::Display)]
37    pub enum StateSrcVar {
38        None,
39        FileRef(String),
40        Var(Variable),
41    }
42
43    #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, strum_macros::Display)]
44    pub enum StateSrc {
45        None,
46        Substance(Box<Substance>),
47    }
48
49    impl StateSrc {
50        pub fn has_substance(&self) -> bool {
51            match self {
52                StateSrc::None => false,
53                StateSrc::Substance(_) => true,
54            }
55        }
56
57        pub fn get_substance(&self) -> Result<Substance, SpaceErr> {
58            match self {
59                StateSrc::None => Err(SpaceErr::server_error("state has no substance")),
60                StateSrc::Substance(substance) => Ok(*substance.clone()),
61            }
62        }
63    }
64
65    #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
66    pub enum PropertyMod {
67        Set {
68            key: String,
69            value: String,
70            lock: bool,
71        },
72        UnSet(String),
73    }
74
75    impl PropertyMod {
76        pub fn set_or<E>(&self, err: E) -> Result<String, E> {
77            match self {
78                Self::Set { key, value, lock } => Ok(value.clone()),
79                Self::UnSet(_) => Err(err),
80            }
81        }
82
83        pub fn opt(&self) -> Option<String> {
84            match self {
85                Self::Set { key, value, lock } => Some(value.clone()),
86                Self::UnSet(_) => None,
87            }
88        }
89    }
90
91    #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
92    pub struct SetProperties {
93        pub map: HashMap<String, PropertyMod>,
94    }
95
96    impl Default for SetProperties {
97        fn default() -> Self {
98            Self {
99                map: Default::default(),
100            }
101        }
102    }
103
104    impl SetProperties {
105        pub fn new() -> Self {
106            Self {
107                map: HashMap::new(),
108            }
109        }
110
111        pub fn append(&mut self, properties: SetProperties) {
112            for (_, property) in properties.map.into_iter() {
113                self.push(property);
114            }
115        }
116
117        pub fn push(&mut self, property: PropertyMod) {
118            match &property {
119                PropertyMod::Set { key, value, lock } => {
120                    self.map.insert(key.clone(), property);
121                }
122                PropertyMod::UnSet(key) => {
123                    self.map.insert(key.clone(), property);
124                }
125            }
126        }
127
128        pub fn iter(&self) -> Iter<'_, String, PropertyMod> {
129            self.map.iter()
130        }
131    }
132
133    impl Deref for SetProperties {
134        type Target = HashMap<String, PropertyMod>;
135
136        fn deref(&self) -> &Self::Target {
137            &self.map
138        }
139    }
140
141    #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, strum_macros::Display)]
142    pub enum SetLabel {
143        Set(String),
144        SetValue { key: String, value: String },
145        Unset(String),
146    }
147
148    #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
149    pub struct SetRegistry {
150        pub labels: Vec<SetLabel>,
151    }
152
153    impl Deref for SetRegistry {
154        type Target = Vec<SetLabel>;
155
156        fn deref(&self) -> &Self::Target {
157            &self.labels
158        }
159    }
160
161    impl DerefMut for SetRegistry {
162        fn deref_mut(&mut self) -> &mut Self::Target {
163            &mut self.labels
164        }
165    }
166
167    impl Default for SetRegistry {
168        fn default() -> Self {
169            Self {
170                labels: Default::default(),
171            }
172        }
173    }
174}
175
176pub mod direct {
177    //    use http::status::InvalidStatusCode;
178    //    use http::{HeaderMap, Request, StatusCode, Uri};
179    use serde::{Deserialize, Serialize};
180
181    use crate::command::direct::create::Create;
182    use crate::command::direct::get::Get;
183    use crate::command::direct::select::Select;
184    use crate::command::direct::set::Set;
185    use crate::command::direct::write::Write;
186    use crate::err::SpaceErr;
187    use crate::fail;
188    use crate::fail::{BadRequest, Fail, NotFound};
189    use crate::kind::{BaseKind, KindParts};
190    use crate::loc::Meta;
191    use crate::point::Point;
192    use crate::selector::KindSelector;
193    use crate::substance::Bin;
194    use crate::substance::{FormErrs, Substance};
195    use crate::util::{ValueMatcher, ValuePattern};
196    use crate::wave::core::ext::ExtMethod;
197    use crate::wave::core::http2::HttpMethod;
198    use crate::wave::core::MethodKind;
199    use crate::wave::core::ReflectedCore;
200
201    #[derive(Debug, Clone, Serialize, Deserialize)]
202    pub enum Cmd {
203        Create(Create),
204        Select(Select),
205        Update(Write),
206        Get(Get),
207        Set(Set),
208    }
209
210    impl PartialEq<Self> for Cmd {
211        fn eq(&self, other: &Self) -> bool {
212            self.get_type() == other.get_type()
213        }
214    }
215
216    impl Eq for Cmd {}
217
218    impl Cmd {
219        pub fn get_type(&self) -> CmdKind {
220            match self {
221                Cmd::Create(_) => CmdKind::Create,
222                Cmd::Select(_) => CmdKind::Select,
223                Cmd::Update(_) => CmdKind::Update,
224                Cmd::Get(_) => CmdKind::Get,
225                Cmd::Set(_) => CmdKind::Set,
226            }
227        }
228    }
229
230    #[derive(
231        Debug,
232        Clone,
233        Eq,
234        PartialEq,
235        strum_macros::Display,
236        strum_macros::EnumString,
237        Serialize,
238        Deserialize,
239    )]
240    pub enum CmdKind {
241        Create,
242        Select,
243        Update,
244        Query,
245        Get,
246        Set,
247    }
248
249    impl ValueMatcher<Cmd> for Cmd {
250        fn is_match(&self, x: &Cmd) -> Result<(), ()> {
251            if self.get_type() == x.get_type() {
252                Ok(())
253            } else {
254                Err(())
255            }
256        }
257    }
258
259    impl ToString for Cmd {
260        fn to_string(&self) -> String {
261            format!("Rc<{}>", self.get_type().to_string())
262        }
263    }
264
265    pub mod set {
266        use serde::{Deserialize, Serialize};
267
268        use crate::command::common::SetProperties;
269        use crate::err::SpaceErr;
270        use crate::parse::Env;
271        use crate::point::{Point, PointCtx, PointVar};
272        use crate::util::ToResolved;
273
274        pub type Set = SetDef<Point>;
275        pub type SetCtx = SetDef<PointCtx>;
276        pub type SetVar = SetDef<PointVar>;
277
278        #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
279        pub struct SetDef<Pnt> {
280            pub point: Pnt,
281            pub properties: SetProperties,
282        }
283
284        impl ToResolved<Set> for SetVar {
285            fn to_resolved(self, env: &Env) -> Result<Set, SpaceErr> {
286                let set: SetCtx = self.to_resolved(env)?;
287                set.to_resolved(env)
288            }
289        }
290
291        impl ToResolved<SetCtx> for SetVar {
292            fn to_resolved(self, env: &Env) -> Result<SetCtx, SpaceErr> {
293                Ok(SetCtx {
294                    point: self.point.to_resolved(env)?,
295                    properties: self.properties,
296                })
297            }
298        }
299
300        impl ToResolved<Set> for SetCtx {
301            fn to_resolved(self, env: &Env) -> Result<Set, SpaceErr> {
302                Ok(Set {
303                    point: self.point.to_resolved(env)?,
304                    properties: self.properties,
305                })
306            }
307        }
308    }
309
310    pub mod get {
311        use serde::{Deserialize, Serialize};
312
313        use crate::command::common::SetProperties;
314        use crate::err::SpaceErr;
315        use crate::parse::Env;
316        use crate::point::{Point, PointCtx, PointVar};
317        use crate::util::ToResolved;
318
319        pub type Get = GetDef<Point>;
320        pub type GetCtx = GetDef<PointCtx>;
321        pub type GetVar = GetDef<PointVar>;
322
323        #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
324        pub struct GetDef<Pnt> {
325            pub point: Pnt,
326            pub op: GetOp,
327        }
328
329        impl ToResolved<Get> for GetVar {
330            fn to_resolved(self, env: &Env) -> Result<Get, SpaceErr> {
331                let set: GetCtx = self.to_resolved(env)?;
332                set.to_resolved(env)
333            }
334        }
335
336        impl ToResolved<GetCtx> for GetVar {
337            fn to_resolved(self, env: &Env) -> Result<GetCtx, SpaceErr> {
338                Ok(GetCtx {
339                    point: self.point.to_resolved(env)?,
340                    op: self.op,
341                })
342            }
343        }
344
345        impl ToResolved<Get> for GetCtx {
346            fn to_resolved(self, env: &Env) -> Result<Get, SpaceErr> {
347                Ok(Get {
348                    point: self.point.to_resolved(env)?,
349                    op: self.op,
350                })
351            }
352        }
353
354        #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
355        pub enum GetOp {
356            State,
357            Properties(Vec<String>),
358        }
359    }
360
361    pub mod create {
362        use std::convert::TryInto;
363        use std::sync::atomic::{AtomicU64, Ordering};
364        use std::sync::Arc;
365
366        use serde::{Deserialize, Serialize};
367        use tokio::sync::Mutex;
368
369        use crate::command::common::{SetProperties, SetRegistry, StateSrc, StateSrcVar};
370        use crate::command::Command;
371        use crate::err::SpaceErr;
372        use crate::kind::{BaseKind, KindParts};
373        use crate::loc::{HostKey, PointFactory, ToSurface};
374        use crate::parse::model::Subst;
375        use crate::parse::{CamelCase, Env, ResolverErr};
376        use crate::point::{Point, PointCtx, PointSeg, PointVar};
377        use crate::selector::SpecificSelector;
378        use crate::substance::Bin;
379        use crate::substance::Substance;
380        use crate::util::{ConvertFrom, ToResolved};
381        use crate::wave::core::cmd::CmdMethod;
382        use crate::wave::core::ext::ExtMethod;
383        use crate::wave::core::hyp::HypMethod;
384        use crate::wave::core::DirectedCore;
385        use crate::wave::{DirectedProto, Ping, Wave};
386
387        pub enum PointTemplateSeg {
388            ExactSeg(PointSeg),
389            Wildcard(String),
390        }
391
392        impl PointTemplateSeg {
393            pub fn is_wildcard(&self) -> bool {
394                match self {
395                    PointTemplateSeg::ExactSeg(_) => false,
396                    PointTemplateSeg::Wildcard(_) => true,
397                }
398            }
399        }
400
401        pub type Template = TemplateDef<PointTemplate>;
402        pub type TemplateCtx = TemplateDef<PointTemplateCtx>;
403        pub type TemplateVar = TemplateDef<PointTemplateVar>;
404
405        #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
406        pub struct TemplateDef<Pnt> {
407            pub point: Pnt,
408            pub kind: KindTemplate,
409        }
410
411        impl ToResolved<Template> for TemplateVar {
412            fn to_resolved(self, env: &Env) -> Result<Template, SpaceErr> {
413                let template: TemplateCtx = self.to_resolved(env)?;
414                template.to_resolved(env)
415            }
416        }
417
418        impl ToResolved<TemplateCtx> for TemplateVar {
419            fn to_resolved(self, env: &Env) -> Result<TemplateCtx, SpaceErr> {
420                let point: PointTemplateCtx = self.point.to_resolved(env)?;
421
422                let template = TemplateCtx {
423                    point,
424                    kind: self.kind,
425                };
426                Ok(template)
427            }
428        }
429        impl ToResolved<Template> for TemplateCtx {
430            fn to_resolved(self, env: &Env) -> Result<Template, SpaceErr> {
431                let point = self.point.to_resolved(env)?;
432
433                let template = Template {
434                    point,
435                    kind: self.kind,
436                };
437                Ok(template)
438            }
439        }
440
441        impl Template {
442            pub fn new(point: PointTemplate, kind: KindTemplate) -> Self {
443                Self { point, kind }
444            }
445        }
446
447        #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
448        pub struct KindTemplate {
449            pub base: BaseKind,
450            pub sub: Option<CamelCase>,
451            pub specific: Option<SpecificSelector>,
452        }
453
454        impl ToString for KindTemplate {
455            fn to_string(&self) -> String {
456                if self.sub.is_some() {
457                    if self.specific.is_some() {
458                        format!(
459                            "{}<{}<{}>>",
460                            self.base.to_string(),
461                            self.sub.as_ref().unwrap().to_string(),
462                            self.specific.as_ref().unwrap().to_string()
463                        )
464                    } else {
465                        format!(
466                            "{}<{}>",
467                            self.base.to_string(),
468                            self.sub.as_ref().unwrap().to_string()
469                        )
470                    }
471                } else {
472                    self.base.to_string()
473                }
474            }
475        }
476
477        impl TryInto<KindParts> for KindTemplate {
478            type Error = SpaceErr;
479
480            fn try_into(self) -> Result<KindParts, Self::Error> {
481                if self.specific.is_some() {
482                    return Err("cannot create a ResourceKind from a specific pattern when using KindTemplate".into());
483                }
484                Ok(KindParts {
485                    base: self.base,
486                    sub: self.sub,
487                    specific: None,
488                })
489            }
490        }
491
492        #[derive(Debug, Clone, Serialize, Deserialize)]
493        pub enum Require {
494            File(String),
495            Auth(String),
496        }
497
498        #[derive(Debug, Clone, Serialize, Deserialize)]
499        pub enum Fulfillment {
500            File { name: String, content: Bin },
501            Complete,
502        }
503
504        pub type Create = CreateDef<Point, StateSrc>;
505        pub type CreateVar = CreateDef<PointVar, StateSrcVar>;
506        pub type CreateCtx = CreateDef<PointCtx, StateSrc>;
507
508        impl ToResolved<Create> for CreateVar {
509            fn to_resolved(self, env: &Env) -> Result<Create, SpaceErr> {
510                let create: CreateCtx = self.to_resolved(env)?;
511                create.to_resolved(env)
512            }
513        }
514
515        impl ToResolved<CreateCtx> for CreateVar {
516            fn to_resolved(self, env: &Env) -> Result<CreateCtx, SpaceErr> {
517                let template = self.template.to_resolved(env)?;
518                let state = match &self.state {
519                    StateSrcVar::None => StateSrc::None,
520                    StateSrcVar::FileRef(name) => StateSrc::Substance(Box::new(Substance::Bin(
521                        env.file(name)
522                            .map_err(|e| match e {
523                                ResolverErr::NotAvailable => SpaceErr::server_error(
524                                    "files are not available in this context",
525                                ),
526                                ResolverErr::NotFound => {
527                                    SpaceErr::server_error(format!("cannot find file '{}'", name))
528                                }
529                            })?
530                            .content,
531                    ))),
532                    StateSrcVar::Var(var) => {
533                        let val = env.val(var.name.as_str()).map_err(|e| match e {
534                            ResolverErr::NotAvailable => {
535                                SpaceErr::server_error("variable are not available in this context")
536                            }
537                            ResolverErr::NotFound => SpaceErr::server_error(format!(
538                                "cannot find variable '{}'",
539                                var.name
540                            )),
541                        })?;
542                        StateSrc::Substance(Box::new(Substance::Bin(
543                            env.file(val.clone())
544                                .map_err(|e| match e {
545                                    ResolverErr::NotAvailable => SpaceErr::server_error(
546                                        "files are not available in this context",
547                                    ),
548                                    ResolverErr::NotFound => SpaceErr::server_error(format!(
549                                        "cannot find file '{}'",
550                                        val.to_text().unwrap_or("err".to_string())
551                                    )),
552                                })?
553                                .content,
554                        )))
555                    }
556                };
557                Ok(CreateCtx {
558                    template,
559                    properties: self.properties,
560                    strategy: self.strategy,
561                    state,
562                })
563            }
564        }
565
566        impl ToResolved<Create> for CreateCtx {
567            fn to_resolved(self, env: &Env) -> Result<Create, SpaceErr> {
568                let template = self.template.to_resolved(env)?;
569                Ok(Create {
570                    template,
571                    properties: self.properties,
572                    strategy: self.strategy,
573                    state: self.state,
574                })
575            }
576        }
577
578        #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
579        pub struct CreateDef<Pnt, StateSrc> {
580            pub template: TemplateDef<PointTemplateDef<Pnt>>,
581            pub properties: SetProperties,
582            pub strategy: Strategy,
583            pub state: StateSrc,
584        }
585
586        impl Create {
587            pub fn fulfillment(mut self, bin: Bin) -> Create {
588                Create {
589                    template: self.template,
590                    state: StateSrc::Substance(Box::new(Substance::Bin(bin))),
591                    properties: self.properties,
592                    strategy: self.strategy,
593                }
594            }
595
596            pub fn to_wave_proto(self) -> DirectedProto {
597                let mut wave = DirectedProto::ping();
598                wave.method(CmdMethod::Command);
599                wave.body(Substance::Command(Box::new(Command::Create(self))));
600                wave.to(Point::global_executor());
601                wave
602            }
603        }
604
605        impl Into<DirectedCore> for Create {
606            fn into(self) -> DirectedCore {
607                let mut directed = DirectedCore::ext(ExtMethod::new("Command").unwrap());
608                directed.body = Substance::Command(Box::new(Command::Create(self)));
609                directed
610            }
611        }
612
613        impl Into<DirectedProto> for Create {
614            fn into(self) -> DirectedProto {
615                let mut request =
616                    DirectedProto::cmd(Point::global_executor().to_surface(), CmdMethod::Command);
617                request.body(Substance::Command(Box::new(Command::Create(self))));
618                request
619            }
620        }
621
622        #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, strum_macros::Display)]
623        pub enum Strategy {
624            Commit,
625            Ensure,
626            Override,
627        }
628
629        pub struct PointFactoryU64 {
630            parent: Point,
631            prefix: String,
632            atomic: Arc<AtomicU64>,
633        }
634
635        impl PointFactoryU64 {
636            pub fn new(parent: Point, prefix: String) -> Self {
637                Self {
638                    parent,
639                    prefix,
640                    atomic: Arc::new(AtomicU64::new(0)),
641                }
642            }
643        }
644
645        #[async_trait]
646        impl PointFactory for PointFactoryU64 {
647            async fn create(&self) -> Result<Point, SpaceErr> {
648                let index = self.atomic.fetch_add(1u64, Ordering::Relaxed);
649                self.parent.push(format!("{}{}", self.prefix, index))
650            }
651        }
652
653        pub type PointTemplate = PointTemplateDef<Point>;
654        pub type PointTemplateCtx = PointTemplateDef<PointCtx>;
655        pub type PointTemplateVar = PointTemplateDef<PointVar>;
656
657        #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
658        pub struct PointTemplateDef<Pnt> {
659            pub parent: Pnt,
660            pub child_segment_template: PointSegTemplate,
661        }
662
663        impl ToResolved<PointTemplateCtx> for PointTemplateVar {
664            fn to_resolved(self, env: &Env) -> Result<PointTemplateCtx, SpaceErr> {
665                let parent = self.parent.to_resolved(env)?;
666                Ok(PointTemplateCtx {
667                    parent,
668                    child_segment_template: self.child_segment_template,
669                })
670            }
671        }
672
673        impl ToResolved<PointTemplate> for PointTemplateCtx {
674            fn to_resolved(self, env: &Env) -> Result<PointTemplate, SpaceErr> {
675                let parent = self.parent.to_resolved(env)?;
676                Ok(PointTemplate {
677                    parent,
678                    child_segment_template: self.child_segment_template,
679                })
680            }
681        }
682
683        impl ToResolved<PointTemplate> for PointTemplateVar {
684            fn to_resolved(self, env: &Env) -> Result<PointTemplate, SpaceErr> {
685                let ctx: PointTemplateCtx = self.to_resolved(env)?;
686                ctx.to_resolved(env)
687            }
688        }
689
690        #[derive(Debug, Clone, strum_macros::Display, Serialize, Deserialize, Eq, PartialEq)]
691        pub enum PointSegTemplate {
692            Exact(String),
693            Pattern(String), // must have a '%'
694            Root,
695        }
696    }
697
698    pub mod select {
699        use std::collections::{HashMap, HashSet};
700        use std::convert::{TryFrom, TryInto};
701        use std::marker::PhantomData;
702
703        use serde::{Deserialize, Serialize};
704
705        use crate::err::SpaceErr;
706        use crate::fail::{BadCoercion, Fail};
707        use crate::point::Point;
708        use crate::parse::Env;
709        use crate::particle::Stub;
710        use crate::selector::{Hop, HopCtx, HopVar, PointHierarchy, Selector, SelectorDef};
711        use crate::substance::{MapPattern, Substance, SubstanceList};
712        use crate::util::{ConvertFrom, ToResolved};
713
714        #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
715        pub enum SelectIntoSubstance {
716            Stubs,
717            Points,
718        }
719
720        impl SelectIntoSubstance {
721            pub fn to_primitive(&self, stubs: Vec<Stub>) -> Result<SubstanceList, SpaceErr> {
722                match self {
723                    SelectIntoSubstance::Stubs => {
724                        let stubs: Vec<Box<Substance>> = stubs
725                            .into_iter()
726                            .map(|stub| Box::new(Substance::Stub(stub)))
727                            .collect();
728                        let stubs = SubstanceList { list: stubs };
729                        Ok(stubs)
730                    }
731                    SelectIntoSubstance::Points => {
732                        let pointes: Vec<Box<Substance>> = stubs
733                            .into_iter()
734                            .map(|stub| Box::new(Substance::Point(stub.point)))
735                            .collect();
736                        let stubs = SubstanceList { list: pointes };
737                        Ok(stubs)
738                    }
739                }
740            }
741        }
742
743        pub type Select = SelectDef<Hop>;
744        pub type SelectCtx = SelectDef<Hop>;
745        pub type SelectVar = SelectDef<Hop>;
746
747        impl ToResolved<Select> for Select {
748            fn to_resolved(self, env: &Env) -> Result<Select, SpaceErr> {
749                Ok(self)
750            }
751        }
752
753        #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
754        pub struct SelectDef<Hop> {
755            pub pattern: SelectorDef<Hop>,
756            pub properties: PropertiesPattern,
757            pub into_substance: SelectIntoSubstance,
758            pub kind: SelectKind,
759        }
760
761        #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
762        pub enum SelectKind {
763            Initial,
764            SubSelect {
765                point: Point,
766                hops: Vec<Hop>,
767                hierarchy: PointHierarchy,
768            },
769        }
770
771        impl Select {
772            pub fn sub_select(
773                self,
774                point: Point,
775                hops: Vec<Hop>,
776                hierarchy: PointHierarchy,
777            ) -> SubSelect {
778                SubSelect {
779                    point,
780                    pattern: self.pattern,
781                    properties: self.properties,
782                    into_payload: self.into_substance,
783                    hops,
784                    hierarchy,
785                }
786            }
787        }
788
789        impl TryInto<SubSelect> for Select {
790            type Error = SpaceErr;
791
792            fn try_into(self) -> Result<SubSelect, Self::Error> {
793                if let SelectKind::SubSelect {
794                    point,
795                    hops,
796                    hierarchy,
797                } = self.kind
798                {
799                    Ok(SubSelect {
800                        point,
801                        pattern: self.pattern,
802                        properties: self.properties,
803                        into_payload: self.into_substance,
804                        hops: hops,
805                        hierarchy,
806                    })
807                } else {
808                    Err("Not of kind SubSelector".into())
809                }
810            }
811        }
812
813        #[derive(Debug, Clone)]
814        pub struct SubSelect {
815            pub point: Point,
816            pub pattern: Selector,
817            pub properties: PropertiesPattern,
818            pub into_payload: SelectIntoSubstance,
819            pub hops: Vec<Hop>,
820            pub hierarchy: PointHierarchy,
821        }
822
823        impl Into<Select> for SubSelect {
824            fn into(self) -> Select {
825                Select {
826                    pattern: self.pattern,
827                    properties: self.properties,
828                    into_substance: self.into_payload,
829                    kind: SelectKind::SubSelect {
830                        point: self.point,
831                        hops: self.hops,
832                        hierarchy: self.hierarchy,
833                    },
834                }
835            }
836        }
837
838        impl SubSelect {
839            pub fn sub_select(
840                &self,
841                point: Point,
842                hops: Vec<Hop>,
843                hierarchy: PointHierarchy,
844            ) -> SubSelect {
845                SubSelect {
846                    point,
847                    pattern: self.pattern.clone(),
848                    properties: self.properties.clone(),
849                    into_payload: self.into_payload.clone(),
850                    hops,
851                    hierarchy,
852                }
853            }
854        }
855
856        impl Select {
857            pub fn new(pattern: Selector) -> Self {
858                Self {
859                    pattern,
860                    properties: Default::default(),
861                    into_substance: SelectIntoSubstance::Stubs,
862                    kind: SelectKind::Initial,
863                }
864            }
865        }
866
867        pub type PropertiesPattern = MapPattern;
868    }
869
870    pub mod delete {
871        use serde::{Deserialize, Serialize};
872
873        use crate::command::direct::select::{PropertiesPattern, Select, SelectIntoSubstance};
874        use crate::err::SpaceErr;
875        use crate::parse::Env;
876        use crate::selector::{Hop, SelectorDef};
877        use crate::util::ToResolved;
878
879        pub type Delete = DeleteDef<Hop>;
880        pub type DeleteCtx = DeleteDef<Hop>;
881        pub type DeleteVar = DeleteDef<Hop>;
882
883        impl ToResolved<Delete> for Delete {
884            fn to_resolved(self, env: &Env) -> Result<Delete, SpaceErr> {
885                Ok(self)
886            }
887        }
888
889        #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
890        pub struct DeleteDef<Hop> {
891            pub selector: SelectorDef<Hop>,
892        }
893
894        impl Into<Select> for Delete {
895            fn into(self) -> Select {
896                let mut select = Select::new(self.selector);
897                select.into_substance = SelectIntoSubstance::Points;
898                select
899            }
900        }
901    }
902
903    pub mod write {
904        use std::convert::TryInto;
905
906        use serde::{Deserialize, Serialize};
907
908        use crate::command::common::SetProperties;
909        use crate::err::SpaceErr;
910        use crate::parse::Env;
911        use crate::point::{Point, PointCtx, PointVar};
912        use crate::substance::Substance;
913        use crate::util::ToResolved;
914
915        pub type Write = WriteDef<Point>;
916        pub type WriteCtx = WriteDef<PointCtx>;
917        pub type WriteVar = WriteDef<PointVar>;
918
919        #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
920        pub struct WriteDef<Pnt> {
921            pub point: Pnt,
922            pub payload: Substance,
923        }
924
925        impl ToResolved<WriteCtx> for WriteVar {
926            fn to_resolved(self, env: &Env) -> Result<WriteCtx, SpaceErr> {
927                Ok(WriteCtx {
928                    point: self.point.to_resolved(env)?,
929                    payload: self.payload,
930                })
931            }
932        }
933
934        impl ToResolved<Write> for WriteCtx {
935            fn to_resolved(self, env: &Env) -> Result<Write, SpaceErr> {
936                Ok(Write {
937                    point: self.point.to_resolved(env)?,
938                    payload: self.payload,
939                })
940            }
941        }
942    }
943
944    pub mod read {
945        use serde::{Deserialize, Serialize};
946
947        use crate::err::SpaceErr;
948        use crate::parse::Env;
949        use crate::point::{Point, PointCtx, PointVar};
950        use crate::substance::Substance;
951        use crate::util::ToResolved;
952
953        pub type Read = ReadDef<Point>;
954        pub type ReadCtx = ReadDef<PointCtx>;
955        pub type ReadVar = ReadDef<PointVar>;
956
957        #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
958        pub struct ReadDef<Pnt> {
959            pub point: Pnt,
960            pub payload: Substance,
961        }
962
963        impl ToResolved<ReadCtx> for ReadVar {
964            fn to_resolved(self, env: &Env) -> Result<ReadCtx, SpaceErr> {
965                Ok(ReadCtx {
966                    point: self.point.to_resolved(env)?,
967                    payload: self.payload,
968                })
969            }
970        }
971
972        impl ToResolved<Read> for ReadCtx {
973            fn to_resolved(self, env: &Env) -> Result<Read, SpaceErr> {
974                Ok(Read {
975                    point: self.point.to_resolved(env)?,
976                    payload: self.payload,
977                })
978            }
979        }
980    }
981
982    pub mod query {
983        use std::convert::TryInto;
984
985        use serde::{Deserialize, Serialize};
986
987        use crate::command::direct::Cmd;
988        use crate::err::SpaceErr;
989        use crate::selector::PointHierarchy;
990
991        #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
992        pub enum Query {
993            PointHierarchy,
994        }
995
996        #[derive(Debug, Clone, Serialize, Deserialize)]
997        pub enum QueryResult {
998            PointHierarchy(PointHierarchy),
999        }
1000
1001        impl TryInto<PointHierarchy> for QueryResult {
1002            type Error = SpaceErr;
1003
1004            fn try_into(self) -> Result<PointHierarchy, SpaceErr> {
1005                match self {
1006                    QueryResult::PointHierarchy(hierarchy) => Ok(hierarchy),
1007                }
1008            }
1009        }
1010
1011        impl ToString for QueryResult {
1012            fn to_string(&self) -> String {
1013                match self {
1014                    QueryResult::PointHierarchy(hierarchy) => hierarchy.to_string(),
1015                }
1016            }
1017        }
1018    }
1019}
1020
1021#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, Autobox)]
1022pub enum Command {
1023    Create(Create),
1024    Delete(Delete),
1025    Select(Select),
1026    Set(Set),
1027    Get(Get),
1028    Write(Write),
1029    Read(Read),
1030}
1031
1032impl ChildSubstance for Command {}
1033
1034impl Command {
1035    pub fn matches(&self, method: &CmdMethod) -> Result<(), ()> {
1036        if match self {
1037            Command::Write(_) => *method == CmdMethod::Update,
1038            Command::Read(_) => *method == CmdMethod::Read,
1039            _ => false,
1040        } {
1041            Ok(())
1042        } else {
1043            Err(())
1044        }
1045    }
1046}
1047
1048pub enum CommandCtx {
1049    Create(CreateCtx),
1050    Delete(DeleteCtx),
1051    Select(SelectCtx),
1052    Set(SetCtx),
1053    Get(GetCtx),
1054    Update(WriteCtx),
1055    Read(ReadCtx),
1056}
1057
1058pub enum CommandVar {
1059    Create(CreateVar),
1060    Delete(DeleteVar),
1061    Select(SelectVar),
1062    Set(SetVar),
1063    Get(GetVar),
1064    Update(WriteVar),
1065    Read(ReadVar),
1066}
1067
1068impl FromStr for CommandVar {
1069    type Err = SpaceErr;
1070
1071    fn from_str(s: &str) -> Result<Self, Self::Err> {
1072        let s = new_span(s);
1073        result(all_consuming(command_line)(s))
1074    }
1075}
1076
1077impl ToResolved<Command> for CommandVar {
1078    fn to_resolved(self, env: &Env) -> Result<Command, SpaceErr> {
1079        let command: CommandCtx = self.to_resolved(env)?;
1080        command.to_resolved(env)
1081    }
1082}
1083
1084impl ToResolved<CommandCtx> for CommandVar {
1085    fn to_resolved(self, env: &Env) -> Result<CommandCtx, SpaceErr> {
1086        Ok(match self {
1087            CommandVar::Create(i) => CommandCtx::Create(i.to_resolved(env)?),
1088            CommandVar::Select(i) => CommandCtx::Select(i.to_resolved(env)?),
1089            CommandVar::Set(i) => CommandCtx::Set(i.to_resolved(env)?),
1090            CommandVar::Get(i) => CommandCtx::Get(i.to_resolved(env)?),
1091            CommandVar::Delete(i) => CommandCtx::Delete(i.to_resolved(env)?),
1092            CommandVar::Update(update) => CommandCtx::Update(update.to_resolved(env)?),
1093            CommandVar::Read(read) => CommandCtx::Read(read.to_resolved(env)?),
1094        })
1095    }
1096}
1097
1098impl ToResolved<Command> for CommandCtx {
1099    fn to_resolved(self, env: &Env) -> Result<Command, SpaceErr> {
1100        Ok(match self {
1101            CommandCtx::Create(i) => Command::Create(i.to_resolved(env)?),
1102            CommandCtx::Select(i) => Command::Select(i.to_resolved(env)?),
1103            CommandCtx::Set(i) => Command::Set(i.to_resolved(env)?),
1104            CommandCtx::Get(i) => Command::Get(i.to_resolved(env)?),
1105            CommandCtx::Delete(i) => Command::Delete(i.to_resolved(env)?),
1106            CommandCtx::Update(update) => Command::Write(update.to_resolved(env)?),
1107            CommandCtx::Read(read) => Command::Read(read.to_resolved(env)?),
1108        })
1109    }
1110}
1111
1112#[derive(Debug, Clone, Serialize, Deserialize)]
1113pub struct CommandTemplate {
1114    pub line: String,
1115    pub transfers: Vec<Trace>,
1116}
1117
1118#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
1119pub struct RawCommand {
1120    pub line: String,
1121    pub transfers: Vec<CmdTransfer>,
1122}
1123
1124impl RawCommand {
1125    pub fn new<S>(line: S) -> Self
1126    where
1127        S: ToString,
1128    {
1129        Self {
1130            line: line.to_string(),
1131            transfers: vec![],
1132        }
1133    }
1134}
1135
1136impl ToString for RawCommand {
1137    fn to_string(&self) -> String {
1138        self.line.clone()
1139    }
1140}
1141
1142#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
1143pub struct CmdTransfer {
1144    pub id: String,
1145    pub content: Bin,
1146}
1147
1148impl CmdTransfer {
1149    pub fn new<N: ToString>(id: N, content: Bin) -> Self {
1150        Self {
1151            id: id.to_string(),
1152            content,
1153        }
1154    }
1155}