1use core::fmt::Formatter;
2use core::str::FromStr;
3use std::ops::Deref;
4
5use nom::combinator::all_consuming;
6use serde::de::{Error, Visitor};
7use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
8
9use cosmic_nom::{new_span, Trace};
10use specific::{ProductSelector, ProviderSelector, VariantSelector, VendorSelector};
11
12use crate::kind::{BaseKind, Kind, KindParts, Specific};
13use crate::loc::{
14 Layer, ToBaseKind, Topic, Variable, VarVal, Version,
15};
16use crate::parse::error::result;
17use crate::parse::{
18 CamelCase, consume_hierarchy, Env, kind_selector, point_segment_selector,
19 point_selector, specific_selector,
20};
21use crate::substance::{
22 CallWithConfigDef, Substance, SubstanceFormat, SubstanceKind, SubstancePattern,
23 SubstancePatternCtx, SubstancePatternDef,
24};
25use crate::util::{ToResolved, ValueMatcher, ValuePattern};
26use crate::SpaceErr;
27use crate::point::{Point, PointCtx, PointSeg, PointVar, RouteSeg};
28
29pub type KindSelector = KindSelectorDef<KindBaseSelector, SubKindSelector, SpecificSelector>;
30pub type KindSelectorVar =
31 KindSelectorDef<VarVal<KindBaseSelector>, VarVal<SubKindSelector>, VarVal<SpecificSelector>>;
32
33#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, Hash)]
34pub struct KindSelectorDef<GenericKindSelector, GenericSubKindSelector, SpecificSelector> {
35 pub base: GenericKindSelector,
36 pub sub: GenericSubKindSelector,
37 pub specific: ValuePattern<SpecificSelector>,
38}
39
40impl KindSelector {
41 pub fn new(
42 kind: KindBaseSelector,
43 sub_kind: SubKindSelector,
44 specific: ValuePattern<SpecificSelector>,
45 ) -> Self {
46 Self {
47 base: kind,
48 sub: sub_kind,
49 specific,
50 }
51 }
52
53 pub fn from_base(base: BaseKind) -> Self {
54 Self {
55 base: Pattern::Exact(base),
56 sub: SubKindSelector::Any,
57 specific: ValuePattern::Any,
58 }
59 }
60
61 pub fn matches(&self, kind: &Kind) -> bool
62 where
63 KindParts: Eq + PartialEq,
64 {
65 self.base.matches(&kind.to_base())
74 }
75
76 pub fn as_point_segments(&self) -> Result<String, SpaceErr> {
77 match &self.base {
78 KindBaseSelector::Any => Err(SpaceErr::server_error(
79 "cannot turn a base wildcard kind into point segments",
80 )),
81 KindBaseSelector::Exact(e) => Ok(e.to_skewer().to_string()),
82 }
83 }
84}
85
86impl FromStr for KindSelector {
87 type Err = SpaceErr;
88
89 fn from_str(s: &str) -> Result<Self, Self::Err> {
90 Ok(result(kind_selector(new_span(s)))?)
91 }
92}
93
94impl ToString for KindSelector {
95 fn to_string(&self) -> String {
96 format!(
97 "{}<{}<{}>>",
98 self.base.to_string(),
99 match &self.sub {
100 SubKindSelector::Any => "*".to_string(),
101 SubKindSelector::Exact(sub) => {
102 sub.as_ref().unwrap().to_string()
103 }
104 },
105 self.specific.to_string()
106 )
107 }
108}
109
110impl KindSelector {
111 pub fn any() -> Self {
112 Self {
113 base: KindBaseSelector::Any,
114 sub: SubKindSelector::Any,
115 specific: ValuePattern::Any,
116 }
117 }
118}
119
120pub type SubKindSelector = Pattern<Option<CamelCase>>;
121
122#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, Hash)]
123pub struct SelectorDef<Hop> {
124 pub hops: Vec<Hop>,
125}
126
127pub type Selector = SelectorDef<Hop>;
128pub type SelectorCtx = SelectorDef<Hop>;
129pub type SelectorVar = SelectorDef<Hop>;
130
131impl ToResolved<Selector> for Selector {
132 fn to_resolved(self, env: &Env) -> Result<Selector, SpaceErr> {
133 Ok(self)
134 }
135}
136
137impl FromStr for Selector {
138 type Err = SpaceErr;
139
140 fn from_str(s: &str) -> Result<Self, Self::Err> {
141 let (_, rtn) = all_consuming(point_selector)(new_span(s))?;
142 Ok(rtn)
143 }
144}
145
146impl Selector {
147 fn consume(&self) -> Option<Selector> {
148 if self.hops.is_empty() {
149 Option::None
150 } else {
151 let mut hops = self.hops.clone();
152 hops.remove(0);
153 Option::Some(Selector { hops })
154 }
155 }
156
157 pub fn matches_root(&self) -> bool {
158 if self.hops.is_empty() {
159 true
160 } else if self.hops.len() == 1 {
161 let hop = self.hops.first().unwrap();
162 if PointSegSelector::InclusiveAny == hop.segment_selector
163 || PointSegSelector::InclusiveRecursive == hop.segment_selector
164 {
165 hop.kind_selector.matches(&Kind::Root)
166 } else {
167 false
168 }
169 } else {
170 false
171 }
172 }
173
174 pub fn is_root(&self) -> bool {
175 self.hops.is_empty()
176 }
177
178 pub fn is_final(&self) -> bool {
179 self.hops.len() == 1
180 }
181
182 pub fn query_root(&self) -> Point {
183 let mut segments = vec![];
184 for hop in &self.hops {
185 if let PointSegSelector::Exact(exact) = &hop.segment_selector {
186 if hop.inclusive {
187 break;
188 }
189 match exact {
190 ExactPointSeg::PointSeg(seg) => {
191 segments.push(seg.clone());
192 }
193 ExactPointSeg::Version(version) => {
194 segments.push(PointSeg::Version(version.clone()));
195 }
196 }
197 } else {
198 break;
199 }
200 }
201
202 Point {
203 route: RouteSeg::This,
204 segments,
205 }
206 }
207
208 pub fn sub_select_hops(&self) -> Vec<Hop> {
209 let mut hops = self.hops.clone();
210 let query_root_segments = self.query_root().segments.len();
211 for _ in 0..query_root_segments {
212 hops.remove(0);
213 }
214 hops
215 }
216
217 pub fn matches(&self, hierarchy: &PointHierarchy) -> bool
218 where
219 BaseKind: Clone,
220 KindParts: Clone,
221 {
222 if hierarchy.is_root() && self.is_root() {
223 return true;
224 }
225
226 if hierarchy.segments.is_empty() || self.hops.is_empty() {
227 return false;
228 }
229
230 let hop = self.hops.first().expect("hop");
231 let seg = hierarchy.segments.first().expect("segment");
232
233 if hierarchy.is_final() && self.is_final() {
249 hop.matches(seg)
251 } else if hierarchy.is_root() {
252 false
253 } else if self.is_root() {
254 false
255 } else if hierarchy.is_final() {
256 if hop.inclusive && hop.matches(&seg) {
260 true
261 } else {
262 false
263 }
264 }
265 else if hop.segment_selector.is_recursive() && self.hops.len() >= 2 {
267 let next_hop = self.hops.get(1).expect("next<Hop>");
270 if next_hop.matches(seg) {
271 self.consume()
275 .expect("PointSelector")
276 .matches(&hierarchy.consume().expect("AddressKindPath"))
277 } else {
278 self.matches(&hierarchy.consume().expect("AddressKindPath"))
280 }
281 } else if hop.segment_selector.is_recursive() && hierarchy.is_final() {
282 hop.matches(hierarchy.segments.last().expect("segment"))
283 } else if hop.segment_selector.is_recursive() {
284 hop.matches(hierarchy.segments.last().expect("segment"))
285 && self.matches(&hierarchy.consume().expect("hierarchy"))
286 } else if hop.matches(seg) {
287 self.consume()
289 .expect("AddressTksPattern")
290 .matches(&hierarchy.consume().expect("AddressKindPath"))
291 } else {
292 false
293 }
294 }
295}
296
297impl ToString for Selector {
298 fn to_string(&self) -> String {
299 let mut rtn = String::new();
300 for (index, hop) in self.hops.iter().enumerate() {
301 rtn.push_str(hop.to_string().as_str());
302 if index < self.hops.len() - 1 {
303 rtn.push_str(":");
304 }
305 }
306 rtn
307 }
308}
309
310#[derive(Debug, Clone, Eq, PartialEq, Hash)]
311pub struct VersionReq {
312 pub version: semver::VersionReq,
313}
314
315impl Deref for VersionReq {
316 type Target = semver::VersionReq;
317
318 fn deref(&self) -> &Self::Target {
319 &self.version
320 }
321}
322
323impl Serialize for VersionReq {
324 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
325 where
326 S: Serializer,
327 {
328 serializer.serialize_str(self.version.to_string().as_str())
329 }
330}
331
332impl<'de> Deserialize<'de> for VersionReq {
333 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
334 where
335 D: Deserializer<'de>,
336 {
337 deserializer.deserialize_str(VersionReqVisitor)
338 }
339}
340
341struct VersionReqVisitor;
342
343impl<'de> Visitor<'de> for VersionReqVisitor {
344 type Value = VersionReq;
345
346 fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
347 formatter.write_str("SemVer version requirement")
348 }
349
350 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
351 where
352 E: de::Error,
353 {
354 match VersionReq::from_str(v) {
355 Ok(version) => Ok(version),
356 Err(error) => {
357 Err(de::Error::invalid_type(de::Unexpected::Str(v), &self))
359 }
360 }
361 }
362}
363
364impl ToString for VersionReq {
365 fn to_string(&self) -> String {
366 self.version.to_string()
367 }
368}
369
370impl TryInto<semver::VersionReq> for VersionReq {
371 type Error = SpaceErr;
372
373 fn try_into(self) -> Result<semver::VersionReq, Self::Error> {
374 Ok(self.version)
375 }
376}
377
378impl FromStr for VersionReq {
379 type Err = SpaceErr;
380
381 fn from_str(s: &str) -> Result<Self, Self::Err> {
382 let version = semver::VersionReq::from_str(s)?;
383 Ok(Self { version })
384 }
385}
386
387#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, Hash)]
388pub enum PointSegSelector {
389 InclusiveAny, InclusiveRecursive, Any, Recursive, Exact(ExactPointSeg),
394 Version(VersionReq),
395}
396
397#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, Hash)]
398pub enum PointSegSelectorVar {
399 InclusiveAny, InclusiveRecursive, Any, Recursive, Exact(ExactPointSeg),
404 Version(VersionReq),
405 Var(Variable),
406 Working(Trace),
407 Pop(Trace),
408}
409
410#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, Hash)]
411pub enum PointSegSelectorCtx {
412 InclusiveAny, InclusiveRecursive, Any, Recursive, Exact(ExactPointSeg),
417 Version(VersionReq),
418 Working(Trace),
419 Pop(Trace),
420}
421
422impl FromStr for PointSegSelector {
423 type Err = SpaceErr;
424
425 fn from_str(s: &str) -> Result<Self, Self::Err> {
426 result(all_consuming(point_segment_selector)(new_span(s)))
427 }
428}
429
430impl PointSegSelector {
431 pub fn is_exact(&self) -> bool {
432 match self {
433 PointSegSelector::Exact(_) => true,
434 _ => false,
435 }
436 }
437
438 pub fn matches(&self, segment: &PointSeg) -> bool {
439 match self {
440 PointSegSelector::InclusiveAny => true,
441 PointSegSelector::InclusiveRecursive => true,
442 PointSegSelector::Any => true,
443 PointSegSelector::Recursive => true,
444 PointSegSelector::Exact(exact) => {
445 match exact {
446 ExactPointSeg::PointSeg(pattern) => {
447 pattern.to_string() == segment.to_string()
448 },
449 ExactPointSeg::Version(a) => {
450 if let PointSeg::Version(b) = segment {
451 *a == *b
452 } else {
453 false
454 }
455 }
456 }},
457 PointSegSelector::Version(req) => {
458 if let PointSeg::Version(b) = segment {
459 req.matches(b)
460 } else {
461 false
462 }
463 }
464 }
465 }
466
467 pub fn is_recursive(&self) -> bool {
468 match self {
469 PointSegSelector::InclusiveAny => false,
470 PointSegSelector::InclusiveRecursive => true,
471 PointSegSelector::Any => false,
472 PointSegSelector::Recursive => true,
473 PointSegSelector::Exact(_) => false,
474 PointSegSelector::Version(_) => false,
475 }
476 }
477}
478
479impl ToString for PointSegSelector {
480 fn to_string(&self) -> String {
481 match self {
482 PointSegSelector::InclusiveAny => "+:*".to_string(),
483 PointSegSelector::InclusiveRecursive => "+:**".to_string(),
484 PointSegSelector::Any => "*".to_string(),
485 PointSegSelector::Recursive => "**".to_string(),
486 PointSegSelector::Exact(exact) => exact.to_string(),
487 PointSegSelector::Version(version) => version.to_string(),
488 }
489 }
490}
491
492pub type KeySegment = String;
493
494#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Hash)]
495pub enum ExactPointSeg {
496 PointSeg(PointSeg),
497 Version(Version),
498}
499
500impl ExactPointSeg {
501 pub fn matches(&self, segment: &PointSeg) -> bool {
502 match self {
503 ExactPointSeg::PointSeg(s) => *s == *segment,
504 ExactPointSeg::Version(a) => {
505 if let PointSeg::Version(b) = segment {
506 *a == *b
507 } else {
508 false
509 }
510 }
511 }
512 }
513}
514
515impl ToString for ExactPointSeg {
516 fn to_string(&self) -> String {
517 match self {
518 ExactPointSeg::PointSeg(point) => point.to_string(),
519 ExactPointSeg::Version(version) => version.to_string(),
520 }
521 }
522}
523
524pub type SpecificSelector = SpecificSelectorDef<
531 ProviderSelector,
532 VendorSelector,
533 ProductSelector,
534 VariantSelector,
535 VersionReq,
536>;
537
538impl FromStr for SpecificSelector {
539 type Err = SpaceErr;
540
541 fn from_str(s: &str) -> Result<Self, Self::Err> {
542 result(all_consuming(specific_selector)(new_span(s)))
543 }
544}
545
546#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, Hash)]
547pub struct SpecificSelectorDef<
548 ProviderSelector,
549 VendorSelector,
550 ProductSelector,
551 VariantSelector,
552 VersionReq,
553> {
554 pub provider: ProviderSelector,
555 pub vendor: VendorSelector,
556 pub product: ProductSelector,
557 pub variant: VariantSelector,
558 pub version: VersionReq,
559}
560
561impl ValueMatcher<Specific> for SpecificSelector {
562 fn is_match(&self, specific: &Specific) -> Result<(), ()> {
563 if self.provider.matches(&specific.provider)
564 && self.vendor.matches(&specific.vendor)
565 && self.product.matches(&specific.product)
566 && self.variant.matches(&specific.variant)
567 && self.version.matches(&specific.version)
568 {
569 Ok(())
570 } else {
571 Err(())
572 }
573 }
574}
575
576impl ToString for SpecificSelector {
577 fn to_string(&self) -> String {
578 format!(
579 "{}:{}:{}:({})",
580 self.vendor.to_string(),
581 self.product.to_string(),
582 self.variant.to_string(),
583 self.version.to_string()
584 )
585 }
586}
587
588pub mod specific {
589 use alloc::string::String;
590 use core::ops::Deref;
591 use core::str::FromStr;
592
593 use crate::err::SpaceErr;
594 use crate::parse::{Domain, SkewerCase};
595 use crate::selector::Pattern;
596
597 pub struct VersionReq {
598 pub req: semver::VersionReq,
599 }
600
601 impl Deref for VersionReq {
602 type Target = semver::VersionReq;
603
604 fn deref(&self) -> &Self::Target {
605 &self.req
606 }
607 }
608
609 impl FromStr for VersionReq {
610 type Err = SpaceErr;
611
612 fn from_str(s: &str) -> Result<Self, Self::Err> {
613 Ok(VersionReq {
614 req: semver::VersionReq::from_str(s)?,
615 })
616 }
617 }
618
619 pub type ProviderSelector = Pattern<Domain>;
620 pub type VendorSelector = Pattern<Domain>;
621 pub type ProductSelector = Pattern<SkewerCase>;
622 pub type VariantSelector = Pattern<SkewerCase>;
623 pub type VersionPattern = Pattern<VersionReq>;
624}
625
626pub type LabeledPrimitiveType = LabeledPrimitiveTypeDef<Point>;
627pub type LabeledPrimitiveTypeCtx = LabeledPrimitiveTypeDef<PointCtx>;
628pub type LabeledPrimitiveTypeVar = LabeledPrimitiveTypeDef<PointVar>;
629
630pub struct LabeledPrimitiveTypeDef<Pnt> {
631 pub label: String,
632 pub def: PayloadType2Def<Pnt>,
633}
634
635pub type PayloadType2 = PayloadType2Def<Point>;
636pub type PayloadType2Ctx = PayloadType2Def<PointCtx>;
637pub type PayloadType2Var = PayloadType2Def<PointVar>;
638
639pub struct PayloadType2Def<Pnt> {
640 pub primitive: SubstanceKind,
641 pub format: Option<SubstanceFormat>,
642 pub verifier: Option<CallWithConfigDef<Pnt>>,
643}
644
645#[derive(Debug, Clone, strum_macros::Display, strum_macros::EnumString, Eq, PartialEq)]
646pub enum Format {
647 #[strum(serialize = "json")]
648 Json,
649 #[strum(serialize = "image")]
650 Image,
651}
652
653#[derive(Debug, Clone, strum_macros::Display, strum_macros::EnumString, Eq, PartialEq)]
654pub enum PipelineKind {
655 Rc,
656 Ext,
657 Http,
658}
659
660pub struct ParsedPipelineBlock {}
661
662pub type MapEntryPatternVar = MapEntryPatternDef<PointVar>;
663pub type MapEntryPatternCtx = MapEntryPatternDef<PointCtx>;
664pub type MapEntryPattern = MapEntryPatternDef<Point>;
665
666#[derive(Clone)]
667pub struct MapEntryPatternDef<Pnt> {
668 pub key: String,
669 pub payload: ValuePattern<SubstancePatternDef<Pnt>>,
670}
671
672pub type Hop = HopDef<PointSegSelector, KindSelector>;
673pub type HopCtx = HopDef<PointSegSelectorCtx, KindSelector>;
674pub type HopVar = HopDef<PointSegSelectorVar, KindSelectorVar>;
675
676#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, Hash)]
677pub struct HopDef<Segment, KindSelector> {
678 pub inclusive: bool,
679 pub segment_selector: Segment,
680 pub kind_selector: KindSelector,
681}
682
683impl Hop {
684 pub fn matches(&self, point_kind_segment: &PointKindSeg) -> bool {
685self.segment_selector.matches(&point_kind_segment.segment)
691 && self.kind_selector.matches(&point_kind_segment.kind)
692 }
693}
694
695impl ToString for Hop {
696 fn to_string(&self) -> String {
697 let mut rtn = String::new();
698 rtn.push_str(self.segment_selector.to_string().as_str());
699
700 if let Pattern::Exact(base) = &self.kind_selector.base {
701 rtn.push_str(format!("<{}", base.to_string()).as_str());
702 if let Pattern::Exact(sub) = &self.kind_selector.sub {
703 rtn.push_str(format!("<{}", sub.as_ref().unwrap().to_string()).as_str());
704 if let ValuePattern::Pattern(specific) = &self.kind_selector.specific {
705 rtn.push_str(format!("<{}", specific.to_string()).as_str());
706 rtn.push_str(">");
707 }
708 rtn.push_str(">");
709 }
710 rtn.push_str(">");
711 }
712
713 if self.inclusive {
714 rtn.push_str("+");
715 }
716
717 rtn
718 }
719}
720
721#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, Hash)]
722pub enum Pattern<P> {
723 Any,
724 Exact(P),
725}
726
727impl<I: ToString> Pattern<I> {
728 pub fn to_string_version(self) -> Pattern<String> {
729 match self {
730 Pattern::Any => Pattern::Any,
731 Pattern::Exact(exact) => Pattern::Exact(exact.to_string()),
732 }
733 }
734}
735
736impl<P> Pattern<P>
737where
738 P: Eq + PartialEq,
739{
740 pub fn is_any(&self) -> bool {
741 match self {
742 Pattern::Any => true,
743 Pattern::Exact(_) => false,
744 }
745 }
746
747 pub fn matches(&self, t: &P) -> bool {
748 match self {
749 Self::Any => true,
750 Self::Exact(p) => *p == *t,
751 }
752 }
753 pub fn matches_opt(&self, other: Option<&P>) -> bool {
754 match self {
755 Self::Any => true,
756 Self::Exact(exact) => {
757 if let Option::Some(other) = other {
758 *exact == *other
759 } else {
760 false
761 }
762 }
763 }
764 }
765
766 pub fn convert<To>(self) -> Result<Pattern<To>, SpaceErr>
767 where
768 P: TryInto<To, Error = SpaceErr> + Eq + PartialEq,
769 {
770 Ok(match self {
771 Pattern::Any => Pattern::Any,
772 Pattern::Exact(exact) => Pattern::Exact(exact.try_into()?),
773 })
774 }
775}
776
777impl<P> ToString for Pattern<P>
778where
779 P: ToString,
780{
781 fn to_string(&self) -> String {
782 match self {
783 Pattern::Any => "*".to_string(),
784 Pattern::Exact(exact) => exact.to_string(),
785 }
786 }
787}
788
789#[derive(Debug, Clone, Serialize, Deserialize)]
790pub enum EmptyPattern<P> {
791 Any,
792 Pattern(P),
793}
794
795impl<P> EmptyPattern<P>
796where
797 P: Eq + PartialEq,
798{
799 pub fn matches(&self, t: &P) -> bool {
800 match self {
801 Self::Any => true,
802 Self::Pattern(p) => *p == *t,
803 }
804 }
805 pub fn matches_opt(&self, other: Option<&P>) -> bool {
806 match self {
807 Self::Any => true,
808 Self::Pattern(exact) => {
809 if let Option::Some(other) = other {
810 *exact == *other
811 } else {
812 false
813 }
814 }
815 }
816 }
817
818 pub fn convert<To>(self) -> Result<EmptyPattern<To>, SpaceErr>
819 where
820 P: TryInto<To, Error = SpaceErr> + Eq + PartialEq,
821 {
822 Ok(match self {
823 EmptyPattern::Any => EmptyPattern::Any,
824 EmptyPattern::Pattern(exact) => EmptyPattern::Pattern(exact.try_into()?),
825 })
826 }
827}
828
829impl Into<EmptyPattern<String>> for EmptyPattern<&str> {
830 fn into(self) -> EmptyPattern<String> {
831 match self {
832 EmptyPattern::Any => EmptyPattern::Any,
833 EmptyPattern::Pattern(f) => EmptyPattern::Pattern(f.to_string()),
834 }
835 }
836}
837
838impl<P> ToString for EmptyPattern<P>
839where
840 P: ToString,
841{
842 fn to_string(&self) -> String {
843 match self {
844 EmptyPattern::Any => "".to_string(),
845 EmptyPattern::Pattern(exact) => exact.to_string(),
846 }
847 }
848}
849
850pub type KindBaseSelector = Pattern<BaseKind>;
851
852#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
853pub struct PortHierarchy {
854 pub topic: Topic,
855 pub layer: Layer,
856 pub point_hierarchy: PointHierarchy,
857}
858
859impl PortHierarchy {
860 pub fn new(point_hierarchy: PointHierarchy, layer: Layer, topic: Topic) -> Self {
861 Self {
862 topic,
863 layer,
864 point_hierarchy,
865 }
866 }
867}
868
869#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
870pub struct PointHierarchy {
871 pub route: RouteSeg,
872 pub segments: Vec<PointKindSeg>,
873}
874
875impl PointHierarchy {
876 pub fn new(route: RouteSeg, segments: Vec<PointKindSeg>) -> Self {
877 Self { route, segments }
878 }
879}
880
881impl PointHierarchy {
882 pub fn push(&self, segment: PointKindSeg) -> PointHierarchy
883 where
884 KindParts: Clone,
885 BaseKind: Clone,
886 {
887 if let PointSeg::Root = segment.segment {
888 println!("pushing ROOT");
889 }
890 let mut segments = self.segments.clone();
891 segments.push(segment);
892 Self {
893 route: self.route.clone(),
894 segments,
895 }
896 }
897}
898
899impl PointHierarchy {
900 pub fn consume(&self) -> Option<PointHierarchy> {
901 if self.segments.len() <= 1 {
902 return Option::None;
903 }
904 let mut segments = self.segments.clone();
905 segments.remove(0);
906 Option::Some(PointHierarchy {
907 route: self.route.clone(),
908 segments,
909 })
910 }
911
912 pub fn is_root(&self) -> bool {
913 self.segments.is_empty()
914 }
915
916 pub fn is_final(&self) -> bool {
917 self.segments.len() == 1
918 }
919}
920
921impl ToString for PointHierarchy {
922 fn to_string(&self) -> String {
923 let mut rtn = String::new();
924 match &self.route {
925 RouteSeg::This => {}
926 route => {
927 rtn.push_str(route.to_string().as_str());
928 rtn.push_str("::");
929 }
930 }
931
932 let mut post_fileroot = false;
933 for (index, segment) in self.segments.iter().enumerate() {
934 if let PointSeg::FilesystemRootDir = segment.segment {
935 post_fileroot = true;
936 }
937 rtn.push_str(segment.segment.preceding_delim(post_fileroot));
938 rtn.push_str(segment.to_string().as_str());
939 }
940
941 rtn
942 }
943}
944
945#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
946pub struct PointKindSeg {
947 pub segment: PointSeg,
948 pub kind: Kind,
949}
950
951impl ToString for PointKindSeg {
952 fn to_string(&self) -> String {
953 format!("{}<{}>", self.segment.to_string(), self.kind.to_string())
954 }
955}
956
957impl FromStr for PointHierarchy {
958 type Err = SpaceErr;
959
960 fn from_str(s: &str) -> Result<Self, Self::Err> {
961 Ok(consume_hierarchy(new_span(s))?)
962 }
963}
964
965pub type PayloadBlock = PayloadBlockDef<Point>;
966pub type PayloadBlockCtx = PayloadBlockDef<PointCtx>;
967pub type PayloadBlockVar = PayloadBlockDef<PointVar>;
968
969impl ToResolved<PayloadBlockCtx> for PayloadBlockVar {
970 fn to_resolved(self, env: &Env) -> Result<PayloadBlockCtx, SpaceErr> {
971 match self {
972 PayloadBlockVar::DirectPattern(block) => Ok(PayloadBlockCtx::DirectPattern(
973 block.modify(move |block| {
974 let block: SubstancePatternCtx = block.to_resolved(env)?;
975 Ok(block)
976 })?,
977 )),
978 PayloadBlockVar::ReflectPattern(block) => Ok(PayloadBlockCtx::ReflectPattern(
979 block.modify(move |block| block.to_resolved(env))?,
980 )),
981 }
982 }
983}
984
985#[derive(Debug, Clone, Serialize, Deserialize)]
986pub struct UploadBlock {
987 pub name: String,
988}
989
990#[derive(Debug, Clone, Serialize, Deserialize)]
991pub struct CreateBlock {
992 pub payload: Substance,
993}
994
995pub type PatternBlock = PatternBlockDef<Point>;
996pub type PatternBlockCtx = PatternBlockDef<PointCtx>;
997pub type PatternBlockVar = PatternBlockDef<PointVar>;
998pub type PatternBlockDef<Pnt> = ValuePattern<SubstancePatternDef<Pnt>>;
999
1000impl ToResolved<PatternBlock> for PatternBlockCtx {
1001 fn to_resolved(self, env: &Env) -> Result<PatternBlock, SpaceErr> {
1002 match self {
1003 PatternBlockCtx::Any => Ok(PatternBlock::Any),
1004 PatternBlockCtx::None => Ok(PatternBlock::None),
1005 PatternBlockCtx::Pattern(pattern) => {
1006 Ok(PatternBlock::Pattern(pattern.to_resolved(env)?))
1007 }
1008 }
1009 }
1010}
1011
1012impl ToResolved<PatternBlockCtx> for PatternBlockVar {
1013 fn to_resolved(self, env: &Env) -> Result<PatternBlockCtx, SpaceErr> {
1014 match self {
1015 PatternBlockVar::Any => Ok(PatternBlockCtx::Any),
1016 PatternBlockVar::None => Ok(PatternBlockCtx::None),
1017 PatternBlockVar::Pattern(pattern) => {
1018 Ok(PatternBlockCtx::Pattern(pattern.to_resolved(env)?))
1019 }
1020 }
1021 }
1022}
1023
1024#[derive(Debug, Clone)]
1025pub enum PayloadBlockDef<Pnt> {
1026 DirectPattern(PatternBlockDef<Pnt>),
1027 ReflectPattern(PatternBlockDef<Pnt>),
1028}
1029
1030impl ToResolved<PayloadBlock> for PayloadBlockCtx {
1031 fn to_resolved(self, env: &Env) -> Result<PayloadBlock, SpaceErr> {
1032 match self {
1033 PayloadBlockCtx::DirectPattern(block) => {
1034 Ok(PayloadBlock::DirectPattern(block.modify(move |block| {
1035 let block: SubstancePattern = block.to_resolved(env)?;
1036 Ok(block)
1037 })?))
1038 }
1039 PayloadBlockCtx::ReflectPattern(block) => Ok(PayloadBlock::ReflectPattern(
1040 block.modify(move |block| block.to_resolved(env))?,
1041 )),
1042 }
1043 }
1044}
1045
1046impl ToResolved<PayloadBlock> for PayloadBlockVar {
1047 fn to_resolved(self, env: &Env) -> Result<PayloadBlock, SpaceErr> {
1048 let block: PayloadBlockCtx = self.to_resolved(env)?;
1049 block.to_resolved(env)
1050 }
1051}