cosmic_space/
parse.rs

1pub mod point;
2
3use core::fmt;
4use core::fmt::Display;
5use std::collections::HashMap;
6use std::convert::{TryFrom, TryInto};
7use std::fmt::Formatter;
8use std::marker::PhantomData;
9use std::ops;
10use std::ops::{Deref, Range, RangeFrom, RangeTo};
11use std::rc::Rc;
12use std::str::FromStr;
13use std::sync::Arc;
14
15//use ariadne::{Label, Report, ReportKind};
16use nom::branch::alt;
17use nom::bytes::complete::take;
18use nom::bytes::complete::{escaped, is_a, is_not};
19use nom::bytes::complete::{tag, take_till, take_until, take_until1, take_while};
20use nom::character::complete::{
21    alpha0, alphanumeric0, alphanumeric1, anychar, char, digit0, line_ending, multispace0,
22    multispace1, newline, one_of, satisfy, space0, space1,
23};
24use nom::character::complete::{alpha1, digit1};
25use nom::character::is_space;
26use nom::combinator::{all_consuming, opt};
27use nom::combinator::{cut, eof, fail, not, peek, recognize, success, value, verify};
28use nom::error::{context, ContextError, ErrorKind, ParseError, VerboseError};
29use nom::multi::{many0, many1, separated_list0};
30use nom::sequence::{delimited, pair, preceded, terminated, tuple};
31use nom::{
32    AsChar, Compare, FindToken, InputIter, InputLength, InputTake, InputTakeAtPosition, Offset,
33    Parser, Slice,
34};
35use nom::{Err, IResult};
36use nom_locate::LocatedSpan;
37use nom_supreme::error::ErrorTree;
38use nom_supreme::final_parser::ExtractContext;
39use nom_supreme::parser_ext::MapRes;
40use nom_supreme::{parse_from_str, ParserExt};
41use regex::{Captures, Error, Match, Regex};
42use serde::{Deserialize, Deserializer, Serialize, Serializer};
43
44use cosmic_nom::{new_span, span_with_extra, Trace};
45use cosmic_nom::{Res, Span, trim, tw, Wrap};
46
47use crate::command::common::{PropertyMod, SetProperties, StateSrc, StateSrcVar};
48use crate::command::direct::create::{
49    Create, CreateVar, KindTemplate, PointSegTemplate, PointTemplate, PointTemplateSeg,
50    PointTemplateVar, Require, Strategy, Template, TemplateVar,
51};
52use crate::command::direct::get::{Get, GetOp, GetVar};
53use crate::command::direct::select::{Select, SelectIntoSubstance, SelectKind, SelectVar};
54use crate::command::direct::set::{Set, SetVar};
55use crate::command::direct::CmdKind;
56use crate::command::CommandVar;
57use crate::config::bind::{
58    BindConfig, Pipeline, PipelineStep, PipelineStepCtx, PipelineStepVar, PipelineStop,
59    PipelineStopCtx, PipelineStopVar, RouteSelector, WaveDirection,
60};
61use crate::config::mechtron::MechtronConfig;
62use crate::config::Document;
63use crate::err::report::{Label, Report, ReportKind};
64use crate::err::{ParseErrs, SpaceErr};
65use crate::kind::{
66    ArtifactSubKind, BaseKind, DatabaseSubKind, FileSubKind, Kind, KindParts, NativeSub, Specific,
67    StarSub, UserBaseSubKind,
68};
69use crate::loc::StarKey;
70use crate::loc::{
71    Layer, PointSegment,
72    Surface, Topic, Uuid, Variable, VarVal, Version,
73};
74use crate::parse::error::{find_parse_err, result};
75use crate::parse::model::{
76    BindScope, BindScopeKind, Block, BlockKind, Chunk, DelimitedBlockKind, LexBlock,
77    LexParentScope, LexRootScope, LexScope, LexScopeSelector, LexScopeSelectorAndFilters,
78    MechtronScope, MessageScopeSelectorAndFilters, NestedBlockKind, PipelineCtx, PipelineSegment,
79    PipelineSegmentCtx, PipelineSegmentVar, PipelineVar, RootScopeSelector, RouteScope,
80    ScopeFilterDef, ScopeFilters, ScopeFiltersDef, ScopeSelectorAndFiltersDef, Spanned, Subst,
81    TerminatedBlockKind, TextType, Var, VarParser,
82};
83use crate::particle::{PointKind, PointKindVar};
84use crate::point::{Point, PointCtx, PointSeg, PointSegCtx, PointSegDelim, PointSegVar, PointVar, RouteSeg, RouteSegVar};
85use crate::security::{
86    AccessGrantKind, AccessGrantKindDef, ChildPerms, ParticlePerms, Permissions, PermissionsMask,
87    PermissionsMaskKind, Privilege,
88};
89use crate::selector::specific::{ProductSelector, VariantSelector, VendorSelector};
90use crate::selector::{
91    ExactPointSeg, Hop, KindBaseSelector, KindSelector, LabeledPrimitiveTypeDef, MapEntryPattern,
92    MapEntryPatternCtx, MapEntryPatternVar, Pattern, PatternBlock, PatternBlockCtx,
93    PatternBlockVar, PayloadBlock, PayloadBlockCtx, PayloadBlockVar, PayloadType2Def,
94    PointHierarchy, PointKindSeg, PointSegSelector, Selector, SelectorDef, SpecificSelector,
95    SubKindSelector, UploadBlock, VersionReq,
96};
97use crate::substance::Bin;
98use crate::substance::{
99    Call, CallCtx, CallKind, CallVar, CallWithConfig, CallWithConfigCtx, CallWithConfigVar,
100    ExtCall, HttpCall, ListPattern, MapPattern, MapPatternCtx, MapPatternVar, NumRange, Substance,
101    SubstanceFormat, SubstanceKind, SubstancePattern, SubstancePatternCtx, SubstancePatternVar,
102    SubstanceTypePatternCtx, SubstanceTypePatternDef, SubstanceTypePatternVar,
103};
104use crate::util::{HttpMethodPattern, StringMatcher, ToResolved, ValuePattern};
105use crate::wave::core::cmd::CmdMethod;
106use crate::wave::core::ext::ExtMethod;
107use crate::wave::core::http2::HttpMethod;
108use crate::wave::core::hyp::HypMethod;
109use crate::wave::core::MethodKind;
110use crate::wave::core::{Method, MethodPattern};
111
112/*
113pub struct Parser {}
114
115impl Parser {
116    pub fn point(input: Span) -> Res<Span, Point> {
117        point_subst(input)
118    }
119
120    pub fn consume_point(input: Span) -> Result<Point, ExtErr> {
121        let (_, point) = all_consuming(point_subst)(input)?;
122        Ok(point)
123    }
124}
125 */
126
127fn any_resource_path_segment<T>(i: T) -> Res<T, T>
128where
129    T: InputTakeAtPosition + nom::InputLength,
130    <T as InputTakeAtPosition>::Item: AsChar,
131{
132    i.split_at_position1_complete(
133        |item| {
134            let char_item = item.as_char();
135            !(char_item == '-')
136                && !(char_item == '.')
137                && !(char_item == '/')
138                && !(char_item == '_')
139                && !(char_item.is_alpha() || char_item.is_dec_digit())
140        },
141        ErrorKind::AlphaNumeric,
142    )
143}
144
145fn sys_route_chars<T>(i: T) -> Res<T, T>
146where
147    T: InputTakeAtPosition + nom::InputLength,
148    <T as InputTakeAtPosition>::Item: AsChar,
149{
150    i.split_at_position1_complete(
151        |item| {
152            let char_item = item.as_char();
153            !(char_item == '-')
154                && !(char_item == '.')
155                && !(char_item == '/')
156                && !(char_item == '_')
157                && !(char_item == ':')
158                && !(char_item == '(')
159                && !(char_item == ')')
160                && !(char_item == '[')
161                && !(char_item == ']')
162                && !(char_item.is_alpha() || char_item.is_dec_digit())
163        },
164        ErrorKind::AlphaNumeric,
165    )
166}
167
168pub fn this_route_segment<I: Span>(input: I) -> Res<I, RouteSeg> {
169    alt((recognize(tag(".")), recognize(not(other_route_segment))))(input)
170        .map(|(next, _)| (next, RouteSeg::This))
171}
172
173pub fn local_route_segment<I: Span>(input: I) -> Res<I, RouteSeg> {
174    tag("LOCAL")(input).map(|(next, _)| (next, RouteSeg::Local))
175}
176
177pub fn remote_route_segment<I: Span>(input: I) -> Res<I, RouteSeg> {
178    tag("REMOTE")(input).map(|(next, _)| (next, RouteSeg::Remote))
179}
180
181pub fn global_route_segment<I: Span>(input: I) -> Res<I, RouteSeg> {
182    tag("GLOBAL")(input).map(|(next, _)| (next, RouteSeg::Global))
183}
184
185pub fn domain_route_segment<I: Span>(input: I) -> Res<I, RouteSeg> {
186    domain_chars(input).map(|(next, domain)| (next, RouteSeg::Domain(domain.to_string())))
187}
188
189pub fn tag_route_segment<I: Span>(input: I) -> Res<I, RouteSeg> {
190    delimited(tag("["), skewer_chars, tag("]"))(input)
191        .map(|(next, tag)| (next, RouteSeg::Tag(tag.to_string())))
192}
193
194pub fn sys_route_segment<I: Span>(input: I) -> Res<I, RouteSeg> {
195    delimited(tag("<<"), sys_route_chars, tag(">>"))(input)
196        .map(|(next, tag)| (next, RouteSeg::Star(tag.to_string())))
197}
198
199pub fn other_route_segment<I: Span>(input: I) -> Res<I, RouteSeg> {
200    alt((
201        sys_route_segment,
202        tag_route_segment,
203        domain_route_segment,
204        global_route_segment,
205        local_route_segment,
206        remote_route_segment,
207    ))(input)
208}
209
210pub fn point_route_segment<I: Span>(input: I) -> Res<I, RouteSeg> {
211    alt((this_route_segment, other_route_segment))(input)
212}
213
214/*
215pub fn point_segment(input: Span) -> Res<Span, PointSegCtx> {
216    alt((
217        base_point_segment,
218        space_point_segment,
219        version_point_segment,
220        filesystem_point_segment,
221        file_point_segment,
222    ))(input)
223}
224
225 */
226
227pub fn mesh_eos<I: Span>(input: I) -> Res<I, I> {
228    peek(alt((tag(":"), eop)))(input)
229}
230
231pub fn fs_trailing<I: Span>(input: I) -> Res<I, I> {
232    peek(pair(
233        recognize(tag(":")),
234        context("point:version:root_not_trailing", cut(tag("/"))),
235    ))(input)
236    .map(|(next, (rtn, _))| (next, rtn))
237}
238
239// version end of segment
240pub fn ver_eos<I: Span>(input: I) -> Res<I, I> {
241    peek(alt((fs_trailing, tag(":/"), eop)))(input)
242}
243
244// end of point
245pub fn eop<I: Span>(input: I) -> Res<I, I> {
246    peek(alt((
247        eof,
248        multispace1,
249        tag("<"),
250        tag("\""),
251        tag("'"),
252        tag("]"),
253        tag(")"),
254        tag("}"),
255        tag("^"),
256        tag("["),
257        tag("("),
258        tag("{"),
259        tag("%"),
260    )))(input)
261}
262
263pub fn space_no_dupe_dots<I: Span>(input: I) -> Res<I, ()> {
264    context(
265        "point:space_segment:dot_dupes",
266        peek(cut(not(take_until("..")))),
267    )(input)
268    .map(|(next, _)| (next, ()))
269}
270
271pub fn space_point_segment<I: Span>(input: I) -> Res<I, PointSeg> {
272    context(
273        "point:space_segment",
274        cut(pair(
275            recognize(tuple((
276                context("point:space_segment_leading", peek(alpha1)),
277                space_no_dupe_dots,
278                space_chars,
279            ))),
280            mesh_eos,
281        )),
282    )(input)
283    .map(|(next, (space, x))| (next, PointSeg::Space(space.to_string())))
284}
285
286pub fn base_point_segment<I: Span>(input: I) -> Res<I, PointSeg> {
287    preceded(
288        peek(lowercase1),
289        context("point:base_segment", cut(pair(rec_skewer, mesh_eos))),
290    )(input)
291    .map(|(next, (base, _))| (next, PointSeg::Base(base.to_string())))
292}
293
294pub fn version_point_segment<I: Span>(input: I) -> Res<I, PointSeg> {
295    preceded(
296        peek(digit1),
297        context("point:version_segment", cut(tuple((version, ver_eos)))),
298    )(input)
299    .map(|(next, (version, _))| (next, PointSeg::Version(version)))
300}
301
302pub fn dir_pop<I: Span>(input: I) -> Res<I, PointSegVar> {
303    context("point:dir_pop", tuple((tag(".."), opt(tag("/")))))(input).map(|(next, _)| {
304        (
305            next.clone(),
306            PointSegVar::Pop(Trace {
307                range: next.location_offset() - 2..next.location_offset(),
308                extra: next.extra(),
309            }),
310        )
311    })
312}
313
314pub fn filesystem_point_segment<I: Span>(input: I) -> Res<I, PointSeg> {
315    tuple((
316        peek(not(eop)),
317        context(
318            "point:file_or_directory",
319            cut(alt((dir_point_segment, file_point_segment))),
320        ),
321    ))(input)
322    .map(|(next, (_, seg))| (next, seg))
323}
324
325pub fn dir_point_segment<I: Span>(input: I) -> Res<I, PointSeg> {
326    context("point:dir_segment", file_chars)(input)
327        .map(|(next, dir)| (next, PointSeg::Dir(dir.to_string())))
328}
329
330pub fn root_dir_point_segment<I: Span>(input: I) -> Res<I, PointSeg> {
331    context("point:root_filesystem_segment", tag(":/"))(input)
332        .map(|(next, _)| (next, PointSeg::FilesystemRootDir))
333}
334
335pub fn root_dir_point_segment_ctx<I: Span>(input: I) -> Res<I, PointSegVar> {
336    context("point:root_filesystem_segment", tag(":/"))(input)
337        .map(|(next, _)| (next, PointSegVar::FilesystemRootDir))
338}
339
340pub fn root_dir_point_segment_var<I: Span>(input: I) -> Res<I, PointSegVar> {
341    context("point:root_filesystem_segment", tag(":/"))(input)
342        .map(|(next, _)| (next, PointSegVar::FilesystemRootDir))
343}
344
345pub fn file_point_segment<I: Span>(input: I) -> Res<I, PointSeg> {
346    context("point:file_segment", file_chars)(input)
347        .map(|(next, filename)| (next, PointSeg::File(filename.to_string())))
348}
349
350pub fn point_var<I: Span>(input: I) -> Res<I, PointVar> {
351    context(
352        "point",
353        tuple((alt((root_point_var, point_non_root_var)), eop)),
354    )(input.clone())
355    .map(|(next, (point, _))| (next, point))
356}
357
358/*
359pub fn var<O,F,P>(mut f: F ) -> impl FnMut(I) -> Res<I,Var<O,P>> where F: Parser<I,O,ErrorTree<I>>, P: VarParser<O> {
360    move | input: I | {
361        let result = recognize(pair(peek(tag("$")),context("var",cut(delimited(tag("${"), skewer_case, tag("}") )))))(input.clone());
362        match result {
363            Ok((next,var)) => {
364                Ok( (next, Var::Var{ name: var.to_string(), parser: f }) )
365            }
366            Err(err) => {
367                match &err {
368                    Err::Incomplete(_) => {
369                        Err(err)
370                    }
371                    Err::Failure(_) => {
372                        Err(err)
373                    }
374                    // in this case the peek failed which means it is not a variable declaration
375                    Err::Error(_) => {
376                        let input = to_owned_span(&input);
377                        f.parse(input)
378                    }
379                }
380            }
381        }
382
383
384        let input = to_owned_span(&input);
385
386        input.parse(input)
387    }
388}
389
390 */
391
392pub fn var_val<F, I: Span, O>(mut f: F) -> impl FnMut(I) -> Res<I, VarVal<O>> + Copy
393where
394    F: FnMut(I) -> Res<I, O> + Copy,
395{
396    move |input: I| context("var_val", alt((var, val(f))))(input)
397}
398
399fn val<I: Span, O, F>(f: F) -> impl FnMut(I) -> Res<I, VarVal<O>>
400where
401    F: FnMut(I) -> Res<I, O> + Copy,
402{
403    move |input| tw(f)(input).map(|(next, val)| (next, VarVal::Val(val)))
404}
405
406fn var<I: Span, O>(input: I) -> Res<I, VarVal<O>> {
407    tw(delimited(tag("${"), skewer_case, tag("}")))(input)
408        .map(|(next, var)| (next, VarVal::Var(var)))
409}
410
411pub fn var_seg<F, I: Span>(mut f: F) -> impl FnMut(I) -> Res<I, PointSegVar> + Copy
412where
413    F: Parser<I, PointSegCtx, ErrorTree<I>> + Copy,
414{
415    move |input: I| {
416        let offset = input.location_offset();
417        let result = pair(
418            peek(tag("$")),
419            context(
420                "var",
421                cut(delimited(tag("${"), skewer_case_chars, tag("}"))),
422            ),
423        )(input.clone());
424
425        match result {
426            Ok((next, (_, var))) => {
427                let range = Range {
428                    start: offset,
429                    end: next.location_offset(),
430                };
431                let trace = Trace {
432                    range,
433                    extra: next.extra(),
434                };
435                let var = Variable::new(var.to_string(), trace);
436                Ok((next, PointSegVar::Var(var)))
437            }
438            Err(err) => match err {
439                Err::Incomplete(needed) => return Err(nom::Err::Incomplete(needed)),
440                Err::Failure(err) => return Err(nom::Err::Failure(err)),
441                Err::Error(_) => f.parse(input).map(|(next, seg)| (next, seg.into())),
442            },
443        }
444    }
445}
446
447pub fn var_route<'a, F, I: Span>(mut f: F) -> impl FnMut(I) -> Res<I, RouteSegVar>
448where
449    F: Parser<I, RouteSeg, ErrorTree<I>>,
450{
451    move |input: I| {
452        let offset = input.location_offset();
453        let result = pair(
454            peek(tag("$")),
455            context(
456                "var",
457                cut(delimited(tag("${"), skewer_case_chars, tag("}"))),
458            ),
459        )(input.clone());
460        match result {
461            Ok((next, (_, var))) => {
462                let range = Range {
463                    start: offset,
464                    end: next.location_offset(),
465                };
466                let trace = Trace {
467                    range,
468                    extra: next.extra(),
469                };
470                let var = Variable::new(var.to_string(), trace);
471                Ok((next, RouteSegVar::Var(var)))
472            }
473            Err(err) => f.parse(input).map(|(next, seg)| (next, seg.into())),
474        }
475    }
476}
477pub fn root_point_var<I: Span>(input: I) -> Res<I, PointVar> {
478    context(
479        "root_point",
480        tuple((
481            opt(terminated(var_route(point_route_segment), tag("::"))),
482            tag("ROOT"),
483        )),
484    )(input)
485    .map(|(next, (route, _))| {
486        let route = route.unwrap_or(RouteSegVar::This);
487        let point = PointVar {
488            route,
489            segments: vec![],
490        };
491        (next, point)
492    })
493}
494
495pub fn point_non_root_var<I: Span>(input: I) -> Res<I, PointVar> {
496    context(
497        "point_non_root",
498        tuple((
499            context(
500                "point_route",
501                opt(terminated(var_route(point_route_segment), tag("::"))),
502            ),
503            var_seg(root_ctx_seg(space_point_segment)),
504            many0(base_seg(var_seg(pop(base_point_segment)))),
505            opt(base_seg(var_seg(pop(version_point_segment)))),
506            opt(tuple((
507                root_dir_point_segment_var,
508                many0(recognize(tuple((
509                    var_seg(pop(dir_point_segment)),
510                    tag("/"),
511                )))),
512                opt(var_seg(pop(file_point_segment))),
513                eop,
514            ))),
515            eop,
516        )),
517    )(input)
518    .map(
519        |(next, (route, space, mut bases, version, filesystem, _))| {
520            let route = route.unwrap_or(RouteSegVar::This);
521            let mut segments = vec![];
522            let mut bases: Vec<PointSegVar> = bases;
523            segments.push(space);
524            segments.append(&mut bases);
525            match version {
526                None => {}
527                Some(version) => {
528                    segments.push(version);
529                }
530            }
531
532            if let Option::Some((fsroot, mut dirs, file, _)) = filesystem {
533                let mut dirs: Vec<PointSegVar> = dirs
534                    .into_iter()
535                    .map(|i| PointSegVar::Dir(i.to_string()))
536                    .collect();
537                segments.push(fsroot);
538                segments.append(&mut dirs);
539                if let Some(file) = file {
540                    segments.push(file);
541                }
542            }
543
544            let point = PointVar { route, segments };
545
546            (next, point)
547        },
548    )
549}
550
551pub fn consume_point(input: &str) -> Result<Point, SpaceErr> {
552    consume_point_ctx(input)?.collapse()
553}
554
555pub fn consume_point_ctx(input: &str) -> Result<PointCtx, SpaceErr> {
556    consume_point_var(input)?.collapse()
557}
558
559pub fn consume_point_var(input: &str) -> Result<PointVar, SpaceErr> {
560    let span = new_span(input);
561    let point = result(context("consume", all_consuming(point_var))(span))?;
562    Ok(point)
563}
564
565/*
566pub fn point_old(input: Span) -> Res<Span, Point> {
567    let (next, point) = point_subst(input.clone())?;
568    match point.brute_resolve() {
569        Ok(point) => Ok((next, point)),
570        Err(err) => {
571            let e = ErrorTree::from_error_kind(input.clone(), ErrorKind::Fail);
572            let e = ErrorTree::add_context(input, "point-subst-brute-force", e);
573            return Err(nom::Err::Failure(e));
574        }
575    }
576}
577
578 */
579
580/*pub fn capture_point(input: Span) -> Res<Span, CaptureAddress> {
581    context(
582        "Address",
583        tuple((
584            tuple((
585                point_route_segment,
586                alt((root_point_capture_segment, space_point_capture_segment)),
587            )),
588            many0(base_point_capture_segment),
589            opt(version_point_segment),
590            opt(root_dir_point_segment),
591            many0(filesystem_point_capture_segment),
592        )),
593    )(input)
594    .map(
595        |(next, ((hub, space), mut bases, version, root, mut files))| {
596            let mut segments = vec![];
597            segments.push(space);
598            segments.append(&mut bases);
599            match version {
600                None => {}
601                Some(version) => {
602                    segments.push(version);
603                }
604            }
605
606            if let Option::Some(root) = root {
607                segments.push(root);
608                segments.append(&mut files);
609            }
610
611            let point = CaptureAddress {
612                route: hub,
613                segments,
614            };
615
616            (next, point)
617        },
618    )
619}
620
621
622pub fn root_point_capture_segment(input: Span) -> Res<Span, PointSeg> {
623    tag("ROOT")(input).map(|(next, space)| (next, PointSeg::Root))
624}
625
626pub fn space_point_capture_segment(input: Span) -> Res<Span, PointSeg> {
627    space_chars_plus_capture(input).map(|(next, space)| (next, PointSeg::Space(space.to_string())))
628}
629
630pub fn base_point_capture_segment(input: Span) -> Res<Span, PointSeg> {
631    preceded(tag(":"), rec_skewer_capture)(input)
632        .map(|(next, base)| (next, PointSeg::Base(base.to_string())))
633}
634
635pub fn filesystem_point_capture_segment(input: Span) -> Res<Span, PointSeg> {
636    alt((dir_point_capture_segment, file_point_capture_segment))(input)
637}
638
639pub fn dir_point_capture_segment(input: Span) -> Res<Span, PointSeg> {
640    context(
641        "dir_point_capture_segment",
642        terminated(file_chars_plus_capture, tag("/")),
643    )(input)
644    .map(|(next, dir)| (next, PointSeg::Dir(format!("{}/", dir))))
645}
646
647pub fn file_point_capture_segment(input: Span) -> Res<Span, PointSeg> {
648    context("file_point_capture_segment", file_chars_plus_capture)(input)
649        .map(|(next, filename)| (next, PointSeg::File(filename.to_string())))
650}
651 */
652
653pub fn space_point_kind_segment<I: Span>(input: I) -> Res<I, PointKindSeg> {
654    tuple((space_point_segment, delim_kind))(input).map(|(next, (point_segment, kind))| {
655        (
656            next,
657            PointKindSeg {
658                segment: point_segment,
659                kind,
660            },
661        )
662    })
663}
664
665pub fn base_point_kind_segment<I: Span>(input: I) -> Res<I, PointKindSeg> {
666    tuple((base_point_segment, delim_kind))(input).map(|(next, (point_segment, kind))| {
667        (
668            next,
669            PointKindSeg {
670                segment: point_segment,
671                kind,
672            },
673        )
674    })
675}
676
677pub fn filepath_point_kind_segment<I: Span>(input: I) -> Res<I, PointKindSeg> {
678    alt((file_point_kind_segment, dir_point_kind_segment))(input)
679}
680pub fn dir_point_kind_segment<I: Span>(input: I) -> Res<I, PointKindSeg> {
681    tuple((dir_point_segment, delim_kind))(input).map(|(next, (point_segment, kind))| {
682        (
683            next,
684            PointKindSeg {
685                segment: point_segment,
686                kind,
687            },
688        )
689    })
690}
691
692pub fn file_point_kind_segment<I: Span>(input: I) -> Res<I, PointKindSeg> {
693    tuple((file_point_segment, delim_kind))(input).map(|(next, (point_segment, kind))| {
694        (
695            next,
696            PointKindSeg {
697                segment: point_segment,
698                kind,
699            },
700        )
701    })
702}
703
704pub fn version_point_kind_segment<I: Span>(input: I) -> Res<I, PointKindSeg> {
705    tuple((version_point_segment, delim_kind))(input).map(|(next, (point_segment, kind))| {
706        (
707            next,
708            PointKindSeg {
709                segment: point_segment,
710                kind,
711            },
712        )
713    })
714}
715
716pub fn consume_hierarchy<I: Span>(input: I) -> Result<PointHierarchy, SpaceErr> {
717    let (_, rtn) = all_consuming(point_kind_hierarchy)(input)?;
718    Ok(rtn)
719}
720
721pub fn point_kind_hierarchy<I: Span>(input: I) -> Res<I, PointHierarchy> {
722    tuple((
723        tuple((point_route_segment, space_point_kind_segment)),
724        many0(base_point_kind_segment),
725        opt(version_point_kind_segment),
726        many0(file_point_kind_segment),
727    ))(input)
728    .map(|(next, ((hub, space), mut bases, version, mut files))| {
729        let mut segments = vec![];
730        segments.push(space);
731        segments.append(&mut bases);
732        match version {
733            None => {}
734            Some(version) => {
735                segments.push(version);
736            }
737        }
738        segments.append(&mut files);
739
740        let point = PointHierarchy::new(hub, segments);
741
742        (next, point)
743    })
744}
745
746pub fn asterisk<T: Span, E: nom::error::ParseError<T>>(input: T) -> IResult<T, T, E>
747where
748    T: InputTakeAtPosition + nom::InputLength,
749    <T as InputTakeAtPosition>::Item: AsChar,
750{
751    input.split_at_position_complete(|item| item.as_char() != '*')
752}
753
754pub fn upper<T, E: nom::error::ParseError<T>>(input: T) -> IResult<T, T, E>
755where
756    T: InputTakeAtPosition + nom::InputLength,
757    <T as InputTakeAtPosition>::Item: AsChar,
758{
759    input.split_at_position_complete(|item| {
760        let char_item = item.as_char();
761
762        !char_item.is_uppercase()
763    })
764}
765
766/*    fn any_resource_path_segment<T>(i: T) -> Res<T, T>
767       where
768           T: InputTakeAtPosition+nom::InputLength,
769           <T as InputTakeAtPosition>::Item: AsChar,
770   {
771       i.split_at_position1_complete(
772           |item| {
773               let char_item = item.as_char();
774               !(char_item == '-')
775                   && !(char_item == '.')
776                   && !(char_item == '/')
777                   && !(char_item == '_')
778                   && !(char_item.is_alpha() || char_item.is_dec_digit())
779           },
780           ErrorKind::AlphaNumeric,
781       )
782   }
783
784*/
785
786pub fn in_double_quotes<T: Span>(i: T) -> Res<T, T>
787where
788    T: InputTakeAtPosition + nom::InputLength,
789    <T as InputTakeAtPosition>::Item: AsChar,
790{
791    i.split_at_position1_complete(
792        |item| {
793            let char_item = item.as_char();
794            char_item == '\"'
795        },
796        ErrorKind::AlphaNumeric,
797    )
798}
799
800pub fn skewer_colon<T: Span>(i: T) -> Res<T, T>
801where
802    T: InputTakeAtPosition + nom::InputLength,
803    <T as InputTakeAtPosition>::Item: AsChar,
804{
805    i.split_at_position1_complete(
806        |item| {
807            let char_item = item.as_char();
808            !(char_item == '-')
809                && !(char_item == ':')
810                && !((char_item.is_alpha() && char_item.is_lowercase()) || char_item.is_dec_digit())
811        },
812        ErrorKind::AlphaNumeric,
813    )
814}
815
816pub fn skewer_dot<I: Span, E>(i: I) -> IResult<I, I, E>
817where
818    I: InputTakeAtPosition + nom::InputLength,
819    <I as InputTakeAtPosition>::Item: AsChar,
820    E: nom::error::ContextError<I> + nom::error::ParseError<I>,
821{
822    i.split_at_position1_complete(
823        |item| {
824            let char_item = item.as_char();
825            !(char_item == '-')
826                && !(char_item == '.')
827                && !((char_item.is_alpha() && char_item.is_lowercase()) || char_item.is_dec_digit())
828        },
829        ErrorKind::AlphaNumeric,
830    )
831}
832
833pub fn domain<I: Span>(i: I) -> Res<I, Domain> {
834    domain_chars(i).map(|(next, domain)| {
835        (
836            next,
837            Domain {
838                string: domain.to_string(),
839            },
840        )
841    })
842}
843
844pub fn point_segment_chars<T: Span>(i: T) -> Res<T, T>
845where
846    T: InputTakeAtPosition + nom::InputLength,
847    <T as InputTakeAtPosition>::Item: AsChar,
848{
849    i.split_at_position1_complete(
850        |item| {
851            let char_item = item.as_char();
852            !(char_item == '-')
853                && !(char_item == '.')
854                && !(char_item.is_alpha() || char_item.is_dec_digit())
855        },
856        ErrorKind::AlphaNumeric,
857    )
858}
859
860pub fn version_chars<T: Span>(i: T) -> Res<T, T>
861where
862    T: InputTakeAtPosition + nom::InputLength,
863    <T as InputTakeAtPosition>::Item: AsChar,
864{
865    i.split_at_position1_complete(
866        |item| {
867            let char_item = item.as_char();
868            char_item != '.'
869                && char_item != '-'
870                && !char_item.is_digit(10)
871                && !(char_item.is_alpha() && char_item.is_lowercase())
872        },
873        ErrorKind::AlphaNumeric,
874    )
875}
876
877pub fn version_req_chars<T: Span>(i: T) -> Res<T, T>
878where
879    T: InputTakeAtPosition + nom::InputLength,
880    <T as InputTakeAtPosition>::Item: AsChar,
881{
882    i.split_at_position1_complete(
883        |item| {
884            let char_item = item.as_char();
885            !(char_item == '-')
886                && !(char_item == '>')
887                && !(char_item == '<')
888                && !(char_item == '^')
889                && !(char_item == '=')
890                && !(char_item == '.')
891                && !((char_item.is_alpha() && char_item.is_lowercase()) || char_item.is_dec_digit())
892        },
893        ErrorKind::AlphaNumeric,
894    )
895}
896
897pub fn lowercase1<T: Span>(i: T) -> Res<T, T>
898where
899    T: InputTakeAtPosition + nom::InputLength,
900    <T as InputTakeAtPosition>::Item: AsChar,
901{
902    i.split_at_position1_complete(
903        |item| {
904            let char_item = item.as_char();
905            !(char_item.is_alpha() && char_item.is_lowercase())
906        },
907        ErrorKind::AlphaNumeric,
908    )
909}
910
911pub fn rec_skewer<I: Span>(input: I) -> Res<I, I> {
912    recognize(tuple((lowercase1, opt(skewer))))(input)
913}
914
915pub fn rec_skewer_capture<I: Span>(input: I) -> Res<I, I> {
916    recognize(tuple((lowercase1, opt(skewer_chars_plus_capture))))(input)
917}
918
919pub fn camel_chars<T>(i: T) -> Res<T, T>
920where
921    T: InputTakeAtPosition + nom::InputLength + Clone + Offset + Slice<RangeTo<usize>>,
922    <T as InputTakeAtPosition>::Item: AsChar,
923{
924    recognize(pair(upper, alphanumeric0))(i)
925}
926
927pub fn skewer_chars<T: Span>(i: T) -> Res<T, T>
928where
929    T: InputTakeAtPosition + nom::InputLength,
930    <T as InputTakeAtPosition>::Item: AsChar,
931{
932    i.split_at_position1_complete(
933        |item| {
934            let char_item = item.as_char();
935            char_item != '-'
936                && !char_item.is_digit(10)
937                && !(char_item.is_alpha() && char_item.is_lowercase())
938        },
939        ErrorKind::AlphaNumeric,
940    )
941}
942
943pub fn parse_uuid<I: Span>(i: I) -> Res<I, Uuid> {
944    let (next, uuid) = uuid_chars(i.clone())?;
945    Ok((
946        next,
947        Uuid::from(uuid)
948            .map_err(|e| nom::Err::Error(ErrorTree::from_error_kind(i, ErrorKind::Tag)))?,
949    ))
950}
951
952pub fn uuid_chars<T: Span>(i: T) -> Res<T, T>
953where
954    T: InputTakeAtPosition + nom::InputLength,
955    <T as InputTakeAtPosition>::Item: AsChar,
956{
957    // same as skewer_chars
958    skewer_chars(i)
959}
960
961pub fn skewer_chars_plus_capture<T: Span>(i: T) -> Res<T, T>
962where
963    T: InputTakeAtPosition + nom::InputLength,
964    <T as InputTakeAtPosition>::Item: AsChar,
965{
966    i.split_at_position1_complete(
967        |item| {
968            let char_item = item.as_char();
969            char_item != '-'
970                && char_item != '$'
971                && !char_item.is_digit(10)
972                && !(char_item.is_alpha() && char_item.is_lowercase())
973        },
974        ErrorKind::AlphaNumeric,
975    )
976}
977
978pub fn skewer_chars_template<T: Span>(i: T) -> Res<T, T>
979where
980    T: InputTakeAtPosition + nom::InputLength,
981    <T as InputTakeAtPosition>::Item: AsChar,
982{
983    i.split_at_position1_complete(
984        |item| {
985            let char_item = item.as_char();
986            char_item != '-'
987                && char_item.as_char() != '%'
988                && !char_item.is_digit(10)
989                && !(char_item.is_alpha() && char_item.is_lowercase())
990        },
991        ErrorKind::AlphaNumeric,
992    )
993}
994
995pub fn space_chars<T: Span>(i: T) -> Res<T, T>
996where
997    T: InputTakeAtPosition + nom::InputLength,
998    <T as InputTakeAtPosition>::Item: AsChar,
999{
1000    i.split_at_position1_complete(
1001        |item| {
1002            let char_item = item.as_char();
1003            !(char_item == '-')
1004                && !(char_item == '.')
1005                && !((char_item.is_alpha() && char_item.is_lowercase()) || char_item.is_dec_digit())
1006        },
1007        ErrorKind::AlphaNumeric,
1008    )
1009}
1010
1011pub fn space_chars_plus_capture<T: Span>(i: T) -> Res<T, T>
1012where
1013    T: InputTakeAtPosition + nom::InputLength,
1014    <T as InputTakeAtPosition>::Item: AsChar,
1015{
1016    i.split_at_position1_complete(
1017        |item| {
1018            let char_item = item.as_char();
1019            !(char_item == '-')
1020                && !(char_item == '.')
1021                && !(char_item == '$')
1022                && !((char_item.is_alpha() && char_item.is_lowercase()) || char_item.is_dec_digit())
1023        },
1024        ErrorKind::AlphaNumeric,
1025    )
1026}
1027
1028pub fn domain_chars<T: Span>(i: T) -> Res<T, T>
1029where
1030    T: InputTakeAtPosition + nom::InputLength,
1031    <T as InputTakeAtPosition>::Item: AsChar,
1032{
1033    i.split_at_position1_complete(
1034        |item| {
1035            let char_item = item.as_char();
1036            !(char_item == '-')
1037                && !(char_item == '.')
1038                && !((char_item.is_alpha() && char_item.is_lowercase()) || char_item.is_dec_digit())
1039        },
1040        ErrorKind::AlphaNumeric,
1041    )
1042}
1043
1044pub fn path_regex<I: Span>(input: I) -> Res<I, I> {
1045    let (next, regex_span) = context("regex", recognize(pair(tag("/"), nospace0)))(input.clone())?;
1046
1047    let regex_string = regex_span.to_string();
1048    match Regex::new(regex_string.as_str()) {
1049        Ok(regex) => Ok((next, regex_span)),
1050        Err(err) => {
1051            println!("regex error {}", err.to_string());
1052            return Err(nom::Err::Error(ErrorTree::from_error_kind(
1053                input,
1054                ErrorKind::Tag,
1055            )));
1056        }
1057    }
1058}
1059
1060pub fn regex<T: Span>(i: T) -> Res<T, T>
1061where
1062    T: InputTakeAtPosition + nom::InputLength,
1063    <T as InputTakeAtPosition>::Item: AsChar,
1064{
1065    i.split_at_position1_complete(
1066        |item| {
1067            let char_item = item.as_char();
1068            !(char_item == '-')
1069                && !(char_item == '.')
1070                && !(char_item == '/')
1071                && !(char_item == ':')
1072                && !(char_item == '_')
1073                && !(char_item.is_alpha() || char_item.is_dec_digit())
1074        },
1075        ErrorKind::AlphaNumeric,
1076    )
1077}
1078
1079pub fn filepath_chars<T: Span>(i: T) -> Res<T, T>
1080where
1081    T: InputTakeAtPosition + nom::InputLength,
1082    <T as InputTakeAtPosition>::Item: AsChar,
1083{
1084    i.split_at_position1_complete(
1085        |item| {
1086            let char_item = item.as_char();
1087            !(char_item == '-')
1088                && !(char_item == '.')
1089                && !(char_item == '/')
1090                && !(char_item == ':')
1091                && !(char_item == '_')
1092                && !(char_item.is_alpha() || char_item.is_dec_digit())
1093        },
1094        ErrorKind::AlphaNumeric,
1095    )
1096}
1097
1098pub fn file_chars_plus_capture<T: Span>(i: T) -> Res<T, T>
1099where
1100    T: InputTakeAtPosition + nom::InputLength,
1101    <T as InputTakeAtPosition>::Item: AsChar,
1102{
1103    i.split_at_position1_complete(
1104        |item| {
1105            let char_item = item.as_char();
1106            !(char_item == '-')
1107                && !(char_item == '.')
1108                && !(char_item == '_')
1109                && !(char_item == '$')
1110                && !(char_item.is_alpha() || char_item.is_dec_digit())
1111        },
1112        ErrorKind::AlphaNumeric,
1113    )
1114}
1115
1116pub fn file_chars<T: Span>(i: T) -> Res<T, T>
1117where
1118    T: InputTakeAtPosition + nom::InputLength,
1119    <T as InputTakeAtPosition>::Item: AsChar,
1120{
1121    i.split_at_position1_complete(
1122        |item| {
1123            let char_item = item.as_char();
1124            !(char_item == '-')
1125                && !(char_item == '.')
1126                && !(char_item == '_')
1127                && !(char_item.is_alpha() || char_item.is_dec_digit())
1128        },
1129        ErrorKind::AlphaNumeric,
1130    )
1131}
1132
1133pub fn file_chars_template<T: Span>(i: T) -> Res<T, T>
1134where
1135    T: InputTakeAtPosition + nom::InputLength,
1136    <T as InputTakeAtPosition>::Item: AsChar,
1137{
1138    i.split_at_position1_complete(
1139        |item| {
1140            let char_item = item.as_char();
1141            !(char_item == '-')
1142                && !(char_item == '.')
1143                && !(char_item == '_')
1144                && !(char_item == '%')
1145                && !(char_item.is_alpha() || char_item.is_dec_digit())
1146        },
1147        ErrorKind::AlphaNumeric,
1148    )
1149}
1150
1151pub fn not_space<I: Span>(input: I) -> Res<I, I> {
1152    is_not(" \n\r\t")(input)
1153}
1154
1155pub fn path<I: Span>(input: I) -> Res<I, I> {
1156    recognize(tuple((tag("/"), opt(filepath_chars))))(input)
1157}
1158
1159pub fn subst_path<I: Span>(input: I) -> Res<I, Subst<I>> {
1160    pair(peek(tag("/")), subst(filepath_chars))(input).map(|(next, (_, path))| (next, path))
1161}
1162
1163pub fn consume_path<I: Span>(input: I) -> Res<I, I> {
1164    all_consuming(path)(input)
1165}
1166
1167#[derive(Debug, Clone, Eq, PartialEq, Hash)]
1168pub struct CamelCase {
1169    string: String,
1170}
1171
1172impl CamelCase {
1173    pub fn as_str(&self) -> &str {
1174        self.string.as_str()
1175    }
1176}
1177
1178impl FromStr for CamelCase {
1179    type Err = SpaceErr;
1180
1181    fn from_str(s: &str) -> Result<Self, Self::Err> {
1182        result(all_consuming(camel_case)(new_span(s)))
1183    }
1184}
1185
1186impl Serialize for CamelCase {
1187    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1188    where
1189        S: Serializer,
1190    {
1191        serializer.serialize_str(self.string.as_str())
1192    }
1193}
1194
1195impl<'de> Deserialize<'de> for CamelCase {
1196    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1197    where
1198        D: Deserializer<'de>,
1199    {
1200        let string = String::deserialize(deserializer)?;
1201
1202        let result = result(camel_case(new_span(string.as_str())));
1203        match result {
1204            Ok(camel) => Ok(camel),
1205            Err(err) => Err(serde::de::Error::custom(err.to_string().as_str())),
1206        }
1207    }
1208}
1209
1210impl Display for CamelCase {
1211    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1212        f.write_str(self.string.as_str())
1213    }
1214}
1215
1216impl Deref for CamelCase {
1217    type Target = String;
1218
1219    fn deref(&self) -> &Self::Target {
1220        &self.string
1221    }
1222}
1223
1224#[derive(Debug, Clone, Eq, PartialEq, Hash)]
1225pub struct Domain {
1226    string: String,
1227}
1228
1229impl Serialize for Domain {
1230    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1231    where
1232        S: Serializer,
1233    {
1234        serializer.serialize_str(self.string.as_str())
1235    }
1236}
1237
1238impl<'de> Deserialize<'de> for Domain {
1239    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1240    where
1241        D: Deserializer<'de>,
1242    {
1243        let string = String::deserialize(deserializer)?;
1244
1245        let result = result(domain(new_span(string.as_str())));
1246        match result {
1247            Ok(domain) => Ok(domain),
1248            Err(err) => Err(serde::de::Error::custom(err.to_string())),
1249        }
1250    }
1251}
1252
1253impl FromStr for Domain {
1254    type Err = SpaceErr;
1255
1256    fn from_str(s: &str) -> Result<Self, Self::Err> {
1257        result(all_consuming(domain)(new_span(s)))
1258    }
1259}
1260
1261impl Display for Domain {
1262    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1263        f.write_str(self.string.as_str())
1264    }
1265}
1266
1267impl Deref for Domain {
1268    type Target = String;
1269
1270    fn deref(&self) -> &Self::Target {
1271        &self.string
1272    }
1273}
1274
1275#[derive(Debug, Clone, Eq, PartialEq, Hash)]
1276pub struct SkewerCase {
1277    string: String,
1278}
1279
1280impl Serialize for SkewerCase {
1281    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1282    where
1283        S: Serializer,
1284    {
1285        serializer.serialize_str(self.string.as_str())
1286    }
1287}
1288
1289impl<'de> Deserialize<'de> for SkewerCase {
1290    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1291    where
1292        D: Deserializer<'de>,
1293    {
1294        let string = String::deserialize(deserializer)?;
1295
1296        let result = result(skewer_case(new_span(string.as_str())));
1297        match result {
1298            Ok(skewer) => Ok(skewer),
1299            Err(err) => Err(serde::de::Error::custom(err.to_string())),
1300        }
1301    }
1302}
1303
1304impl FromStr for SkewerCase {
1305    type Err = SpaceErr;
1306
1307    fn from_str(s: &str) -> Result<Self, Self::Err> {
1308        result(all_consuming(skewer_case)(new_span(s)))
1309    }
1310}
1311
1312impl Display for SkewerCase {
1313    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1314        f.write_str(self.string.as_str())
1315    }
1316}
1317
1318impl Deref for SkewerCase {
1319    type Target = String;
1320
1321    fn deref(&self) -> &Self::Target {
1322        &self.string
1323    }
1324}
1325
1326pub fn camel_case<I: Span>(input: I) -> Res<I, CamelCase> {
1327    context("expect-camel-case", camel_case_chars)(input).map(|(next, camel_case_chars)| {
1328        (
1329            next,
1330            CamelCase {
1331                string: camel_case_chars.to_string(),
1332            },
1333        )
1334    })
1335}
1336
1337pub fn skewer_case<I: Span>(input: I) -> Res<I, SkewerCase> {
1338    context("expect-skewer-case", skewer_case_chars)(input).map(|(next, skewer_case_chars)| {
1339        (
1340            next,
1341            SkewerCase {
1342                string: skewer_case_chars.to_string(),
1343            },
1344        )
1345    })
1346}
1347
1348pub fn camel_case_chars<I: Span>(input: I) -> Res<I, I> {
1349    recognize(tuple((is_a("ABCDEFGHIJKLMNOPQRSTUVWXYZ"), alphanumeric0)))(input)
1350}
1351
1352pub fn skewer_case_chars<I: Span>(input: I) -> Res<I, I> {
1353    recognize(tuple((
1354        is_a("abcdefghijklmnopqrstuvwxyz"),
1355        many0(alt((alphanumeric1, tag("-")))),
1356    )))(input)
1357}
1358
1359pub fn lowercase_alphanumeric<I: Span>(input: I) -> Res<I, I> {
1360    recognize(tuple((lowercase1, alphanumeric0)))(input)
1361}
1362
1363pub fn single_lowercase<T: Span, Input, Error: ParseError<Input>>(
1364    arr: T,
1365) -> impl Fn(Input) -> IResult<Input, Input, Error>
1366where
1367    Input: InputTakeAtPosition,
1368    T: FindToken<<Input as InputTakeAtPosition>::Item>,
1369{
1370    move |i: Input| {
1371        let e: ErrorKind = ErrorKind::IsA;
1372        i.split_at_position1_complete(|c| !arr.find_token(c), e)
1373    }
1374}
1375
1376pub fn single_lowerscase<I: Span>(input: I) -> Res<I, I> {
1377    is_a("abcdefghijklmnopqrstuvwxyz")(input)
1378}
1379pub fn single_digit<I: Span>(input: I) -> Res<I, I> {
1380    is_a("abcdefghijklmnopqrstuvwxyz")(input)
1381}
1382
1383pub fn camel_case_to_string_matcher<I: Span>(input: I) -> Res<I, StringMatcher> {
1384    camel_case_chars(input).map(|(next, camel)| (next, StringMatcher::new(camel.to_string())))
1385}
1386
1387fn parse_version_major_minor_patch<I: Span>(input: I) -> Res<I, (I, I, I)> {
1388    context(
1389        "version_major_minor_patch",
1390        tuple((
1391            terminated(digit1, tag(".")),
1392            terminated(digit1, tag(".")),
1393            terminated(digit1, not(digit1)),
1394        )),
1395    )(input)
1396}
1397
1398pub fn parse_version<I: Span>(input: I) -> Res<I, ((I, I, I), Option<I>)> {
1399    tuple((
1400        parse_version_major_minor_patch,
1401        opt(preceded(tag("-"), skewer_chars)),
1402    ))(input)
1403}
1404
1405pub fn rec_version<I: Span>(input: I) -> Res<I, I> {
1406    recognize(parse_version)(input)
1407}
1408
1409pub fn base_point_segment_wildcard<I: Span>(input: I) -> Res<I, PointTemplateSeg> {
1410    preceded(
1411        tag(":"),
1412        recognize(tuple((many0(skewer), tag("%"), many0(skewer)))),
1413    )(input)
1414    .map(|(next, base)| (next, PointTemplateSeg::Wildcard(base.to_string())))
1415}
1416
1417pub fn base_point_segment_template<I: Span>(input: I) -> Res<I, PointTemplateSeg> {
1418    preceded(tag(":"), rec_skewer)(input).map(|(next, base)| {
1419        (
1420            next,
1421            PointTemplateSeg::ExactSeg(PointSeg::Base(base.to_string())),
1422        )
1423    })
1424}
1425
1426pub fn filepath_point_segment_wildcard<I: Span>(input: I) -> Res<I, PointTemplateSeg> {
1427    recognize(tuple((
1428        many0(filepath_chars),
1429        tag("%"),
1430        many0(filepath_chars),
1431    )))(input)
1432    .map(|(next, base)| (next, PointTemplateSeg::Wildcard(base.to_string())))
1433}
1434
1435pub fn filepath_point_segment_template<I: Span>(input: I) -> Res<I, PointTemplateSeg> {
1436    filesystem_point_segment(input)
1437        .map(|(next, segment)| (next, PointTemplateSeg::ExactSeg(segment)))
1438}
1439
1440/*pub fn point_template<I: Span>(input: I) -> Res<I, PointTemplate> {
1441    let (next, ((hub, space), mut bases, version, root, mut files)) = tuple((
1442        tuple((point_route_segment, space_point_segment)),
1443        many0(alt((
1444            base_point_segment_wildcard,
1445            base_point_segment_template,
1446        ))),
1447        opt(version_point_segment),
1448        opt(root_dir_point_segment),
1449        many0(alt((
1450            filepath_point_segment_wildcard,
1451            filepath_point_segment_template,
1452        ))),
1453    ))(input.clone())?;
1454
1455    let mut base_wildcard = false;
1456    for (index, segment) in bases.iter().enumerate() {
1457        if segment.is_wildcard() {
1458            if index != bases.len() - 1 {
1459                return Err(nom::Err::Error(ErrorTree::from_error_kind(
1460                    input,
1461                    ErrorKind::Tag,
1462                )));
1463            } else {
1464                base_wildcard = true;
1465            }
1466        }
1467    }
1468
1469    if base_wildcard && version.is_some() {
1470        return Err(nom::Err::Error(ErrorTree::from_error_kind(
1471            input,
1472            ErrorKind::Tag,
1473        )));
1474    }
1475
1476    if base_wildcard && root.is_some() {
1477        return Err(nom::Err::Error(ErrorTree::from_error_kind(
1478            input,
1479            ErrorKind::Tag,
1480        )));
1481    }
1482
1483    let mut files_wildcard = false;
1484    for (index, segment) in files.iter().enumerate() {
1485        if segment.is_wildcard() {
1486            if index != files.len() - 1 {
1487                return Err(nom::Err::Error(ErrorTree::from_error_kind(
1488                    input.clone(),
1489                    ErrorKind::Tag,
1490                )));
1491            } else {
1492                files_wildcard = true;
1493            }
1494        }
1495    }
1496
1497    let mut space_last = false;
1498    let last = if !files.is_empty() {
1499        match files.remove(files.len() - 1) {
1500            PointTemplateSeg::ExactSeg(exact) => PointSegFactory::Exact(exact.to_string()),
1501            PointTemplateSeg::Wildcard(pattern) => PointSegFactory::Pattern(pattern),
1502        }
1503    } else if root.is_some() {
1504        PointSegFactory::Exact("/".to_string())
1505    } else if let Option::Some(version) = &version {
1506        PointSegFactory::Exact(version.to_string())
1507    } else if !bases.is_empty() {
1508        match bases.remove(bases.len() - 1) {
1509            PointTemplateSeg::ExactSeg(exact) => PointSegFactory::Exact(exact.to_string()),
1510            PointTemplateSeg::Wildcard(pattern) => PointSegFactory::Pattern(pattern),
1511        }
1512    } else {
1513        space_last = true;
1514        PointSegFactory::Exact(space.to_string())
1515    };
1516
1517    let mut bases: Vec<PointSeg> = bases
1518        .into_iter()
1519        .map(|b| match b {
1520            PointTemplateSeg::ExactSeg(seg) => seg,
1521            PointTemplateSeg::Wildcard(_) => {
1522                panic!("should have filtered wildcards already!")
1523            }
1524        })
1525        .collect();
1526
1527    let mut files: Vec<PointSeg> = files
1528        .into_iter()
1529        .map(|b| match b {
1530            PointTemplateSeg::ExactSeg(seg) => seg,
1531            PointTemplateSeg::Wildcard(_) => {
1532                panic!("should have filtered wildcards already!")
1533            }
1534        })
1535        .collect();
1536
1537    let mut segments = vec![];
1538
1539    if !space_last {
1540        segments.push(space);
1541    }
1542
1543    segments.append(&mut bases);
1544
1545    match version {
1546        None => {}
1547        Some(version) => {
1548            segments.push(version);
1549        }
1550    }
1551
1552    if let Option::Some(root) = root {
1553        segments.push(root);
1554        segments.append(&mut files);
1555    }
1556
1557    let point = Point {
1558        route: hub,
1559        segments,
1560    };
1561
1562    let point_template = PointTemplate {
1563        parent: point,
1564        child_segment_template: last,
1565    };
1566
1567    Ok((next, point_template))
1568}
1569
1570 */
1571
1572pub fn point_template<I: Span>(input: I) -> Res<I, PointTemplateVar> {
1573    let (next, (point, wildcard)) = pair(point_var, opt(recognize(tag("%"))))(input.clone())?;
1574
1575    if point.is_root() {
1576        return Ok((
1577            next,
1578            PointTemplateVar {
1579                parent: point,
1580                child_segment_template: PointSegTemplate::Root,
1581            },
1582        ));
1583    }
1584
1585    let parent = point
1586        .parent()
1587        .expect("expect that point template has a parent");
1588    let child = point
1589        .last_segment()
1590        .expect("expect that point template has a last segment");
1591
1592    match wildcard {
1593        None => Ok((
1594            next,
1595            PointTemplateVar {
1596                parent,
1597                child_segment_template: PointSegTemplate::Exact(child.to_string()),
1598            },
1599        )),
1600        Some(_) => {
1601            let child = format!("{}%", child.to_string());
1602            Ok((
1603                next,
1604                PointTemplateVar {
1605                    parent,
1606                    child_segment_template: PointSegTemplate::Exact(child),
1607                },
1608            ))
1609        }
1610    }
1611}
1612
1613pub fn kind_template<I: Span>(input: I) -> Res<I, KindTemplate> {
1614    tuple((
1615        kind_base,
1616        opt(delimited(
1617            tag("<"),
1618            tuple((
1619                camel_case,
1620                opt(delimited(tag("<"), specific_selector, tag(">"))),
1621            )),
1622            tag(">"),
1623        )),
1624    ))(input)
1625    .map(|(next, (kind, more))| {
1626        let mut parts = KindTemplate {
1627            base: kind,
1628            sub: None,
1629            specific: None,
1630        };
1631
1632        match more {
1633            Some((sub, specific)) => {
1634                parts.sub = Option::Some(sub);
1635                parts.specific = specific;
1636            }
1637            None => {}
1638        }
1639
1640        (next, parts)
1641    })
1642}
1643
1644pub fn template<I: Span>(input: I) -> Res<I, TemplateVar> {
1645    tuple((point_template, delimited(tag("<"), kind_template, tag(">"))))(input)
1646        .map(|(next, (point, kind))| (next, TemplateVar { point, kind }))
1647}
1648
1649pub fn set_property_mod<I: Span>(input: I) -> Res<I, PropertyMod> {
1650    tuple((tag("+"), skewer_dot, tag("="), property_value))(input).map(
1651        |(next, (_, key, _, value))| {
1652            (
1653                next,
1654                PropertyMod::Set {
1655                    key: key.to_string(),
1656                    value: value.to_string(),
1657                    lock: false,
1658                },
1659            )
1660        },
1661    )
1662}
1663
1664pub fn set_property_mod_lock<I: Span>(input: I) -> Res<I, PropertyMod> {
1665    tuple((tag("+@"), skewer_dot, tag("="), property_value))(input).map(
1666        |(next, (_, key, _, value))| {
1667            (
1668                next,
1669                PropertyMod::Set {
1670                    key: key.to_string(),
1671                    value: value.to_string(),
1672                    lock: true,
1673                },
1674            )
1675        },
1676    )
1677}
1678
1679pub fn property_value_not_space_or_comma<I: Span>(input: I) -> Res<I, I> {
1680    is_not(" \n\r\t,")(input)
1681}
1682
1683pub fn property_value_single_quotes<I: Span>(input: I) -> Res<I, I> {
1684    delimited(tag("'"), is_not("'"), tag("'"))(input)
1685}
1686
1687pub fn property_value_double_quotes<I: Span>(input: I) -> Res<I, I> {
1688    delimited(tag("\""), is_not("\""), tag("\""))(input)
1689}
1690
1691pub fn property_value<I: Span>(input: I) -> Res<I, I> {
1692    alt((
1693        property_value_single_quotes,
1694        property_value_double_quotes,
1695        property_value_not_space_or_comma,
1696    ))(input)
1697}
1698
1699pub fn unset_property_mod<I: Span>(input: I) -> Res<I, PropertyMod> {
1700    tuple((tag("!"), skewer_dot))(input)
1701        .map(|(next, (_, name))| (next, PropertyMod::UnSet(name.to_string())))
1702}
1703
1704pub fn property_mod<I: Span>(input: I) -> Res<I, PropertyMod> {
1705    alt((set_property_mod, unset_property_mod))(input)
1706}
1707
1708pub fn set_properties<I: Span>(input: I) -> Res<I, SetProperties> {
1709    separated_list0(tag(","), tuple((multispace0, property_mod, multispace0)))(input).map(
1710        |(next, properties)| {
1711            let mut set_properties = SetProperties::new();
1712            for (_, property, _) in properties {
1713                set_properties.push(property);
1714            }
1715            (next, set_properties)
1716        },
1717    )
1718}
1719
1720pub fn get_properties<I: Span>(input: I) -> Res<I, Vec<String>> {
1721    separated_list0(tag(","), tuple((multispace0, skewer, multispace0)))(input).map(
1722        |(next, keys)| {
1723            let keys: Vec<String> = keys.iter().map(|(_, key, _)| key.to_string()).collect();
1724            (next, keys)
1725        },
1726    )
1727}
1728
1729pub fn create<I: Span>(input: I) -> Res<I, CreateVar> {
1730    tuple((
1731        opt(alt((
1732            value(Strategy::Override, tag("!")),
1733            value(Strategy::Ensure, tag("?")),
1734        ))),
1735        space1,
1736        template,
1737        opt(delimited(tag("{"), set_properties, tag("}"))),
1738    ))(input)
1739    .map(|(next, (strategy, _, template, properties))| {
1740        let strategy = match strategy {
1741            None => Strategy::Commit,
1742            Some(strategy) => strategy,
1743        };
1744        let properties = match properties {
1745            Some(properties) => properties,
1746            None => SetProperties::new(),
1747        };
1748        let create = CreateVar {
1749            template,
1750            state: StateSrcVar::None,
1751            properties,
1752            strategy,
1753        };
1754        (next, create)
1755    })
1756}
1757
1758pub fn set<I: Span>(input: I) -> Res<I, SetVar> {
1759    tuple((point_var, delimited(tag("{"), set_properties, tag("}"))))(input).map(
1760        |(next, (point, properties))| {
1761            let set = SetVar { point, properties };
1762            (next, set)
1763        },
1764    )
1765}
1766
1767pub fn get<I: Span>(input: I) -> Res<I, GetVar> {
1768    tuple((
1769        point_var,
1770        opt(delimited(tag("{"), get_properties, tag("}"))),
1771    ))(input)
1772    .map(|(next, (point, keys))| {
1773        let op = match keys {
1774            None => GetOp::State,
1775            Some(keys) => GetOp::Properties(keys),
1776        };
1777        let get = GetVar { point, op };
1778
1779        (next, get)
1780    })
1781}
1782
1783pub fn select<I: Span>(input: I) -> Res<I, SelectVar> {
1784    point_selector(input).map(|(next, point_kind_pattern)| {
1785        let select = SelectVar {
1786            pattern: point_kind_pattern,
1787            properties: Default::default(),
1788            into_substance: SelectIntoSubstance::Stubs,
1789            kind: SelectKind::Initial,
1790        };
1791        (next, select)
1792    })
1793}
1794
1795pub fn publish<I: Span>(input: I) -> Res<I, CreateVar> {
1796    let (next, (upload, _, point)) = tuple((upload_block, space1, point_template))(input.clone())?;
1797
1798    /*
1799    let parent = match point.parent() {
1800        None => {
1801            return Err(nom::Err::Error(ErrorTree::from_error_kind(
1802                input,
1803                ErrorKind::Tag,
1804            )));
1805        }
1806        Some(parent) => parent,
1807    };
1808
1809    let last = match point.last_segment() {
1810        None => {
1811            return Err(nom::Err::Error(ErrorTree::from_error_kind(
1812                input.clone(),
1813                ErrorKind::Tag,
1814            )));
1815        }
1816        Some(last) => last,
1817    };
1818     */
1819
1820    let template = TemplateVar {
1821        point,
1822        kind: KindTemplate {
1823            base: BaseKind::Bundle,
1824            sub: None,
1825            specific: None,
1826        },
1827    };
1828
1829    let create = CreateVar {
1830        template,
1831        state: StateSrcVar::None,
1832        properties: Default::default(),
1833        strategy: Strategy::Commit,
1834    };
1835
1836    Ok((next, create))
1837}
1838
1839#[derive(Debug, Clone, Serialize, Deserialize)]
1840pub enum Ctx {
1841    WorkingPoint,
1842    PointFromRoot,
1843}
1844
1845impl ToString for Ctx {
1846    fn to_string(&self) -> String {
1847        match self {
1848            Ctx::WorkingPoint => ".".to_string(),
1849            Ctx::PointFromRoot => "...".to_string(),
1850        }
1851    }
1852}
1853
1854#[derive(Clone, Serialize, Deserialize)]
1855pub struct File {
1856    pub name: String,
1857    pub content: Bin,
1858}
1859
1860impl File {
1861    pub fn new<S: ToString>(name: S, content: Bin) -> Self {
1862        Self {
1863            name: name.to_string(),
1864            content,
1865        }
1866    }
1867}
1868
1869#[derive(Clone, Serialize, Deserialize)]
1870pub struct FileResolver {
1871    pub files: HashMap<String, Bin>,
1872}
1873
1874impl FileResolver {
1875    pub fn new() -> Self {
1876        Self {
1877            files: HashMap::new(),
1878        }
1879    }
1880
1881    pub fn file<N: ToString>(&self, name: N) -> Result<File, ResolverErr> {
1882        if let Some(content) = self.files.get(&name.to_string()) {
1883            Ok(File::new(name, content.clone()))
1884        } else {
1885            Err(ResolverErr::NotFound)
1886        }
1887    }
1888
1889    /// grab the only file
1890    pub fn singleton(&self) -> Result<File, ResolverErr> {
1891        if self.files.len() == 1 {
1892            let i = &mut self.files.iter();
1893            if let Some((name, content)) = i.next() {
1894                Ok(File::new(name.clone(), content.clone()))
1895            } else {
1896                Err(ResolverErr::NotFound)
1897            }
1898        } else {
1899            Err(ResolverErr::NotFound)
1900        }
1901    }
1902}
1903
1904#[derive(Clone, Serialize, Deserialize)]
1905pub struct Env {
1906    parent: Option<Box<Env>>,
1907    pub point: Point,
1908    pub vars: HashMap<String, Substance>,
1909    pub file_resolver: FileResolver,
1910
1911    #[serde(skip_serializing)]
1912    #[serde(skip_deserializing)]
1913    #[serde(default)]
1914    pub var_resolvers: MultiVarResolver,
1915}
1916
1917impl Env {
1918    pub fn new(working: Point) -> Self {
1919        Self {
1920            parent: None,
1921            point: working,
1922            vars: HashMap::new(),
1923            file_resolver: FileResolver::new(),
1924            var_resolvers: MultiVarResolver::new(),
1925        }
1926    }
1927
1928    pub fn no_point() -> Self {
1929        Self::new(Point::root())
1930    }
1931
1932    pub fn push(self) -> Self {
1933        Self {
1934            point: self.point.clone(),
1935            parent: Some(Box::new(self)),
1936            vars: HashMap::new(),
1937            file_resolver: FileResolver::new(),
1938            var_resolvers: MultiVarResolver::new(),
1939        }
1940    }
1941
1942    pub fn push_working<S: ToString>(self, segs: S) -> Result<Self, SpaceErr> {
1943        Ok(Self {
1944            point: self.point.push(segs.to_string())?,
1945            parent: Some(Box::new(self)),
1946            vars: HashMap::new(),
1947            file_resolver: FileResolver::new(),
1948            var_resolvers: MultiVarResolver::new(),
1949        })
1950    }
1951
1952    pub fn point_or(&self) -> Result<Point, SpaceErr> {
1953        Ok(self.point.clone())
1954    }
1955
1956    pub fn pop(self) -> Result<Env, SpaceErr> {
1957        Ok(*self
1958            .parent
1959            .ok_or::<SpaceErr>("expected parent scopedVars".into())?)
1960    }
1961
1962    pub fn add_var_resolver(&mut self, var_resolver: Arc<dyn VarResolver>) {
1963        self.var_resolvers.push(var_resolver);
1964    }
1965
1966    pub fn val<K: ToString>(&self, var: K) -> Result<Substance, ResolverErr> {
1967        match self.vars.get(&var.to_string()) {
1968            None => {
1969                if let Ok(val) = self.var_resolvers.val(var.to_string().as_str()) {
1970                    Ok(val.clone())
1971                } else if let Some(parent) = self.parent.as_ref() {
1972                    parent.val(var.to_string())
1973                } else {
1974                    Err(ResolverErr::NotFound)
1975                }
1976            }
1977            Some(val) => Ok(val.clone()),
1978        }
1979    }
1980
1981    pub fn set_working(&mut self, point: Point) {
1982        self.point = point;
1983    }
1984
1985    pub fn working(&self) -> &Point {
1986        &self.point
1987    }
1988
1989    pub fn set_var_str<V: ToString>(&mut self, key: V, value: V) {
1990        self.vars
1991            .insert(key.to_string(), Substance::Text(value.to_string()));
1992    }
1993
1994    pub fn set_var<V: ToString>(&mut self, key: V, value: Substance) {
1995        self.vars.insert(key.to_string(), value);
1996    }
1997
1998    pub fn file<N: ToString>(&self, name: N) -> Result<File, ResolverErr> {
1999        match self.file_resolver.files.get(&name.to_string()) {
2000            None => {
2001                if let Some(parent) = self.parent.as_ref() {
2002                    parent.file(name.to_string())
2003                } else {
2004                    Err(ResolverErr::NotFound)
2005                }
2006            }
2007            Some(bin) => Ok(File::new(name.to_string(), bin.clone())),
2008        }
2009    }
2010
2011    pub fn set_file<N: ToString>(&mut self, name: N, content: Bin) {
2012        self.file_resolver.files.insert(name.to_string(), content);
2013    }
2014}
2015
2016impl Default for Env {
2017    fn default() -> Self {
2018        Self {
2019            parent: None,
2020            point: Point::root(),
2021            vars: HashMap::new(),
2022            file_resolver: FileResolver::new(),
2023            var_resolvers: MultiVarResolver::new(),
2024        }
2025    }
2026}
2027
2028/*
2029#[derive(Clone)]
2030pub struct Env {
2031    point: Option<Point>,
2032    var_resolver: Option<CompositeResolver>,
2033    file_resolver: Option<FileResolver>,
2034}
2035
2036impl Env {
2037    pub fn add_var_resolver(&mut self, resolver: Arc<dyn VarResolver>) {
2038        if let Some(r) = self.var_resolver.as_mut() {
2039            r.other_resolver.push(resolver)
2040        }
2041    }
2042
2043    pub fn no_point() -> Self {
2044        Self {
2045            point: None,
2046            var_resolver: Some(CompositeResolver::new()),
2047            file_resolver: None,
2048        }
2049    }
2050
2051    pub fn unavailable() -> Self {
2052        Self {
2053            point: None,
2054            var_resolver: None,
2055            file_resolver: None,
2056        }
2057    }
2058
2059    pub fn new(point: Point) -> Self {
2060        Self {
2061            point: Some(point),
2062            var_resolver: Some(CompositeResolver::new()),
2063            file_resolver: Some(FileResolver::new()),
2064        }
2065    }
2066
2067    pub fn just_point(point: Point) -> Self {
2068        Self {
2069            point: Some(point),
2070            var_resolver: None,
2071            file_resolver: None,
2072        }
2073    }
2074
2075    pub fn point_or(&self) -> Result<&Point, ExtErr> {
2076        self.point
2077            .as_ref()
2078            .ok_or("cannot reference working point in this context".into())
2079    }
2080
2081    pub fn val(&self, var: &str) -> Result<String, ResolverErr> {
2082        if let None = self.var_resolver {
2083            Err(ResolverErr::NotAvailable)
2084        } else {
2085            self.var_resolver.as_ref().unwrap().val(var)
2086        }
2087    }
2088
2089    pub fn set_working(&mut self, point: Point) {
2090        self.point.replace(point);
2091    }
2092
2093    pub fn set_var<V: ToString>(&mut self, key: V, value: V) {
2094        match self.var_resolver.as_mut() {
2095            None => {
2096                let mut var_resolver = CompositeResolver::new();
2097                var_resolver.set(key, value);
2098                self.var_resolver.replace(var_resolver);
2099            }
2100            Some(var_resolver) => {
2101                var_resolver.set(key, value);
2102            }
2103        }
2104    }
2105
2106    pub fn file<N: ToString>(&self, name: N) -> Result<File, ResolverErr> {
2107        match &self.file_resolver {
2108            None => Err(ResolverErr::NotAvailable),
2109            Some(file_resolver) => file_resolver.file(name),
2110        }
2111    }
2112
2113    pub fn set_file<N: ToString>(&mut self, name: N, content: Bin) {
2114        match self.file_resolver.as_mut() {
2115            None => {
2116                let mut file_resolver = FileResolver::new();
2117                file_resolver.files.insert(name.to_string(), content);
2118                self.file_resolver.replace(file_resolver);
2119            }
2120            Some(file_resolver) => {
2121                file_resolver.files.insert(name.to_string(), content);
2122            }
2123        }
2124    }
2125}
2126
2127 */
2128
2129#[derive(Clone)]
2130pub struct CompositeResolver {
2131    pub env_resolver: Arc<dyn VarResolver>,
2132    pub scope_resolver: MapResolver,
2133    pub other_resolver: MultiVarResolver,
2134}
2135
2136impl CompositeResolver {
2137    pub fn new() -> Self {
2138        Self {
2139            env_resolver: Arc::new(NoResolver::new()),
2140            scope_resolver: MapResolver::new(),
2141            other_resolver: MultiVarResolver::new(),
2142        }
2143    }
2144
2145    pub fn set<S>(&mut self, key: S, value: Substance)
2146    where
2147        S: ToString,
2148    {
2149        self.scope_resolver.insert(key.to_string(), value);
2150    }
2151}
2152
2153impl VarResolver for CompositeResolver {
2154    fn val(&self, var: &str) -> Result<Substance, ResolverErr> {
2155        if let Ok(val) = self.scope_resolver.val(var) {
2156            Ok(val)
2157        } else if let Ok(val) = self.scope_resolver.val(var) {
2158            Ok(val)
2159        } else if let Ok(val) = self.other_resolver.val(var) {
2160            Ok(val)
2161        } else {
2162            Err(ResolverErr::NotFound)
2163        }
2164    }
2165}
2166
2167pub trait CtxResolver {
2168    fn working_point(&self) -> Result<&Point, SpaceErr>;
2169}
2170
2171pub struct PointCtxResolver(Point);
2172
2173impl CtxResolver for PointCtxResolver {
2174    fn working_point(&self) -> Result<&Point, SpaceErr> {
2175        Ok(&self.0)
2176    }
2177}
2178
2179pub enum ResolverErr {
2180    NotAvailable,
2181    NotFound,
2182}
2183
2184pub trait VarResolver: Send + Sync {
2185    fn val(&self, var: &str) -> Result<Substance, ResolverErr> {
2186        Err(ResolverErr::NotFound)
2187    }
2188}
2189
2190#[derive(Clone)]
2191pub struct NoResolver;
2192
2193impl NoResolver {
2194    pub fn new() -> Self {
2195        Self {}
2196    }
2197}
2198
2199impl VarResolver for NoResolver {}
2200
2201#[derive(Clone)]
2202pub struct MapResolver {
2203    pub map: HashMap<String, Substance>,
2204}
2205
2206impl MapResolver {
2207    pub fn new() -> Self {
2208        Self {
2209            map: HashMap::new(),
2210        }
2211    }
2212
2213    pub fn insert<K: ToString>(&mut self, key: K, value: Substance) {
2214        self.map.insert(key.to_string(), value);
2215    }
2216}
2217
2218impl VarResolver for MapResolver {
2219    fn val(&self, var: &str) -> Result<Substance, ResolverErr> {
2220        self.map
2221            .get(&var.to_string())
2222            .cloned()
2223            .ok_or(ResolverErr::NotFound)
2224    }
2225}
2226
2227#[derive(Clone)]
2228pub struct RegexCapturesResolver {
2229    regex: Regex,
2230    text: String,
2231}
2232
2233impl RegexCapturesResolver {
2234    pub fn new(regex: Regex, text: String) -> Result<Self, SpaceErr> {
2235        regex.captures(text.as_str()).ok_or("no regex captures")?;
2236        Ok(Self { regex, text })
2237    }
2238}
2239
2240impl VarResolver for RegexCapturesResolver {
2241    fn val(&self, id: &str) -> Result<Substance, ResolverErr> {
2242        let captures = self
2243            .regex
2244            .captures(self.text.as_str())
2245            .expect("expected captures");
2246        match captures.name(id) {
2247            None => Err(ResolverErr::NotFound),
2248            Some(m) => Ok(Substance::Text(m.as_str().to_string())),
2249        }
2250    }
2251}
2252
2253#[derive(Clone)]
2254pub struct MultiVarResolver(Vec<Arc<dyn VarResolver>>);
2255
2256impl Default for MultiVarResolver {
2257    fn default() -> Self {
2258        MultiVarResolver::new()
2259    }
2260}
2261
2262impl MultiVarResolver {
2263    pub fn new() -> Self {
2264        Self(vec![])
2265    }
2266
2267    pub fn push(&mut self, resolver: Arc<dyn VarResolver>) {
2268        self.0.push(resolver);
2269    }
2270}
2271
2272impl VarResolver for MultiVarResolver {
2273    fn val(&self, var: &str) -> Result<Substance, ResolverErr> {
2274        for resolver in &self.0 {
2275            match resolver.val(&var.to_string()) {
2276                Ok(ok) => return Ok(ok),
2277                Err(_) => {}
2278            }
2279        }
2280        Err(ResolverErr::NotFound)
2281    }
2282}
2283
2284/*
2285pub trait BruteResolver<Resolved>
2286where
2287    Self: Sized + ToResolved<Resolved>,
2288{
2289    fn brute_resolve(self) -> Result<Resolved, ExtErr> {
2290        let resolver = NoResolver::new().wrap();
2291        Ok(self.to_resolved(&resolver)?)
2292    }
2293}
2294
2295 */
2296
2297pub fn diagnose<I: Clone, O, E: ParseError<I>, F>(
2298    tag: &'static str,
2299    mut f: F,
2300) -> impl FnMut(I) -> IResult<I, O, E>
2301where
2302    I: ToString
2303        + InputLength
2304        + InputTake
2305        + Compare<&'static str>
2306        + InputIter
2307        + Clone
2308        + InputTakeAtPosition,
2309    <I as InputTakeAtPosition>::Item: AsChar,
2310    I: ToString,
2311    F: nom::Parser<I, O, E>,
2312    E: nom::error::ContextError<I>,
2313    O: Clone,
2314{
2315    move |input: I| {
2316        let (next, i) = f.parse(input)?;
2317        Ok((next, i))
2318    }
2319}
2320
2321pub trait SubstParser<T: Sized> {
2322    fn parse_string(&self, string: String) -> Result<T, SpaceErr> {
2323        let span = new_span(string.as_str());
2324        let output = result(self.parse_span(span))?;
2325        Ok(output)
2326    }
2327
2328    fn parse_span<I: Span>(&self, input: I) -> Res<I, T>;
2329}
2330
2331pub fn root_ctx_seg<I: Span, E: ParseError<I>, F>(
2332    mut f: F,
2333) -> impl FnMut(I) -> IResult<I, PointSegCtx, E> + Copy
2334where
2335    F: nom::Parser<I, PointSeg, E> + Copy,
2336    E: nom::error::ContextError<I>,
2337{
2338    move |input: I| match pair(tag::<&str, I, E>(".."), eos)(input.clone()) {
2339        Ok((next, v)) => Ok((
2340            next.clone(),
2341            PointSegCtx::Pop(Trace {
2342                range: next.location_offset() - 2..next.location_offset(),
2343                extra: next.extra(),
2344            }),
2345        )),
2346        Err(err) => match pair(tag::<&str, I, E>("."), eos)(input.clone()) {
2347            Ok((next, _)) => Ok((
2348                next.clone(),
2349                PointSegCtx::Working(Trace {
2350                    range: next.location_offset() - 1..next.location_offset(),
2351                    extra: next.extra(),
2352                }),
2353            )),
2354            Err(err) => match f.parse(input) {
2355                Ok((next, seg)) => Ok((next, seg.into())),
2356                Err(err) => Err(err),
2357            },
2358        },
2359    }
2360}
2361
2362pub fn working<I: Span, E: ParseError<I>, F>(
2363    mut f: F,
2364) -> impl FnMut(I) -> IResult<I, PointSegCtx, E>
2365where
2366    F: nom::Parser<I, PointSeg, E>,
2367    E: nom::error::ContextError<I>,
2368{
2369    move |input: I| match pair(tag::<&str, I, E>("."), eos)(input.clone()) {
2370        Ok((next, v)) => Ok((
2371            next.clone(),
2372            PointSegCtx::Working(Trace {
2373                range: next.location_offset() - 1..next.location_offset(),
2374                extra: next.extra(),
2375            }),
2376        )),
2377        Err(err) => match f.parse(input.clone()) {
2378            Ok((next, seg)) => Ok((next, seg.into())),
2379            Err(err) => Err(err),
2380        },
2381    }
2382}
2383
2384pub fn pop<I: Span, E: ParseError<I>, F>(
2385    mut f: F,
2386) -> impl FnMut(I) -> IResult<I, PointSegCtx, E> + Copy
2387where
2388    F: nom::Parser<I, PointSeg, E> + Copy,
2389    E: nom::error::ContextError<I>,
2390{
2391    move |input: I| match pair(tag::<&str, I, E>(".."), eos)(input.clone()) {
2392        Ok((next, v)) => Ok((
2393            next.clone(),
2394            PointSegCtx::Working(Trace {
2395                range: next.location_offset() - 2..next.location_offset(),
2396                extra: next.extra(),
2397            }),
2398        )),
2399        Err(err) => match f.parse(input.clone()) {
2400            Ok((next, seg)) => Ok((next, seg.into())),
2401            Err(err) => Err(err),
2402        },
2403    }
2404}
2405
2406pub fn base_seg<I, F, S, E>(mut f: F) -> impl FnMut(I) -> IResult<I, S, E>
2407where
2408    I: Span,
2409    F: nom::Parser<I, S, E> + Copy,
2410    E: nom::error::ContextError<I> + nom::error::ParseError<I>,
2411    S: PointSegment,
2412{
2413    move |input: I| preceded(tag(":"), f)(input)
2414}
2415
2416pub fn mesh_seg<I: Span, E: ParseError<I>, F, S1, S2>(
2417    mut f: F,
2418) -> impl FnMut(I) -> IResult<I, S2, E>
2419where
2420    F: nom::Parser<I, S1, E> + Copy,
2421    E: nom::error::ContextError<I>,
2422    S1: PointSegment + Into<S2>,
2423    S2: PointSegment,
2424{
2425    move |input: I| {
2426        tuple((seg_delim, f, eos))(input).map(|(next, (delim, seg, _))| (next, seg.into()))
2427    }
2428}
2429
2430// end of segment
2431pub fn seg_delim<I: Span, E>(input: I) -> IResult<I, PointSegDelim, E>
2432where
2433    I: ToString
2434        + Clone
2435        + InputLength
2436        + InputTake
2437        + Compare<&'static str>
2438        + InputIter
2439        + InputTakeAtPosition,
2440    <I as InputTakeAtPosition>::Item: AsChar + Clone,
2441    E: nom::error::ContextError<I> + nom::error::ParseError<I>,
2442{
2443    alt((
2444        value(PointSegDelim::File, tag("/")),
2445        value(PointSegDelim::Mesh, tag(":")),
2446    ))(input)
2447    .map(|(next, delim)| (next, delim))
2448}
2449
2450// end of segment
2451pub fn eos<I: Span, E>(input: I) -> IResult<I, (), E>
2452where
2453    E: nom::error::ContextError<I> + nom::error::ParseError<I>,
2454{
2455    peek(alt((tag("/"), tag(":"), tag("%"), space1, eof)))(input).map(|(next, _)| (next, ()))
2456}
2457
2458/*
2459pub fn var<O>(f: impl Fn(Span) -> Res<Span,O>+'static+Clone) -> impl FnMut(Span) -> Res<Span, Symbol<O>>
2460{
2461    unimplemented!()
2462    /*
2463    move |input: Span| {
2464        preceded(
2465            tag("$"),
2466            context(
2467                "variable",
2468                cut(delimited(
2469                    context("variable:open", tag("(")),
2470                    variable_name,
2471                    tag(")"),
2472                )),
2473            ),
2474        )(input)
2475        .map(|(next, name)| {
2476            (
2477                next,
2478                Symbol::named(name.to_string(), f.clone() ),
2479            )
2480        })
2481    }
2482
2483     */
2484}
2485
2486 */
2487
2488/*jjj
2489pub fn ctx<O><I:Span>(input: Span) -> Res<Span, Symbol<O>>
2490
2491{
2492    alt((
2493        value(Ctx::RelativePointPop, tuple((tag(".."), eos))),
2494        value(Ctx::RelativePoint, tuple((tag("."), eos))),
2495    ))(input)
2496        .map(|(next, ctx)| (next, Symbol::ctx(ctx)))
2497}
2498
2499 */
2500
2501/*
2502pub fn ctx<I, O, F, E><I:Span>(input: I) -> Res<I, Symbol<O>>
2503where
2504    I: ToString
2505        + Clone
2506        + InputLength
2507        + InputTake
2508        + Compare<&'static str>
2509        + InputIter
2510        + InputTakeAtPosition,
2511    <I as InputTakeAtPosition>::Item: AsChar + Clone,
2512    F: nom::Parser<I, O, E> + Clone,
2513    E: nom::error::ContextError<I>,
2514{
2515    alt((
2516        value(Ctx::RelativePointPop, tuple((tag(".."), eos))),
2517        value(Ctx::RelativePoint, tuple((tag("."), eos))),
2518    ))(input)
2519    .map(|(next, ctx)| (next, Symbol::ctx(ctx)))
2520}
2521
2522 */
2523
2524pub fn variable_name<I: Span>(input: I) -> Res<I, I> {
2525    recognize(pair(lowercase1, opt(skewer_dot)))(input).map(|(next, name)| (next, name))
2526}
2527
2528pub fn ispan<'a, I: Clone, O, E: ParseError<I>, F>(
2529    mut f: F,
2530) -> impl FnMut(I) -> IResult<I, Spanned<I, O>, E>
2531where
2532    I: ToString
2533        + InputLength
2534        + InputTake
2535        + Compare<&'static str>
2536        + InputIter
2537        + Clone
2538        + InputTakeAtPosition,
2539    <I as InputTakeAtPosition>::Item: AsChar,
2540    F: nom::Parser<I, O, E>,
2541    E: nom::error::ContextError<I>,
2542    O: Clone + FromStr<Err = SpaceErr>,
2543{
2544    move |input: I| {
2545        let (next, element) = f.parse(input.clone())?;
2546        Ok((next, Spanned::new(element, input.clone())))
2547    }
2548}
2549
2550pub fn sub<I: Span, O, F>(mut f: F) -> impl FnMut(I) -> Res<I, Spanned<I, O>>
2551where
2552    F: nom::Parser<I, O, ErrorTree<I>>,
2553    O: Clone,
2554{
2555    move |input: I| {
2556        let (next, element) = f.parse(input.clone())?;
2557        Ok((
2558            next.clone(),
2559            Spanned::new(element, input.slice(0..(input.len() - next.len()))),
2560        ))
2561    }
2562}
2563
2564pub fn access_grant_kind<I: Span>(input: I) -> Res<I, AccessGrantKind> {
2565    tuple((
2566        context(
2567            "access_grant_kind",
2568            peek(alt((
2569                tuple((tag("perm"), space1)),
2570                tuple((tag("priv"), space1)),
2571            ))),
2572        ),
2573        alt((access_grant_kind_perm, access_grant_kind_priv)),
2574    ))(input)
2575    .map(|(next, (_, kind))| (next, kind))
2576}
2577
2578pub fn access_grant_kind_priv<I: Span>(input: I) -> Res<I, AccessGrantKind> {
2579    tuple((
2580        tag("priv"),
2581        context("access_grant:priv", tuple((space1, privilege))),
2582    ))(input)
2583    .map(|(next, (_, (_, privilege)))| (next, AccessGrantKindDef::Privilege(privilege)))
2584}
2585
2586pub fn access_grant_kind_perm<I: Span>(input: I) -> Res<I, AccessGrantKind> {
2587    tuple((
2588        tag("perm"),
2589        context("access_grant:perm", tuple((space1, permissions_mask))),
2590    ))(input)
2591    .map(|(next, (_, (_, perms)))| (next, AccessGrantKindDef::PermissionsMask(perms)))
2592}
2593
2594pub fn privilege<I: Span>(input: I) -> Res<I, Privilege> {
2595    context("privilege", alt((tag("*"), skewer_colon)))(input).map(|(next, prv)| {
2596        let prv = match prv.to_string().as_str() {
2597            "*" => Privilege::Full,
2598            prv => Privilege::Single(prv.to_string()),
2599        };
2600        (next, prv)
2601    })
2602}
2603
2604pub fn permissions_mask<I: Span>(input: I) -> Res<I, PermissionsMask> {
2605    context(
2606        "permissions_mask",
2607        tuple((
2608            alt((
2609                value(PermissionsMaskKind::Or, char('+')),
2610                value(PermissionsMaskKind::And, char('&')),
2611            )),
2612            permissions,
2613        )),
2614    )(input)
2615    .map(|(next, (kind, permissions))| {
2616        let mask = PermissionsMask { kind, permissions };
2617
2618        (next, mask)
2619    })
2620}
2621
2622pub fn permissions<I: Span>(input: I) -> Res<I, Permissions> {
2623    context(
2624        "permissions",
2625        tuple((child_perms, tag("-"), particle_perms)),
2626    )(input)
2627    .map(|(next, (child, _, particle))| {
2628        let permissions = Permissions { child, particle };
2629        (next, permissions)
2630    })
2631}
2632
2633pub fn child_perms<I: Span>(input: I) -> Res<I, ChildPerms> {
2634    context(
2635        "child_perms",
2636        alt((
2637            tuple((
2638                alt((value(false, char('c')), value(true, char('C')))),
2639                alt((value(false, char('s')), value(true, char('S')))),
2640                alt((value(false, char('d')), value(true, char('D')))),
2641            )),
2642            fail,
2643        )),
2644    )(input)
2645    .map(|(next, (create, select, delete))| {
2646        let block = ChildPerms {
2647            create,
2648            select,
2649            delete,
2650        };
2651        (next, block)
2652    })
2653}
2654
2655pub fn particle_perms<I: Span>(input: I) -> Res<I, ParticlePerms> {
2656    context(
2657        "particle_perms",
2658        tuple((
2659            alt((value(false, char('r')), value(true, char('R')))),
2660            alt((value(false, char('w')), value(true, char('W')))),
2661            alt((value(false, char('x')), value(true, char('X')))),
2662        )),
2663    )(input)
2664    .map(|(next, (read, write, execute))| {
2665        let block = ParticlePerms {
2666            read,
2667            write,
2668            execute,
2669        };
2670        (next, block)
2671    })
2672}
2673
2674/*
2675pub fn grant<I><I:Span>(input: I) -> Res<I,AccessGrant> where I:Clone+InputIter+InputLength+InputTake{
2676
2677}
2678
2679 */
2680
2681pub fn none<I: Span, O, E>(input: I) -> IResult<I, Option<O>, E> {
2682    Ok((input, None))
2683}
2684
2685pub fn some<I: Span, O, E, F>(mut f: F) -> impl FnMut(I) -> IResult<I, Option<O>, E>
2686where
2687    I: ToString
2688        + InputLength
2689        + InputTake
2690        + Compare<&'static str>
2691        + InputIter
2692        + Clone
2693        + InputTakeAtPosition,
2694    <I as InputTakeAtPosition>::Item: AsChar,
2695    I: ToString,
2696    I: Offset + nom::Slice<std::ops::RangeTo<usize>>,
2697    I: nom::Slice<std::ops::RangeFrom<usize>>,
2698    <I as InputIter>::Item: AsChar,
2699    E: nom::error::ContextError<I> + nom::error::ParseError<I>,
2700    F: nom::Parser<I, O, E> + Clone,
2701{
2702    move |input: I| {
2703        f.clone()
2704            .parse(input)
2705            .map(|(next, output)| (next, Some(output)))
2706    }
2707}
2708
2709pub fn lex_block_alt<I: Span, E>(
2710    kinds: Vec<BlockKind>,
2711) -> impl FnMut(I) -> IResult<I, LexBlock<I>, E>
2712where
2713    I: ToString
2714        + InputLength
2715        + InputTake
2716        + Compare<&'static str>
2717        + InputIter
2718        + Clone
2719        + InputTakeAtPosition,
2720    <I as InputTakeAtPosition>::Item: AsChar,
2721    I: ToString,
2722    I: Offset + nom::Slice<std::ops::RangeTo<usize>>,
2723    I: nom::Slice<std::ops::RangeFrom<usize>>,
2724    <I as InputIter>::Item: AsChar + Copy,
2725    E: nom::error::ContextError<I> + nom::error::ParseError<I>,
2726{
2727    move |input: I| {
2728        for kind in &kinds {
2729            let result = lex_block(kind.clone())(input.clone());
2730            match &result {
2731                Ok((next, block)) => return result,
2732                Err(err) => {
2733                    match err {
2734                        nom::Err::Incomplete(Needed) => return result,
2735                        nom::Err::Error(e) => {
2736                            // let's hope for another match...
2737                        }
2738                        nom::Err::Failure(e) => return result,
2739                    }
2740                }
2741            }
2742        }
2743
2744        Err(nom::Err::Failure(E::from_error_kind(
2745            input.clone(),
2746            ErrorKind::Alt,
2747        )))
2748    }
2749}
2750
2751pub fn lex_block<I: Span, E>(kind: BlockKind) -> impl FnMut(I) -> IResult<I, LexBlock<I>, E>
2752where
2753    I: ToString
2754        + InputLength
2755        + InputTake
2756        + Compare<&'static str>
2757        + InputIter
2758        + Clone
2759        + InputTakeAtPosition,
2760    <I as InputTakeAtPosition>::Item: AsChar,
2761    I: ToString,
2762    I: Offset + nom::Slice<std::ops::RangeTo<usize>>,
2763    I: nom::Slice<std::ops::RangeFrom<usize>>,
2764    <I as InputIter>::Item: AsChar + Copy,
2765    E: nom::error::ContextError<I> + nom::error::ParseError<I>,
2766{
2767    move |input: I| match kind {
2768        BlockKind::Nested(kind) => lex_nested_block(kind).parse(input),
2769        BlockKind::Terminated(kind) => lex_terminated_block(kind).parse(input),
2770        BlockKind::Delimited(kind) => lex_delimited_block(kind).parse(input),
2771        BlockKind::Partial => {
2772            eprintln!("parser should not be seeking partial block kinds...");
2773            Err(nom::Err::Failure(E::from_error_kind(
2774                input,
2775                ErrorKind::IsNot,
2776            )))
2777        }
2778    }
2779}
2780
2781pub fn lex_terminated_block<I: Span, E>(
2782    kind: TerminatedBlockKind,
2783) -> impl FnMut(I) -> IResult<I, LexBlock<I>, E>
2784where
2785    I: ToString
2786        + InputLength
2787        + InputTake
2788        + Compare<&'static str>
2789        + InputIter
2790        + Clone
2791        + InputTakeAtPosition,
2792    <I as InputTakeAtPosition>::Item: AsChar,
2793    I: ToString,
2794    I: Offset + nom::Slice<std::ops::RangeTo<usize>>,
2795    I: nom::Slice<std::ops::RangeFrom<usize>>,
2796    <I as InputIter>::Item: AsChar,
2797    E: nom::error::ContextError<I> + nom::error::ParseError<I>,
2798{
2799    move |input: I| {
2800        terminated(
2801            recognize(many0(satisfy(|c| c != kind.as_char()))),
2802            tag(kind.tag()),
2803        )(input)
2804        .map(|(next, content)| {
2805            let block = LexBlock {
2806                kind: BlockKind::Terminated(kind),
2807                content,
2808                data: (),
2809            };
2810
2811            (next, block)
2812        })
2813    }
2814}
2815
2816/// rough block simply makes sure that the opening and closing symbols match
2817/// it accounts for multiple embedded blocks of the same kind but NOT of differing kinds
2818pub fn lex_nested_block<I: Span, E>(
2819    kind: NestedBlockKind,
2820) -> impl FnMut(I) -> IResult<I, LexBlock<I>, E>
2821where
2822    I: ToString
2823        + InputLength
2824        + InputTake
2825        + Compare<&'static str>
2826        + InputIter
2827        + Clone
2828        + InputTakeAtPosition,
2829    <I as InputTakeAtPosition>::Item: AsChar,
2830    I: ToString,
2831    I: Offset + nom::Slice<std::ops::RangeTo<usize>>,
2832    I: nom::Slice<std::ops::RangeFrom<usize>>,
2833    <I as InputIter>::Item: AsChar + Copy,
2834    E: nom::error::ContextError<I> + nom::error::ParseError<I>,
2835{
2836    move |input: I| {
2837        let (next, content) = context(
2838            kind.context(),
2839            delimited(
2840                context(kind.open_context(), tag(kind.open())),
2841                recognize(many0(alt((
2842                    recognize(lex_nested_block(kind.clone())),
2843                    recognize(tuple((
2844                        not(peek(tag(kind.close()))),
2845                        alt((recognize(pair(tag("\\"), anychar)), recognize(anychar))),
2846                    ))),
2847                )))),
2848                context(kind.close_context(), cut(tag(kind.close()))),
2849            ),
2850        )(input)?;
2851        let block = Block::parse(BlockKind::Nested(kind), content);
2852        Ok((next, block))
2853    }
2854}
2855
2856pub fn nested_block_content<I: Span>(kind: NestedBlockKind) -> impl FnMut(I) -> Res<I, I> {
2857    move |input: I| nested_block(kind)(input).map(|(next, block)| (next, block.content))
2858}
2859
2860pub fn nested_block<I: Span>(kind: NestedBlockKind) -> impl FnMut(I) -> Res<I, Block<I, ()>> {
2861    move |input: I| {
2862        let (next, content) = context(
2863            kind.context(),
2864            delimited(
2865                context(kind.open_context(), tag(kind.open())),
2866                recognize(many0(tuple((
2867                    not(peek(tag(kind.close()))),
2868                    context(
2869                        kind.unpaired_closing_scope(),
2870                        cut(peek(expected_block_terminator_or_non_terminator(
2871                            kind.clone(),
2872                        ))),
2873                    ),
2874                    alt((
2875                        recognize(pair(peek(block_open), any_block)),
2876                        recognize(anychar),
2877                    )),
2878                )))),
2879                context(kind.close_context(), cut(tag(kind.close()))),
2880            ),
2881        )(input)?;
2882        let block = Block::parse(BlockKind::Nested(kind), content);
2883        Ok((next, block))
2884    }
2885}
2886
2887pub fn lex_delimited_block<I: Span, E>(
2888    kind: DelimitedBlockKind,
2889) -> impl FnMut(I) -> IResult<I, LexBlock<I>, E>
2890where
2891    I: ToString
2892        + InputLength
2893        + InputTake
2894        + Compare<&'static str>
2895        + InputIter
2896        + Clone
2897        + InputTakeAtPosition,
2898    <I as InputTakeAtPosition>::Item: AsChar,
2899    I: ToString,
2900    I: Offset + nom::Slice<std::ops::RangeTo<usize>>,
2901    I: nom::Slice<std::ops::RangeFrom<usize>>,
2902    <I as InputIter>::Item: AsChar + Copy,
2903    E: nom::error::ContextError<I> + nom::error::ParseError<I>,
2904{
2905    move |input: I| {
2906        let (next, content) = context(
2907            kind.context(),
2908            delimited(
2909                context(kind.context(), tag(kind.delim())),
2910                recognize(many0(tuple((
2911                    not(peek(tag(kind.delim()))),
2912                    alt((recognize(pair(tag("\\"), anychar)), recognize(anychar))),
2913                )))),
2914                context(kind.missing_close_context(), cut(tag(kind.delim()))),
2915            ),
2916        )(input)?;
2917        let block = Block::parse(BlockKind::Delimited(kind), content);
2918        Ok((next, block))
2919    }
2920}
2921
2922fn block_open<I: Span>(input: I) -> Res<I, NestedBlockKind> {
2923    alt((
2924        value(NestedBlockKind::Curly, tag(NestedBlockKind::Curly.open())),
2925        value(NestedBlockKind::Angle, tag(NestedBlockKind::Angle.open())),
2926        value(NestedBlockKind::Parens, tag(NestedBlockKind::Parens.open())),
2927        value(NestedBlockKind::Square, tag(NestedBlockKind::Square.open())),
2928    ))(input)
2929}
2930
2931fn any_soround_lex_block<I: Span, E>(input: I) -> IResult<I, LexBlock<I>, E>
2932where
2933    I: ToString
2934        + InputLength
2935        + InputTake
2936        + Compare<&'static str>
2937        + InputIter
2938        + Clone
2939        + InputTakeAtPosition,
2940    <I as InputTakeAtPosition>::Item: AsChar,
2941    I: ToString,
2942    I: Offset + nom::Slice<std::ops::RangeTo<usize>>,
2943    I: nom::Slice<std::ops::RangeFrom<usize>>,
2944    <I as InputIter>::Item: AsChar + Copy,
2945    E: nom::error::ContextError<I> + nom::error::ParseError<I>,
2946{
2947    alt((
2948        lex_nested_block(NestedBlockKind::Curly),
2949        lex_nested_block(NestedBlockKind::Angle),
2950        lex_nested_block(NestedBlockKind::Parens),
2951        lex_nested_block(NestedBlockKind::Square),
2952        lex_delimited_block(DelimitedBlockKind::DoubleQuotes),
2953        lex_delimited_block(DelimitedBlockKind::SingleQuotes),
2954    ))(input)
2955}
2956
2957fn any_block<I: Span>(input: I) -> Res<I, LexBlock<I>> {
2958    alt((
2959        nested_block(NestedBlockKind::Curly),
2960        nested_block(NestedBlockKind::Angle),
2961        nested_block(NestedBlockKind::Parens),
2962        nested_block(NestedBlockKind::Square),
2963        lex_delimited_block(DelimitedBlockKind::DoubleQuotes),
2964        lex_delimited_block(DelimitedBlockKind::SingleQuotes),
2965    ))(input)
2966}
2967
2968pub fn expected_block_terminator_or_non_terminator<I: Span>(
2969    expect: NestedBlockKind,
2970) -> impl FnMut(I) -> Res<I, ()>
2971where
2972    I: InputIter + InputLength + Slice<RangeFrom<usize>>,
2973    <I as InputIter>::Item: AsChar,
2974    I: Clone,
2975{
2976    move |input: I| -> Res<I, ()> {
2977        verify(anychar, move |c| {
2978            if NestedBlockKind::is_block_terminator(*c) {
2979                *c == expect.close_as_char()
2980            } else {
2981                true
2982            }
2983        })(input)
2984        .map(|(next, _)| (next, ()))
2985    }
2986}
2987
2988/*
2989pub fn lex_hierarchy_scope<'a>(
2990    scope: LexScope<Span<'a>>,
2991    max_depth: usize,
2992) -> Result<LexHierarchyScope<'a>, ExtErr> {
2993    let mut errs = vec![];
2994    let scope = lex_child_scopes(scope)?;
2995    let mut children = vec![];
2996
2997    for child in scope.block {
2998        if max_depth <= 0 {
2999            let mut builder = Report::build(ReportKind::Error, (), 0);
3000            let report = builder
3001                .with_message("exceeded max depth hierarchy for nested scopes")
3002                .with_label(
3003                    Label::new(
3004                        child.block.content.location_offset()
3005                            ..child.block.content.location_offset() + child.block.content.len(),
3006                    )
3007                    .with_message("Nest Limit Exceeded"),
3008                )
3009                .finish();
3010            return Err(ParseErrs::new(report, child.block.content.extra.clone()).into());
3011        }
3012        match lex_hierarchy_scope(child, max_depth - 1) {
3013            Ok(child) => {
3014                children.push(child);
3015            }
3016            Err(err) => errs.push(err),
3017        }
3018    }
3019
3020    Ok(LexHierarchyScope::new(scope.selector.clone(), children))
3021}*/
3022
3023pub fn unwrap_block<I: Span, F, O>(kind: BlockKind, mut f: F) -> impl FnMut(I) -> Res<I, O>
3024where
3025    F: FnMut(I) -> Res<I, O>,
3026{
3027    move |input: I| {
3028        let (next, block) = lex_block(kind)(input)?;
3029        let (_, content) = f.parse(block.content)?;
3030        //        let (_, content) = context("block", f)(block.content)?;
3031        Ok((next, content))
3032    }
3033}
3034
3035pub fn lex_child_scopes<I: Span>(parent: LexScope<I>) -> Result<LexParentScope<I>, SpaceErr> {
3036    if parent.selector.children.is_some() {
3037        let (_, child_selector) = all_consuming(lex_scope_selector)(
3038            parent
3039                .selector
3040                .children
3041                .as_ref()
3042                .expect("child names...")
3043                .clone(),
3044        )?;
3045
3046        let child = LexScope::new(child_selector.into(), parent.block);
3047
3048        Ok(LexParentScope {
3049            selector: parent.selector.clone(),
3050            pipeline_step: None,
3051            block: vec![child],
3052        })
3053    } else {
3054        let scopes = lex_scopes(parent.block.content)?;
3055
3056        Ok(LexParentScope {
3057            selector: parent.selector.into(),
3058            pipeline_step: parent.pipeline_step,
3059            block: scopes,
3060        })
3061    }
3062}
3063
3064pub fn lex_scope<I: Span>(input: I) -> Res<I, LexScope<I>> {
3065    context(
3066        "scope",
3067        tuple((
3068            peek(alt((tag("*"), alpha1, tag("<")))),
3069            lex_scope_selector,
3070            multispace1,
3071            lex_scope_pipeline_step_and_block,
3072        )),
3073    )(input)
3074    .map(|(next, (_, selector, _, (pipeline_step, block)))| {
3075        let scope = LexScope {
3076            selector,
3077            pipeline_step,
3078            block,
3079        };
3080        (next, scope)
3081    })
3082}
3083
3084pub fn lex_scoped_block_kind<I: Span>(input: I) -> Res<I, BlockKind> {
3085    alt((
3086        value(
3087            BlockKind::Nested(NestedBlockKind::Curly),
3088            recognize(tuple((
3089                multispace0,
3090                rough_pipeline_step,
3091                multispace0,
3092                lex_block(BlockKind::Nested(NestedBlockKind::Curly)),
3093            ))),
3094        ),
3095        value(
3096            BlockKind::Terminated(TerminatedBlockKind::Semicolon),
3097            recognize(pair(
3098                rough_pipeline_step,
3099                lex_block(BlockKind::Terminated(TerminatedBlockKind::Semicolon)),
3100            )),
3101        ),
3102    ))(input)
3103}
3104
3105pub fn lex_scope_pipeline_step_and_block<I: Span>(input: I) -> Res<I, (Option<I>, LexBlock<I>)> {
3106    let (_, block_kind) = peek(lex_scoped_block_kind)(input.clone())?;
3107    match block_kind {
3108        BlockKind::Nested(_) => tuple((
3109            rough_pipeline_step,
3110            multispace1,
3111            lex_block(BlockKind::Nested(NestedBlockKind::Curly)),
3112        ))(input)
3113        .map(|(next, (step, _, block))| (next, (Some(step), block))),
3114        BlockKind::Terminated(_) => {
3115            lex_block(BlockKind::Terminated(TerminatedBlockKind::Semicolon))(input)
3116                .map(|(next, block)| (next, (None, block)))
3117        }
3118        _ => unimplemented!(),
3119    }
3120}
3121
3122pub fn lex_sub_scope_selectors_and_filters_and_block<I: Span>(input: I) -> Res<I, LexBlock<I>> {
3123    recognize(pair(
3124        nested_block_content(NestedBlockKind::Angle),
3125        tuple((
3126            opt(scope_filters),
3127            multispace0,
3128            opt(rough_pipeline_step),
3129            multispace0,
3130            lex_block_alt(vec![
3131                BlockKind::Nested(NestedBlockKind::Curly),
3132                BlockKind::Terminated(TerminatedBlockKind::Semicolon),
3133            ]),
3134        )),
3135    ))(input)
3136    .map(|(next, content)| {
3137        (
3138            next,
3139            LexBlock {
3140                kind: BlockKind::Partial,
3141                content,
3142                data: (),
3143            },
3144        )
3145    })
3146}
3147
3148pub fn root_scope<I: Span>(input: I) -> Res<I, LexRootScope<I>> {
3149    context(
3150        "root-scope",
3151        tuple((
3152            root_scope_selector,
3153            multispace0,
3154            context("root-scope:block", cut(peek(tag("{")))),
3155            context(
3156                "root-scope:block",
3157                cut(lex_nested_block(NestedBlockKind::Curly)),
3158            ),
3159        )),
3160    )(input)
3161    .map(|(next, (selector, _, _, block))| {
3162        let scope = LexRootScope::new(selector, block);
3163        (next, scope)
3164    })
3165}
3166
3167pub fn lex_scopes<I: Span>(input: I) -> Result<Vec<LexScope<I>>, SpaceErr> {
3168    if input.len() == 0 {
3169        return Ok(vec![]);
3170    }
3171
3172    if wrapper(input.clone(), all_consuming(multispace1)).is_ok() {
3173        return Ok(vec![]);
3174    }
3175
3176    result(
3177        context(
3178            "parsed-scopes",
3179            all_consuming(many0(delimited(
3180                multispace0,
3181                context(
3182                    "scope",
3183                    pair(peek(not(alt((tag("}"), eof)))), cut(lex_scope)),
3184                ),
3185                multispace0,
3186            ))),
3187        )(input)
3188        .map(|(next, scopes)| {
3189            let scopes: Vec<LexScope<I>> = scopes.into_iter().map(|scope| scope.1).collect();
3190            (next, scopes)
3191        }),
3192    )
3193}
3194
3195/*
3196pub fn sub_scope_selector<I:Span>(input: Span) -> Res<Span, ScopeSelector<Span>> {
3197    alt((sub_scope_selector_expanded, sub_scope_selector_collapsed))
3198}
3199
3200
3201
3202
3203pub fn lex_scope_selector_no_filters(
3204    input: Span,
3205) -> Res<Span, ParsedScopeSelectorAndFilters<Span>> {
3206    context("parsed-scope-selector-no-filters", lex_scope_selector)(input)
3207        .map(|(next, selector)| (next, ParsedScopeSelectorAndFilters::new(selector, vec![])))
3208}
3209
3210 */
3211
3212pub fn next_stacked_name<I: Span>(input: I) -> Res<I, (I, Option<I>)> {
3213    match wrapper(
3214        input.clone(),
3215        pair(
3216            peek(tag("<")),
3217            tuple((
3218                tag("<"),
3219                pair(
3220                    context("scope-selector", alt((alphanumeric1, tag("*")))),
3221                    opt(recognize(nested_block(NestedBlockKind::Angle))),
3222                ),
3223                tag(">"),
3224            )),
3225        ),
3226    )
3227    .map(|(next, (_, (_, (name, children), _)))| (next, (name, children)))
3228    {
3229        Ok((next, (name, children))) => return Ok((next, (name, children))),
3230        Err(_) => {}
3231    }
3232    pair(
3233        context("scope-selector", cut(alt((alphanumeric1, tag("*"))))),
3234        opt(recognize(nested_block(NestedBlockKind::Angle))),
3235    )(input)
3236}
3237
3238pub fn lex_scope_selector<I: Span>(input: I) -> Res<I, LexScopeSelector<I>> {
3239    let (next, ((name, children), filters, path)) = context(
3240        "parsed-scope-selector",
3241        tuple((next_stacked_name, scope_filters, opt(path_regex))),
3242    )(input.clone())?;
3243
3244    Ok((next, LexScopeSelector::new(name, filters, path, children)))
3245}
3246
3247pub fn lex_name_stack<I: Span>(mut input: I) -> Res<I, Vec<I>> {
3248    let mut stack = vec![];
3249    let (next, (name, mut children)) = next_stacked_name(input)?;
3250    stack.push(name);
3251    loop {
3252        match &children {
3253            None => {
3254                break;
3255            }
3256            Some(children) => {
3257                input = children.clone();
3258            }
3259        }
3260        let (_, (name, c)) = next_stacked_name(input)?;
3261        children = c;
3262        stack.push(name);
3263    }
3264
3265    Ok((next, stack))
3266}
3267
3268pub struct LexRouteSelector<I> {
3269    pub names: Vec<I>,
3270    pub filters: ScopeFiltersDef<I>,
3271    pub path: Option<I>,
3272}
3273
3274pub fn lex_route_selector<I: Span>(input: I) -> Res<I, LexRouteSelector<I>> {
3275    tuple((lex_name_stack, scope_filters, opt(path_regex)))(input).map(
3276        |(next, (names, filters, path))| {
3277            let selector = LexRouteSelector {
3278                names,
3279                filters,
3280                path,
3281            };
3282            (next, selector)
3283        },
3284    )
3285}
3286
3287pub fn wrapper<I: Span, O, F>(input: I, mut f: F) -> Res<I, O>
3288where
3289    F: FnMut(I) -> Res<I, O>,
3290{
3291    f.parse(input)
3292}
3293
3294pub fn parse_inner_block<I, E, F>(
3295    kind: NestedBlockKind,
3296    mut f: &F,
3297) -> impl FnMut(I) -> IResult<I, I, E> + '_
3298where
3299    I: Span,
3300    &'static str: FindToken<<I as InputTakeAtPosition>::Item>,
3301
3302    I: ToString
3303        + InputLength
3304        + InputTake
3305        + Compare<&'static str>
3306        + InputIter
3307        + Clone
3308        + InputTakeAtPosition,
3309    <I as InputTakeAtPosition>::Item: AsChar + Copy,
3310    I: ToString,
3311    I: Offset + nom::Slice<std::ops::RangeTo<usize>>,
3312    I: nom::Slice<std::ops::RangeFrom<usize>>,
3313    <I as InputIter>::Item: AsChar + Copy,
3314    E: nom::error::ContextError<I> + nom::error::ParseError<I>,
3315    F: Fn(char) -> bool,
3316    F: Clone,
3317{
3318    move |input: I| {
3319        let (next, rtn) = alt((
3320            delimited(
3321                tag(kind.open()),
3322                recognize(many1(alt((
3323                    recognize(any_soround_lex_block),
3324                    recognize(verify(anychar, move |c| {
3325                        f(*c) && *c != kind.close_as_char()
3326                    })),
3327                )))),
3328                tag(kind.close()),
3329            ),
3330            recognize(many1(verify(anychar, move |c| {
3331                f(*c) && *c != kind.close_as_char()
3332            }))),
3333        ))(input)?;
3334        Ok((next, rtn))
3335    }
3336}
3337
3338pub fn parse_include_blocks<I, O2, E, F>(
3339    kind: NestedBlockKind,
3340    mut f: F,
3341) -> impl FnMut(I) -> IResult<I, I, E>
3342where
3343    I: Span,
3344    &'static str: FindToken<<I as InputTakeAtPosition>::Item>,
3345
3346    I: ToString
3347        + InputLength
3348        + InputTake
3349        + Compare<&'static str>
3350        + InputIter
3351        + Clone
3352        + InputTakeAtPosition,
3353    <I as InputTakeAtPosition>::Item: AsChar,
3354    I: ToString,
3355    I: Offset + nom::Slice<std::ops::RangeTo<usize>>,
3356    I: nom::Slice<std::ops::RangeFrom<usize>>,
3357    <I as InputIter>::Item: AsChar,
3358    E: nom::error::ContextError<I> + nom::error::ParseError<I>,
3359    F: FnMut(I) -> IResult<I, O2, E>,
3360    F: Clone,
3361    <I as InputIter>::Item: std::marker::Copy,
3362{
3363    move |input: I| {
3364        recognize(many0(alt((
3365            recognize(any_soround_lex_block),
3366            recognize(verify(anychar, move |c| *c != kind.close_as_char())),
3367        ))))(input)
3368    }
3369}
3370
3371pub fn scope_filters<I: Span>(input: I) -> Res<I, ScopeFiltersDef<I>> {
3372    pair(opt(scope_filter), many0(preceded(tag("-"), scope_filter)))(input).map(
3373        |(next, (first, mut many_filters))| {
3374            let mut filters = vec![];
3375            match first {
3376                None => {}
3377                Some(first) => {
3378                    filters.push(first);
3379                }
3380            }
3381            filters.append(&mut many_filters);
3382            let filters = ScopeFiltersDef { filters };
3383            (next, filters)
3384        },
3385    )
3386}
3387
3388pub fn scope_filter<I: Span>(input: I) -> Res<I, ScopeFilterDef<I>> {
3389    delimited(
3390        tag("("),
3391        context(
3392            "scope-filter",
3393            cut(tuple((
3394                context("filter-name", cut(scope_name)),
3395                opt(context(
3396                    "filter-arguments",
3397                    preceded(
3398                        multispace1,
3399                        parse_include_blocks(NestedBlockKind::Parens, args),
3400                    ),
3401                )),
3402            ))),
3403        ),
3404        tag(")"),
3405    )(input)
3406    .map(|(next, (name, args))| {
3407        let filter = ScopeFilterDef { name, args };
3408        (next, filter)
3409    })
3410}
3411
3412pub fn scope_name<I>(input: I) -> Res<I, I>
3413where
3414    I: Span,
3415{
3416    recognize(pair(
3417        skewer_case_chars,
3418        peek(alt((eof, multispace1, tag(")")))),
3419    ))(input)
3420}
3421
3422pub fn root_scope_selector<I: Span>(input: I) -> Res<I, RootScopeSelector<I, Spanned<I, Version>>> {
3423    context(
3424        "root-scope-selector",
3425        cut(preceded(
3426            multispace0,
3427            pair(
3428                context("root-scope-selector:name", cut(root_scope_selector_name)),
3429                context("root-scope-selector:version", cut(scope_version)),
3430            ),
3431        )),
3432    )(input)
3433    .map(|(next, (name, version))| (next, RootScopeSelector { version, name }))
3434}
3435
3436pub fn scope_version<I: Span>(input: I) -> Res<I, Spanned<I, Version>> {
3437    context(
3438        "scope-selector-version",
3439        tuple((
3440            tag("(version="),
3441            sub(version),
3442            context("scope-selector-version-closing-tag", tag(")")),
3443        )),
3444    )(input)
3445    .map(|((next, (_, version, _)))| (next, version))
3446}
3447
3448/*
3449pub fn mytag<O>( tag: &str ) -> impl Fn(Span) -> Res<Span,O>
3450{
3451    move |i: Span| {
3452        let tag_len = tag.input_len();
3453        let t = tag.clone();
3454        let res: IResult<_, _, Error> = match i.compare(t) {
3455            CompareResult::Ok => Ok(i.take_split(tag_len)),
3456            _ => {
3457                let e: ErrorKind = ErrorKind::Tag;
3458                Err(Err::Error(Error::from_error_kind(i, e)))
3459            }
3460        };
3461        res
3462    }
3463}
3464
3465 */
3466
3467pub fn scope_selector_name<I: Span>(input: I) -> Res<I, I> {
3468    context(
3469        "scope-selector-name",
3470        delimited(
3471            (context(
3472                "scope-selector-name:expect-alphanumeric-leading",
3473                cut(peek(alpha1)),
3474            )),
3475            alphanumeric1,
3476            context(
3477                "scope-selector-name:expect-termination",
3478                cut(peek(alt((
3479                    multispace1,
3480                    tag("{"),
3481                    tag("("),
3482                    tag("<"),
3483                    tag(">"),
3484                )))),
3485            ),
3486        ),
3487    )(input)
3488    .map(|(next, name)| (next, name))
3489}
3490
3491pub fn root_scope_selector_name<I: Span>(input: I) -> Res<I, I> {
3492    context(
3493        "root-scope-selector-name",
3494        pair((peek(alpha1)), alphanumeric1),
3495    )(input)
3496    .map(|(next, (_, name))| (next, name))
3497}
3498
3499pub fn lex_root_scope<I: Span>(span: I) -> Result<LexRootScope<I>, SpaceErr> {
3500    let root_scope = result(delimited(multispace0, root_scope, multispace0)(span))?;
3501    Ok(root_scope)
3502}
3503
3504pub fn method_kind<I: Span>(input: I) -> Res<I, MethodKind> {
3505    let (next, v) = recognize(alt((tag("Cmd"), tag("Ext"), tag("Http"), tag("Hyp"))))(input)?;
3506    Ok((next, MethodKind::from_str(v.to_string().as_str()).unwrap()))
3507}
3508
3509pub mod model {
3510    use std::collections::HashMap;
3511    use std::fmt::{Formatter, Write};
3512    use std::marker::PhantomData;
3513    use std::ops::{Deref, DerefMut};
3514    use std::rc::Rc;
3515    use std::str::FromStr;
3516
3517    use bincode::Options;
3518    use nom::bytes::complete::tag;
3519    use nom::character::complete::{alphanumeric1, multispace0, multispace1, satisfy};
3520    use nom::combinator::{cut, fail, not, peek, recognize, value};
3521    use nom::sequence::delimited;
3522    use regex::Regex;
3523    use serde::de::Visitor;
3524    use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
3525
3526    use cosmic_nom::{new_span, Res, Span, Trace, Tw};
3527
3528    use crate::command::direct::CmdKind;
3529    use crate::config::bind::{
3530        BindConfig, PipelineStepCtx, PipelineStepDef, PipelineStepVar, PipelineStopCtx,
3531        PipelineStopDef, PipelineStopVar, WaveDirection,
3532    };
3533    use crate::err::{ParseErrs, SpaceErr};
3534    use crate::loc::Version;
3535    use crate::parse::error::result;
3536    use crate::parse::{
3537        Assignment, camel_case_chars, CtxResolver, Env, filepath_chars, http_method,
3538        lex_child_scopes, method_kind, pipeline, rc_command_type,
3539        ResolverErr, SubstParser, value_pattern, wrapped_cmd_method, wrapped_ext_method, wrapped_http_method,
3540        wrapped_sys_method,
3541    };
3542    use crate::point::{Point, PointCtx, PointVar};
3543    use crate::util::{HttpMethodPattern, StringMatcher, ToResolved, ValueMatcher, ValuePattern};
3544    use crate::wave::core::http2::HttpMethod;
3545    use crate::wave::core::{DirectedCore, Method, MethodKind};
3546    use crate::wave::{DirectedWave, Ping, SingularDirectedWave};
3547
3548    #[derive(Clone)]
3549    pub struct ScopeSelectorAndFiltersDef<S, I> {
3550        pub selector: S,
3551        pub filters: ScopeFiltersDef<I>,
3552    }
3553
3554    impl<S, I> Deref for ScopeSelectorAndFiltersDef<S, I> {
3555        type Target = S;
3556
3557        fn deref(&self) -> &Self::Target {
3558            &self.selector
3559        }
3560    }
3561
3562    impl<S, I> ScopeSelectorAndFiltersDef<S, I> {
3563        pub fn new(selector: S, filters: ScopeFiltersDef<I>) -> Self {
3564            Self { selector, filters }
3565        }
3566    }
3567
3568    pub enum ParsePhase {
3569        Root,
3570        SubScopes,
3571    }
3572
3573    #[derive(Clone)]
3574    pub struct Spanned<I, E>
3575    where
3576        E: Clone,
3577        I: ToString,
3578    {
3579        pub span: I,
3580        pub element: E,
3581    }
3582
3583    impl<I, E> Spanned<I, E>
3584    where
3585        E: Clone,
3586        I: ToString,
3587    {
3588        pub fn new(element: E, span: I) -> Spanned<I, E> {
3589            Self { span, element }
3590        }
3591    }
3592
3593    impl<I, E> Spanned<I, E>
3594    where
3595        E: Clone + ToString,
3596        I: ToString,
3597    {
3598        pub fn len(&self) -> usize {
3599            self.element.to_string().len()
3600        }
3601    }
3602
3603    impl<I, E> ToString for Spanned<I, E>
3604    where
3605        E: Clone + ToString,
3606        I: ToString,
3607    {
3608        fn to_string(&self) -> String {
3609            self.element.to_string()
3610        }
3611    }
3612
3613    impl<I, E> Deref for Spanned<I, E>
3614    where
3615        E: Clone,
3616        I: ToString,
3617    {
3618        type Target = E;
3619
3620        fn deref(&self) -> &Self::Target {
3621            &self.element
3622        }
3623    }
3624
3625    impl<I, E> DerefMut for Spanned<I, E>
3626    where
3627        E: Clone,
3628        I: ToString,
3629    {
3630        fn deref_mut(&mut self) -> &mut Self::Target {
3631            &mut self.element
3632        }
3633    }
3634
3635    #[derive(Clone, Eq, PartialEq, Hash)]
3636    pub struct RootScopeSelector<I, V> {
3637        pub name: I,
3638        pub version: V,
3639    }
3640
3641    impl<I, V> RootScopeSelector<I, V> {
3642        pub fn new(name: I, version: V) -> Self {
3643            RootScopeSelector { name, version }
3644        }
3645    }
3646
3647    impl<I: ToString, V: ToString> RootScopeSelector<I, V> {
3648        pub fn to_concrete(self) -> Result<RootScopeSelector<String, Version>, SpaceErr> {
3649            Ok(RootScopeSelector {
3650                name: self.name.to_string(),
3651                version: Version::from_str(self.version.to_string().as_str())?,
3652            })
3653        }
3654    }
3655
3656    impl RouteScope {
3657        pub fn select(&self, directed: &DirectedWave) -> Vec<&WaveScope> {
3658            let mut scopes = vec![];
3659            for scope in &self.block {
3660                if scope.selector.is_match(directed).is_ok() {
3661                    scopes.push(scope);
3662                }
3663            }
3664            scopes
3665        }
3666    }
3667
3668    #[derive(Clone)]
3669    pub struct RouteScopeSelector {
3670        pub selector: ScopeSelectorDef<String, Regex>,
3671    }
3672
3673    impl RouteScopeSelector {
3674        pub fn new<I: ToString>(path: Option<I>) -> Result<Self, SpaceErr> {
3675            let path = match path {
3676                None => Regex::new(".*")?,
3677                Some(path) => Regex::new(path.to_string().as_str())?,
3678            };
3679            Ok(Self {
3680                selector: ScopeSelectorDef {
3681                    path,
3682                    name: "Route".to_string(),
3683                },
3684            })
3685        }
3686
3687        pub fn from<I: ToString>(selector: LexScopeSelector<I>) -> Result<Self, SpaceErr> {
3688            if selector.name.to_string().as_str() != "Route" {
3689                return Err(SpaceErr::server_error("expected Route"));
3690            }
3691            let path = match selector.path {
3692                None => None,
3693                Some(path) => Some(path.to_string()),
3694            };
3695
3696            Ok(RouteScopeSelector::new(path)?)
3697        }
3698    }
3699
3700    impl Deref for RouteScopeSelector {
3701        type Target = ScopeSelectorDef<String, Regex>;
3702
3703        fn deref(&self) -> &Self::Target {
3704            &self.selector
3705        }
3706    }
3707
3708    #[derive(Clone)]
3709    pub struct ScopeSelectorDef<N, P> {
3710        pub name: N,
3711        pub path: P,
3712    }
3713
3714    impl ValueMatcher<DirectedWave> for RouteScopeSelector {
3715        fn is_match(&self, directed: &DirectedWave) -> Result<(), ()> {
3716            if self.name.as_str() != "Route" {
3717                return Err(());
3718            }
3719            match self.selector.path.is_match(&directed.core().uri.path()) {
3720                true => Ok(()),
3721                false => Err(()),
3722            }
3723        }
3724    }
3725
3726    impl ValueMatcher<SingularDirectedWave> for RouteScopeSelector {
3727        fn is_match(&self, directed: &SingularDirectedWave) -> Result<(), ()> {
3728            if self.name.as_str() != "Route" {
3729                return Err(());
3730            }
3731            match self.selector.path.is_match(&directed.core().uri.path()) {
3732                true => Ok(()),
3733                false => Err(()),
3734            }
3735        }
3736    }
3737
3738    impl ValueMatcher<DirectedWave> for MessageScopeSelector {
3739        fn is_match(&self, directed: &DirectedWave) -> Result<(), ()> {
3740            self.name.is_match(&directed.core().method.kind())?;
3741            match self.path.is_match(&directed.core().uri.path()) {
3742                true => Ok(()),
3743                false => Err(()),
3744            }
3745        }
3746    }
3747
3748    impl ValueMatcher<SingularDirectedWave> for MessageScopeSelector {
3749        fn is_match(&self, directed: &SingularDirectedWave) -> Result<(), ()> {
3750            self.name.is_match(&directed.core().method.kind())?;
3751            match self.path.is_match(&directed.core().uri.path()) {
3752                true => Ok(()),
3753                false => Err(()),
3754            }
3755        }
3756    }
3757
3758    fn default_path<I: ToString>(path: Option<I>) -> Result<Regex, SpaceErr> {
3759        match path {
3760            None => Ok(Regex::new(".*")?),
3761            Some(path) => Ok(Regex::new(path.to_string().as_str())?),
3762        }
3763    }
3764    impl WaveScope {
3765        pub fn from_scope<I: Span>(scope: LexParentScope<I>) -> Result<Self, SpaceErr> {
3766            let selector = MessageScopeSelectorAndFilters::from_selector(scope.selector)?;
3767            let mut block = vec![];
3768
3769            for scope in scope.block.into_iter() {
3770                let method = MethodScope::from_scope(&selector.selector.name, scope)?;
3771                block.push(method);
3772            }
3773
3774            Ok(Self { selector, block })
3775        }
3776
3777        pub fn select(&self, directed: &DirectedWave) -> Vec<&MethodScope> {
3778            let mut scopes = vec![];
3779            for scope in &self.block {
3780                if scope.selector.is_match(directed).is_ok() {
3781                    scopes.push(scope);
3782                }
3783            }
3784            scopes
3785        }
3786    }
3787
3788    impl MessageScopeSelectorAndFilters {
3789        pub fn from_selector<I: Span>(selector: LexScopeSelector<I>) -> Result<Self, SpaceErr> {
3790            let filters = selector.filters.clone().to_scope_filters();
3791            let selector = MessageScopeSelector::from_selector(selector)?;
3792            Ok(Self { selector, filters })
3793        }
3794    }
3795
3796    impl RouteScopeSelectorAndFilters {
3797        pub fn from_selector<I: Span>(selector: LexScopeSelector<I>) -> Result<Self, SpaceErr> {
3798            let filters = selector.filters.clone().to_scope_filters();
3799            let selector = RouteScopeSelector::new(selector.path.clone())?;
3800            Ok(Self { selector, filters })
3801        }
3802    }
3803
3804    impl ValueMatcher<DirectedWave> for RouteScopeSelectorAndFilters {
3805        fn is_match(&self, request: &DirectedWave) -> Result<(), ()> {
3806            // nothing for filters at this time...
3807            self.selector.is_match(request)
3808        }
3809    }
3810
3811    impl ValueMatcher<SingularDirectedWave> for RouteScopeSelectorAndFilters {
3812        fn is_match(&self, wave: &SingularDirectedWave) -> Result<(), ()> {
3813            // nothing for filters at this time...
3814            self.selector.is_match(wave)
3815        }
3816    }
3817
3818    impl ValueMatcher<DirectedWave> for MessageScopeSelectorAndFilters {
3819        fn is_match(&self, request: &DirectedWave) -> Result<(), ()> {
3820            // nothing for filters at this time...
3821            self.selector.is_match(request)
3822        }
3823    }
3824
3825    impl ValueMatcher<SingularDirectedWave> for MessageScopeSelectorAndFilters {
3826        fn is_match(&self, request: &SingularDirectedWave) -> Result<(), ()> {
3827            // nothing for filters at this time...
3828            self.selector.is_match(request)
3829        }
3830    }
3831
3832    impl ValueMatcher<DirectedWave> for MethodScopeSelectorAndFilters {
3833        fn is_match(&self, directed: &DirectedWave) -> Result<(), ()> {
3834            // nothing for filters at this time...
3835            self.selector.is_match(directed)
3836        }
3837    }
3838
3839    impl ValueMatcher<SingularDirectedWave> for MethodScopeSelectorAndFilters {
3840        fn is_match(&self, directed: &SingularDirectedWave) -> Result<(), ()> {
3841            // nothing for filters at this time...
3842            self.selector.is_match(directed)
3843        }
3844    }
3845
3846    impl MethodScope {
3847        pub fn from_scope<I: Span>(
3848            parent: &ValuePattern<MethodKind>,
3849            scope: LexScope<I>,
3850        ) -> Result<Self, SpaceErr> {
3851            let selector = MethodScopeSelectorAndFilters::from_selector(parent, scope.selector)?;
3852            let block = result(pipeline(scope.block.content))?;
3853            Ok(Self { selector, block })
3854        }
3855    }
3856
3857    impl MessageScopeSelector {
3858        pub fn from_selector<I: Span>(selector: LexScopeSelector<I>) -> Result<Self, SpaceErr> {
3859            let kind = match result(value_pattern(method_kind)(selector.name.clone())) {
3860                Ok(kind) => kind,
3861                Err(_) => {
3862                    return Err(ParseErrs::from_loc_span(
3863                        format!(
3864                            "unknown MessageKind: {} valid message kinds: Ext, Http, Cmd or *",
3865                            selector.name.to_string()
3866                        )
3867                        .as_str(),
3868                        "unknown message kind",
3869                        selector.name,
3870                    ));
3871                }
3872            };
3873
3874            Ok(Self {
3875                name: kind,
3876                path: default_path(selector.path)?,
3877            })
3878        }
3879    }
3880
3881    impl ValueMatcher<DirectedWave> for MethodScopeSelector {
3882        fn is_match(&self, directed: &DirectedWave) -> Result<(), ()> {
3883            self.name.is_match(&directed.core().method)?;
3884            match self.path.is_match(&directed.core().uri.path()) {
3885                true => Ok(()),
3886                false => Err(()),
3887            }
3888        }
3889    }
3890
3891    impl ValueMatcher<SingularDirectedWave> for MethodScopeSelector {
3892        fn is_match(&self, directed: &SingularDirectedWave) -> Result<(), ()> {
3893            self.name.is_match(&directed.core().method)?;
3894            match self.path.is_match(&directed.core().uri.path()) {
3895                true => Ok(()),
3896                false => Err(()),
3897            }
3898        }
3899    }
3900    impl MethodScopeSelectorAndFilters {
3901        pub fn from_selector<I: Span>(
3902            parent: &ValuePattern<MethodKind>,
3903            selector: LexScopeSelector<I>,
3904        ) -> Result<Self, SpaceErr> {
3905            let filters = selector.filters.clone().to_scope_filters();
3906            let selector = MethodScopeSelector::from_selector(parent, selector)?;
3907            Ok(Self { selector, filters })
3908        }
3909    }
3910
3911    impl MethodScopeSelector {
3912        pub fn from_selector<I: Span>(
3913            parent: &ValuePattern<MethodKind>,
3914            selector: LexScopeSelector<I>,
3915        ) -> Result<Self, SpaceErr> {
3916            let name = match parent {
3917                ValuePattern::Any => ValuePattern::Any,
3918                ValuePattern::None => ValuePattern::None,
3919                ValuePattern::Pattern(message_kind) => match message_kind {
3920                    MethodKind::Hyp => {
3921                        match result(value_pattern(wrapped_sys_method)(selector.name.clone())) {
3922                            Ok(r) => r,
3923                            Err(_) => {
3924                                return Err(ParseErrs::from_loc_span(
3925                                    format!(
3926                                        "invalid Hyp method '{}'.  Hyp should be CamelCase",
3927                                        selector.name.to_string()
3928                                    )
3929                                    .as_str(),
3930                                    "invalid Hyp",
3931                                    selector.name,
3932                                ))
3933                            }
3934                        }
3935                    }
3936                    MethodKind::Cmd => {
3937                        match result(value_pattern(wrapped_cmd_method)(selector.name.clone())) {
3938                            Ok(r) => r,
3939                            Err(_) => {
3940                                return Err(ParseErrs::from_loc_span(
3941                                    format!(
3942                                        "invalid Cmd method '{}'.  Cmd should be CamelCase",
3943                                        selector.name.to_string()
3944                                    )
3945                                    .as_str(),
3946                                    "invalid Cmd",
3947                                    selector.name,
3948                                ))
3949                            }
3950                        }
3951                    }
3952                    MethodKind::Ext => {
3953                        match result(value_pattern(wrapped_ext_method)(selector.name.clone())) {
3954                            Ok(r) => r,
3955                            Err(_) => {
3956                                return Err(ParseErrs::from_loc_span(
3957                                    format!(
3958                                        "invalid Ext method '{}'.  Ext should be CamelCase",
3959                                        selector.name.to_string()
3960                                    )
3961                                    .as_str(),
3962                                    "invalid Ext",
3963                                    selector.name,
3964                                ))
3965                            }
3966                        }
3967                    }
3968                    MethodKind::Http => {
3969                        match result(value_pattern( wrapped_http_method)(selector.name.clone())) {
3970                                Ok(r) => r,
3971                                Err(_) => {
3972                                    return Err(ParseErrs::from_loc_span(format!("invalid Http Pattern '{}'.  Http should be camel case 'Get' and a valid Http method", selector.name.to_string()).as_str(), "invalid Http method", selector.name ))
3973                                }
3974                            }
3975                    }
3976                },
3977            };
3978
3979            Ok(Self {
3980                name,
3981                path: default_path(selector.path)?,
3982            })
3983        }
3984    }
3985
3986    impl<N, P> ScopeSelectorDef<N, P> {
3987        pub fn new(name: N, path: P) -> Self {
3988            Self { name, path }
3989        }
3990    }
3991
3992    #[derive(Clone)]
3993    pub struct LexScopeSelector<I> {
3994        pub name: I,
3995        pub filters: ScopeFiltersDef<I>,
3996        pub children: Option<I>,
3997        pub path: Option<I>,
3998    }
3999
4000    impl<I: ToString> LexScopeSelector<I> {
4001        pub fn new(
4002            name: I,
4003            filters: ScopeFiltersDef<I>,
4004            path: Option<I>,
4005            children: Option<I>,
4006        ) -> Self {
4007            Self {
4008                name,
4009                filters,
4010                children,
4011                path,
4012            }
4013        }
4014    }
4015
4016    impl<I> LexScopeSelector<I> {
4017        pub fn has_children(&self) -> bool {
4018            self.children.is_some()
4019        }
4020    }
4021
4022    #[derive(Clone)]
4023    pub struct ScopeFiltersDef<I> {
4024        pub filters: Vec<ScopeFilterDef<I>>,
4025    }
4026
4027    impl Default for ScopeFilters {
4028        fn default() -> Self {
4029            Self { filters: vec![] }
4030        }
4031    }
4032
4033    impl<I> Deref for ScopeFiltersDef<I> {
4034        type Target = Vec<ScopeFilterDef<I>>;
4035
4036        fn deref(&self) -> &Self::Target {
4037            &self.filters
4038        }
4039    }
4040
4041    impl<I> ScopeFiltersDef<I> {
4042        pub fn is_empty(&self) -> bool {
4043            self.filters.is_empty()
4044        }
4045    }
4046
4047    impl<I: ToString> ScopeFiltersDef<I> {
4048        pub fn to_scope_filters(self) -> ScopeFilters {
4049            ScopeFilters {
4050                filters: self
4051                    .filters
4052                    .into_iter()
4053                    .map(|f| f.to_scope_filter())
4054                    .collect(),
4055            }
4056        }
4057
4058        pub fn len(&self) -> usize {
4059            self.filters.len()
4060        }
4061
4062        pub fn empty() -> Self {
4063            Self { filters: vec![] }
4064        }
4065    }
4066
4067    #[derive(Clone)]
4068    pub struct ScopeFilterDef<I> {
4069        pub name: I,
4070        pub args: Option<I>,
4071    }
4072
4073    impl<I: ToString> ScopeFilterDef<I> {
4074        pub fn to_scope_filter(self) -> ScopeFilter {
4075            ScopeFilter {
4076                name: self.name.to_string(),
4077                args: match self.args {
4078                    None => None,
4079                    Some(args) => Some(args.to_string()),
4080                },
4081            }
4082        }
4083    }
4084
4085    pub type RegexStr = String;
4086    pub type ScopeFilter = ScopeFilterDef<String>;
4087    pub type ScopeFilters = ScopeFiltersDef<String>;
4088    pub type LexBlock<I> = Block<I, ()>;
4089    pub type LexRootScope<I> = Scope<RootScopeSelector<I, Spanned<I, Version>>, Block<I, ()>, I>;
4090    pub type LexScope<I> = Scope<LexScopeSelector<I>, Block<I, ()>, I>;
4091    pub type LexParentScope<I> = Scope<LexScopeSelector<I>, Vec<LexScope<I>>, I>;
4092
4093    //pub type LexPipelineScope<I> = PipelineScopeDef<I, VarPipeline>;
4094    pub type PipelineSegmentCtx = PipelineSegmentDef<PointCtx>;
4095    pub type PipelineSegmentVar = PipelineSegmentDef<PointVar>;
4096
4097    #[derive(Debug, Clone)]
4098    pub struct PipelineSegmentDef<Pnt> {
4099        pub step: PipelineStepDef<Pnt>,
4100        pub stop: PipelineStopDef<Pnt>,
4101    }
4102
4103    impl ToResolved<PipelineSegment> for PipelineSegmentVar {
4104        fn to_resolved(self, env: &Env) -> Result<PipelineSegment, SpaceErr> {
4105            let rtn: PipelineSegmentCtx = self.to_resolved(env)?;
4106            rtn.to_resolved(env)
4107        }
4108    }
4109
4110    impl ToResolved<PipelineSegment> for PipelineSegmentCtx {
4111        fn to_resolved(self, env: &Env) -> Result<PipelineSegment, SpaceErr> {
4112            Ok(PipelineSegment {
4113                step: self.step.to_resolved(env)?,
4114                stop: self.stop.to_resolved(env)?,
4115            })
4116        }
4117    }
4118
4119    impl ToResolved<PipelineSegmentCtx> for PipelineSegmentVar {
4120        fn to_resolved(self, env: &Env) -> Result<PipelineSegmentCtx, SpaceErr> {
4121            Ok(PipelineSegmentCtx {
4122                step: self.step.to_resolved(env)?,
4123                stop: self.stop.to_resolved(env)?,
4124            })
4125        }
4126    }
4127
4128    /*
4129    impl CtxSubst<PipelineSegment> for PipelineSegmentCtx{
4130        fn resolve_ctx(self, resolver: &dyn CtxResolver) -> Result<PipelineSegment, ExtErr> {
4131            let mut errs = vec![];
4132            let step = match self.step.resolve_ctx(resolver) {
4133                Ok(step) => Some(step),
4134                Err(err) => {
4135                    errs.push(err);
4136                    None
4137                }
4138            };
4139            let stop = match self.stop.resolve_ctx(resolver) {
4140                Ok(stop) => Some(stop),
4141                Err(err) => {
4142                    errs.push(err);
4143                    None
4144                }
4145            };
4146            if errs.is_empty() {
4147                Ok(PipelineSegment {
4148                    step: step.expect("step"),
4149                    stop: stop.expect("stop")
4150                })
4151            } else {
4152                Err(ParseErrs::fold(errs).into())
4153            }
4154        }
4155    }
4156
4157     */
4158
4159    pub type PipelineSegment = PipelineSegmentDef<Point>;
4160    pub type RouteScope = ScopeDef<RouteScopeSelectorAndFilters, Vec<WaveScope>>;
4161    pub type WaveScope = ScopeDef<MessageScopeSelectorAndFilters, Vec<MethodScope>>;
4162    pub type MethodScope = ScopeDef<MethodScopeSelectorAndFilters, PipelineVar>;
4163    //    pub type ValuePatternScopeSelector = ScopeSelectorDef<ValuePattern<String>, String,Regex>;
4164    pub type MessageScopeSelector = ScopeSelectorDef<ValuePattern<MethodKind>, Regex>;
4165    pub type MethodScopeSelector = ScopeSelectorDef<ValuePattern<Method>, Regex>;
4166    pub type RouteScopeSelectorAndFilters = ScopeSelectorAndFiltersDef<RouteScopeSelector, String>;
4167    pub type MessageScopeSelectorAndFilters =
4168        ScopeSelectorAndFiltersDef<MessageScopeSelector, String>;
4169    pub type MethodScopeSelectorAndFilters =
4170        ScopeSelectorAndFiltersDef<MethodScopeSelector, String>;
4171
4172    /*    pub type ValuePatternScopeSelectorAndFilters =
4173           ScopeSelectorAndFiltersDef<ValuePatternScopeSelector, String>;
4174
4175    */
4176    pub type LexScopeSelectorAndFilters<I> = ScopeSelectorAndFiltersDef<LexScopeSelector<I>, I>;
4177    //    pub type Pipeline = Vec<PipelineSegment>;
4178
4179    impl<I: Span> TryFrom<LexParentScope<I>> for RouteScope {
4180        type Error = SpaceErr;
4181
4182        fn try_from(scope: LexParentScope<I>) -> Result<Self, Self::Error> {
4183            let mut errs = vec![];
4184            let mut message_scopes = vec![];
4185            let route_selector = RouteScopeSelectorAndFilters::from_selector(scope.selector)?;
4186            for message_scope in scope.block {
4187                match lex_child_scopes(message_scope) {
4188                    Ok(message_scope) => match WaveScope::from_scope(message_scope) {
4189                        Ok(message_scope) => message_scopes.push(message_scope),
4190                        Err(err) => errs.push(err),
4191                    },
4192                    Err(err) => {
4193                        errs.push(err);
4194                    }
4195                }
4196            }
4197            if errs.is_empty() {
4198                Ok(RouteScope {
4199                    selector: route_selector,
4200                    block: message_scopes,
4201                })
4202            } else {
4203                Err(ParseErrs::fold(errs).into())
4204            }
4205        }
4206    }
4207
4208    /*
4209    impl<I: Span> LexScopeSelectorAndFilters<I> {
4210        pub fn to_value_pattern_scope_selector(
4211            self,
4212        ) -> Result<ValuePatternScopeSelectorAndFilters, ExtErr> {
4213            Ok(ValuePatternScopeSelectorAndFilters {
4214                selector: self.selector.to_value_pattern_scope_selector()?,
4215                filters: self.filters.to_scope_filters(),
4216            })
4217        }
4218    }
4219
4220     */
4221
4222    /*
4223    #[derive(Debug, Clone, Serialize, Deserialize)]
4224    pub struct VarPipelineSegmentDef<Step, Stop> {
4225        pub step: Step,
4226        pub stop: Stop,
4227    }
4228
4229    #[derive(Debug, Clone, Serialize, Deserialize)]
4230    pub struct PipelineSegmentDef<Pnt> {
4231        pub step: PipelineStepDef<Pnt>,
4232        pub stop: PipelineStopDef<Pnt>,
4233    }
4234
4235     */
4236
4237    pub type Pipeline = PipelineDef<PipelineSegment>;
4238    pub type PipelineCtx = PipelineDef<PipelineSegmentCtx>;
4239    pub type PipelineVar = PipelineDef<PipelineSegmentVar>;
4240
4241    impl ToResolved<Pipeline> for PipelineCtx {
4242        fn to_resolved(self, env: &Env) -> Result<Pipeline, SpaceErr> {
4243            let mut segments = vec![];
4244            for segment in self.segments.into_iter() {
4245                segments.push(segment.to_resolved(env)?);
4246            }
4247
4248            Ok(Pipeline { segments })
4249        }
4250    }
4251
4252    impl ToResolved<PipelineCtx> for PipelineVar {
4253        fn to_resolved(self, env: &Env) -> Result<PipelineCtx, SpaceErr> {
4254            let mut segments = vec![];
4255            for segment in self.segments.into_iter() {
4256                segments.push(segment.to_resolved(env)?);
4257            }
4258
4259            Ok(PipelineCtx { segments })
4260        }
4261    }
4262
4263    /*
4264    impl CtxSubst<Pipeline> for PipelineCtx {
4265        fn resolve_ctx(self, resolver: &dyn CtxResolver) -> Result<Pipeline, ExtErr> {
4266            let mut errs = vec![];
4267            let mut segments = vec![];
4268            for segment in self.segments {
4269                match segment.resolve_ctx(resolver) {
4270                    Ok(segment) => segments.push(segment),
4271                    Err(err) => errs.push(err)
4272                }
4273            }
4274            if errs.is_empty() {
4275                Ok( Pipeline { segments })
4276            } else {
4277                Err(ParseErrs::fold(errs).into())
4278            }
4279        }
4280    }
4281
4282     */
4283
4284    #[derive(Debug, Clone, Serialize, Deserialize)]
4285    pub struct PipelineDef<S> {
4286        pub segments: Vec<S>,
4287    }
4288
4289    impl<S> PipelineDef<S> {
4290        pub fn new() -> Self {
4291            Self { segments: vec![] }
4292        }
4293    }
4294
4295    impl<S> Deref for PipelineDef<S> {
4296        type Target = Vec<S>;
4297
4298        fn deref(&self) -> &Self::Target {
4299            &self.segments
4300        }
4301    }
4302
4303    impl<S> DerefMut for PipelineDef<S> {
4304        fn deref_mut(&mut self) -> &mut Self::Target {
4305            &mut self.segments
4306        }
4307    }
4308
4309    impl<S> PipelineDef<S> {
4310        pub fn consume(&mut self) -> Option<S> {
4311            if self.segments.is_empty() {
4312                None
4313            } else {
4314                Some(self.segments.remove(0))
4315            }
4316        }
4317    }
4318
4319    /*
4320    impl <I:Span> VarSubst<PipelineCtx> for VarPipeline<I> {
4321        fn resolve_vars(self, resolver: &dyn VarResolver) -> Result<PipelineCtx, ExtErr> {
4322            let mut pipeline = PipelineCtx::new();
4323            let mut errs = vec![];
4324            for segment in self.segments {
4325                match segment.resolve_vars(resolver) {
4326                    Ok(segment) => {
4327                        pipeline.segments.push(segment);
4328                    }
4329                    Err(err) => {
4330                        errs.push(err);
4331                    }
4332                }
4333            }
4334
4335            if errs.is_empty() {
4336                Ok(pipeline)
4337            } else {
4338                Err(ParseErrs::fold(errs).into())
4339            }
4340        }
4341    }
4342
4343     */
4344
4345    /*
4346    impl <I:Span> VarSubst<PipelineSegmentCtx> for VarPipelineSegment<I> {
4347        fn resolve_vars(self, resolver: &dyn VarResolver) -> Result<PipelineSegmentCtx, ExtErr> {
4348            unimplemented!()
4349            /*
4350            let mut errs = vec![];
4351
4352            if self.stop.is_none() {
4353                errs.push(ParseErrs::from_owned_span(
4354                    "expecting Pipeline Stop to follow Pipeline Step",
4355                    "Needs a following Pipeline Stop",
4356                    self.step.span(),
4357                ));
4358            }
4359
4360            let step = match self.step.resolve(resolver) {
4361                Ok(step) => Some(step),
4362                Err(err) => {
4363                    errs.push(err);
4364                    None
4365                }
4366            };
4367
4368            let stop = match self.stop {
4369                Some(stop) => match stop.resolve(resolver) {
4370                    Ok(stop) => Some(stop),
4371                    Err(err) => {
4372                        errs.push(err);
4373                        None
4374                    }
4375                },
4376                None => None,
4377            };
4378
4379            if step.is_some() && stop.is_some() && errs.is_empty() {
4380                let step = step.expect("step");
4381                let stop = stop.expect("stop");
4382                Ok(PipelineSegmentCtx { step, stop })
4383            } else {
4384                Err(ParseErrs::fold(errs).into())
4385            }
4386
4387             */
4388        }
4389    }
4390
4391     */
4392
4393    #[derive(Clone)]
4394    pub enum MechtronScope {
4395        WasmScope(Vec<Assignment>),
4396    }
4397
4398    #[derive(Clone)]
4399    pub enum BindScope {
4400        RequestScope(RouteScope),
4401    }
4402
4403    #[derive(Debug, Clone)]
4404    pub struct ScopeDef<S, B> {
4405        pub selector: S,
4406        pub block: B,
4407    }
4408
4409    #[derive(Clone)]
4410    pub enum BindScopeKind {
4411        Pipelines,
4412    }
4413
4414    #[derive(Clone)]
4415    pub enum BuiltInFilter {
4416        Auth,
4417        NoAuth,
4418    }
4419
4420    #[derive(Clone)]
4421    pub struct Scope<S, B, P>
4422    where
4423        S: Clone,
4424    {
4425        pub selector: S,
4426        pub pipeline_step: Option<P>,
4427        pub block: B,
4428    }
4429
4430    impl<S, B, P> Scope<S, B, P>
4431    where
4432        S: Clone,
4433    {
4434        pub fn new(selector: S, block: B) -> Self {
4435            Self {
4436                selector,
4437                block,
4438                pipeline_step: None,
4439            }
4440        }
4441
4442        pub fn new_with_pipeline_step(selector: S, block: B, pipeline_step: Option<P>) -> Self {
4443            Self {
4444                selector,
4445                block,
4446                pipeline_step,
4447            }
4448        }
4449    }
4450
4451    impl<S, FromBlock, P> Scope<S, FromBlock, P>
4452    where
4453        S: Clone,
4454    {
4455        pub fn upgrade<ToBlock>(self, block: ToBlock) -> Scope<S, ToBlock, P> {
4456            Scope {
4457                selector: self.selector,
4458                block,
4459                pipeline_step: self.pipeline_step,
4460            }
4461        }
4462    }
4463
4464    #[derive(Clone)]
4465    pub struct Block<I, D> {
4466        pub kind: BlockKind,
4467        pub content: I,
4468        pub data: D,
4469    }
4470
4471    impl<I> Block<I, ()> {
4472        pub fn parse(kind: BlockKind, content: I) -> Block<I, ()> {
4473            Block {
4474                kind,
4475                content,
4476                data: (),
4477            }
4478        }
4479    }
4480
4481    #[derive(Debug, Copy, Clone, strum_macros::Display, Eq, PartialEq)]
4482    pub enum BlockKind {
4483        Nested(NestedBlockKind),
4484        Terminated(TerminatedBlockKind),
4485        Delimited(DelimitedBlockKind),
4486        Partial,
4487    }
4488
4489    #[derive(Debug, Copy, Clone, strum_macros::Display, Eq, PartialEq)]
4490    pub enum TerminatedBlockKind {
4491        Semicolon,
4492    }
4493
4494    impl TerminatedBlockKind {
4495        pub fn tag(&self) -> &'static str {
4496            match self {
4497                TerminatedBlockKind::Semicolon => ";",
4498            }
4499        }
4500
4501        pub fn as_char(&self) -> char {
4502            match self {
4503                TerminatedBlockKind::Semicolon => ';',
4504            }
4505        }
4506    }
4507
4508    #[derive(
4509        Debug, Copy, Clone, strum_macros::Display, strum_macros::EnumString, Eq, PartialEq,
4510    )]
4511    pub enum DelimitedBlockKind {
4512        SingleQuotes,
4513        DoubleQuotes,
4514    }
4515
4516    impl DelimitedBlockKind {
4517        pub fn delim(&self) -> &'static str {
4518            match self {
4519                DelimitedBlockKind::SingleQuotes => "'",
4520                DelimitedBlockKind::DoubleQuotes => "\"",
4521            }
4522        }
4523
4524        pub fn escaped(&self) -> &'static str {
4525            match self {
4526                DelimitedBlockKind::SingleQuotes => "\'",
4527                DelimitedBlockKind::DoubleQuotes => "\"",
4528            }
4529        }
4530
4531        pub fn context(&self) -> &'static str {
4532            match self {
4533                DelimitedBlockKind::SingleQuotes => "single:quotes:block",
4534                DelimitedBlockKind::DoubleQuotes => "double:quotes:block",
4535            }
4536        }
4537
4538        pub fn missing_close_context(&self) -> &'static str {
4539            match self {
4540                DelimitedBlockKind::SingleQuotes => "single:quotes:block:missing-close",
4541                DelimitedBlockKind::DoubleQuotes => "double:quotes:block:missing-close",
4542            }
4543        }
4544    }
4545
4546    #[derive(
4547        Debug, Copy, Clone, strum_macros::Display, strum_macros::EnumString, Eq, PartialEq,
4548    )]
4549    pub enum NestedBlockKind {
4550        Curly,
4551        Parens,
4552        Square,
4553        Angle,
4554    }
4555
4556    impl NestedBlockKind {
4557        pub fn is_block_terminator(c: char) -> bool {
4558            match c {
4559                '}' => true,
4560                ')' => true,
4561                ']' => true,
4562                '>' => true,
4563                _ => false,
4564            }
4565        }
4566
4567        pub fn error_message<I: Span>(span: &I, context: &str) -> Result<&'static str, ()> {
4568            if Self::Curly.open_context() == context {
4569                Ok("expecting '{' (open scope block)")
4570            } else if Self::Parens.open_context() == context {
4571                Ok("expecting '(' (open scope block)")
4572            } else if Self::Angle.open_context() == context {
4573                Ok("expecting '<' (open scope block)")
4574            } else if Self::Square.open_context() == context {
4575                Ok("expecting '[' (open scope block)")
4576            } else if Self::Curly.close_context() == context {
4577                Ok("expecting '}' (close scope block)")
4578            } else if Self::Parens.close_context() == context {
4579                Ok("expecting ')' (close scope block)")
4580            } else if Self::Angle.close_context() == context {
4581                Ok("expecting '>' (close scope block)")
4582            } else if Self::Square.close_context() == context {
4583                Ok("expecting ']' (close scope block)")
4584            } else if Self::Curly.unpaired_closing_scope() == context {
4585                Ok("closing scope without an opening scope")
4586            } else if Self::Parens.unpaired_closing_scope() == context {
4587                Ok("closing scope without an opening scope")
4588            } else if Self::Angle.unpaired_closing_scope() == context {
4589                Ok("closing scope without an opening scope")
4590            } else if Self::Square.unpaired_closing_scope() == context {
4591                Ok("closing scope without an opening scope")
4592            } else {
4593                Err(())
4594            }
4595        }
4596
4597        pub fn context(&self) -> &'static str {
4598            match self {
4599                NestedBlockKind::Curly => "block:{}",
4600                NestedBlockKind::Parens => "block:()",
4601                NestedBlockKind::Square => "block:[]",
4602                NestedBlockKind::Angle => "block:<>",
4603            }
4604        }
4605
4606        pub fn open_context(&self) -> &'static str {
4607            match self {
4608                NestedBlockKind::Curly => "block:open:{",
4609                NestedBlockKind::Parens => "block:open:(",
4610                NestedBlockKind::Square => "block:open:[",
4611                NestedBlockKind::Angle => "block:open:<",
4612            }
4613        }
4614
4615        pub fn close_context(&self) -> &'static str {
4616            match self {
4617                NestedBlockKind::Curly => "block:close:}",
4618                NestedBlockKind::Parens => "block:close:)",
4619                NestedBlockKind::Square => "block:close:]",
4620                NestedBlockKind::Angle => "block:close:>",
4621            }
4622        }
4623
4624        pub fn unpaired_closing_scope(&self) -> &'static str {
4625            match self {
4626                NestedBlockKind::Curly => "block:close-before-open:}",
4627                NestedBlockKind::Parens => "block:close-before-open:)",
4628                NestedBlockKind::Square => "block:close-before-open:]",
4629                NestedBlockKind::Angle => "block:close-before-open:>",
4630            }
4631        }
4632
4633        pub fn open(&self) -> &'static str {
4634            match self {
4635                NestedBlockKind::Curly => "{",
4636                NestedBlockKind::Parens => "(",
4637                NestedBlockKind::Square => "[",
4638                NestedBlockKind::Angle => "<",
4639            }
4640        }
4641
4642        pub fn close(&self) -> &'static str {
4643            match self {
4644                NestedBlockKind::Curly => "}",
4645                NestedBlockKind::Parens => ")",
4646                NestedBlockKind::Square => "]",
4647                NestedBlockKind::Angle => ">",
4648            }
4649        }
4650
4651        pub fn open_as_char(&self) -> char {
4652            match self {
4653                NestedBlockKind::Curly => '{',
4654                NestedBlockKind::Parens => '(',
4655                NestedBlockKind::Square => '[',
4656                NestedBlockKind::Angle => '<',
4657            }
4658        }
4659
4660        pub fn close_as_char(&self) -> char {
4661            match self {
4662                NestedBlockKind::Curly => '}',
4663                NestedBlockKind::Parens => ')',
4664                NestedBlockKind::Square => ']',
4665                NestedBlockKind::Angle => '>',
4666            }
4667        }
4668    }
4669
4670    pub enum TextType<I> {
4671        Comment(I),
4672        NoComment(I),
4673    }
4674
4675    impl<I: ToString> ToString for TextType<I> {
4676        fn to_string(&self) -> String {
4677            match self {
4678                TextType::Comment(i) => i.to_string(),
4679                TextType::NoComment(i) => i.to_string(),
4680            }
4681        }
4682    }
4683
4684    #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
4685    pub enum Chunk<I> {
4686        Var(I),
4687        Text(I),
4688    }
4689    impl<I> Chunk<I>
4690    where
4691        I: Span,
4692    {
4693        pub fn stringify(self) -> Chunk<Tw<String>> {
4694            match self {
4695                Chunk::Var(var) => Chunk::Var(Tw::new(var.clone(), var.to_string())),
4696                Chunk::Text(text) => Chunk::Text(Tw::new(text.clone(), text.to_string())),
4697            }
4698        }
4699    }
4700
4701    impl<I> Chunk<I> {
4702        pub fn span(&self) -> &I {
4703            match self {
4704                Chunk::Var(var) => var,
4705                Chunk::Text(text) => text,
4706            }
4707        }
4708    }
4709
4710    impl<I: ToString> Chunk<I> {
4711        pub fn len(&self) -> usize {
4712            match self {
4713                Chunk::Var(var) => {
4714                    // account for ${}
4715                    var.to_string().len() + 3
4716                }
4717                Chunk::Text(text) => text.to_string().len(),
4718            }
4719        }
4720    }
4721
4722    #[derive(Clone)]
4723    pub enum Var<O, P>
4724    where
4725        P: VarParser<O>,
4726    {
4727        Val(O),
4728        Var { name: String, parser: P },
4729    }
4730
4731    pub trait VarParser<O> {
4732        fn parse<I: Span>(input: I) -> Result<O, SpaceErr>;
4733    }
4734
4735    #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
4736    pub struct Subst<I> {
4737        pub chunks: Vec<Chunk<I>>,
4738        pub trace: Trace,
4739    }
4740
4741    impl Subst<Tw<String>> {
4742        pub fn new(path: &str) -> Result<Self, SpaceErr> {
4743            let path = result(crate::parse::subst_path(new_span(path)))?;
4744            Ok(path.stringify())
4745        }
4746    }
4747
4748    impl<I> Subst<I>
4749    where
4750        I: Span,
4751    {
4752        pub fn stringify(self) -> Subst<Tw<String>> {
4753            let chunks: Vec<Chunk<Tw<String>>> =
4754                self.chunks.into_iter().map(|c| c.stringify()).collect();
4755            Subst {
4756                chunks,
4757                trace: self.trace,
4758            }
4759        }
4760    }
4761
4762    impl<I> ToString for Subst<I>
4763    where
4764        I: ToString,
4765    {
4766        fn to_string(&self) -> String {
4767            let mut rtn = String::new();
4768            for chunk in &self.chunks {
4769                match chunk {
4770                    Chunk::Var(var) => {
4771                        rtn.push_str(format!("${{{}}}", var.to_string()).as_str());
4772                    }
4773                    Chunk::Text(text) => {
4774                        rtn.push_str(text.to_string().as_str());
4775                    }
4776                }
4777            }
4778            rtn
4779        }
4780    }
4781
4782    impl ToResolved<String> for Subst<Tw<String>> {
4783        fn to_resolved(self, env: &Env) -> Result<String, SpaceErr> {
4784            let mut rtn = String::new();
4785            let mut errs = vec![];
4786            for chunk in self.chunks {
4787                match chunk {
4788                    Chunk::Var(var) => match env.val(var.to_string().as_str()) {
4789                        Ok(val) => {
4790                            let val: String = val.clone().try_into()?;
4791                            rtn.push_str(val.as_str());
4792                        }
4793                        Err(err) => {
4794                            errs.push(ParseErrs::from_range(
4795                                format!("could not find variable: {}", var.to_string()).as_str(),
4796                                "not found",
4797                                var.trace.range,
4798                                var.trace.extra,
4799                            ));
4800                        }
4801                    },
4802                    Chunk::Text(text) => {
4803                        rtn.push_str(text.to_string().as_str());
4804                    }
4805                }
4806            }
4807
4808            if errs.is_empty() {
4809                Ok(rtn)
4810            } else {
4811                let errs = ParseErrs::fold(errs);
4812                Err(errs.into())
4813            }
4814        }
4815    }
4816}
4817
4818pub mod error {
4819    use core::str::FromStr;
4820    use std::collections::HashMap;
4821    use std::sync::Arc;
4822    //    use ariadne::Report;
4823    //    use ariadne::{Label, ReportKind, Source};
4824    use nom::branch::alt;
4825    use nom::bytes::complete::tag;
4826    use nom::character::complete::{
4827        alpha1, alphanumeric0, alphanumeric1, digit1, multispace0, multispace1, satisfy, space1,
4828    };
4829    use nom::combinator::{all_consuming, cut, fail, not, opt, peek, recognize, value};
4830    use nom::error::{context, ContextError, ErrorKind, ParseError};
4831    use nom::multi::{many0, many1, separated_list0};
4832    use nom::sequence::{delimited, pair, preceded, terminated, tuple};
4833    use nom::{
4834        AsChar, Compare, Err, InputLength, InputTake, InputTakeAtPosition, IResult, Parser, Slice,
4835    };
4836    use nom_supreme::error::{BaseErrorKind, ErrorTree, StackContext};
4837    use regex::{Error, Regex};
4838
4839    use cosmic_nom::{len, new_span, Res, Span, span_with_extra, trim, tw};
4840
4841    use crate::command::direct::CmdKind;
4842    use crate::command::CommandVar;
4843    use crate::config::bind::{PipelineStepVar, PipelineStopVar, RouteSelector, WaveDirection};
4844    use crate::err::report::{Label, Report, ReportKind};
4845    use crate::err::{ParseErrs, SpaceErr};
4846    use crate::kind::KindParts;
4847    use crate::loc::{Layer, StarKey, Topic, VarVal, Version};
4848    use crate::parse::model::{
4849        BindScope, BindScopeKind, BlockKind, Chunk, DelimitedBlockKind, LexScope, NestedBlockKind,
4850        PipelineSegmentVar, PipelineVar, RouteScope, Spanned, Subst, TextType,
4851    };
4852    use crate::parse::{
4853        any_block, any_soround_lex_block, camel_case, camel_case_chars,
4854        camel_case_to_string_matcher, CamelCase, domain, file_chars, filepath_chars, get,
4855        lex_child_scopes, lex_root_scope, lex_route_selector, lex_scopes, lowercase_alphanumeric,
4856        method_kind, nospace1, parse_uuid, point_segment_chars, point_var, rec_version, select, set,
4857        skewer, skewer_case, skewer_chars, subst_path, SubstParser, unwrap_block,
4858        variable_name, version_chars, version_req_chars,
4859    };
4860    use crate::particle::PointKindVar;
4861    use crate::selector::{
4862        ExactPointSeg, Hop, KindBaseSelector, KindSelector, LabeledPrimitiveTypeDef,
4863        MapEntryPattern, MapEntryPatternVar, Pattern, PatternBlockVar, PayloadBlockVar,
4864        PayloadType2Def, PointSegSelector, SelectorDef, SpecificSelector, SubKindSelector,
4865        UploadBlock, VersionReq,
4866    };
4867    use crate::substance::{
4868        CallKind, CallVar, CallWithConfigVar, ExtCall, HttpCall, ListPattern, MapPatternVar,
4869        NumRange, SubstanceFormat, SubstanceKind, SubstancePattern, SubstancePatternVar,
4870        SubstanceTypePatternDef, SubstanceTypePatternVar,
4871    };
4872    use crate::util::{HttpMethodPattern, StringMatcher, ToResolved, ValuePattern};
4873    use crate::wave::core::cmd::CmdMethod;
4874    use crate::wave::core::ext::ExtMethod;
4875    use crate::wave::core::http2::HttpMethod;
4876    use crate::wave::core::hyp::HypMethod;
4877    use crate::wave::core::{Method, MethodKind, MethodPattern};
4878    use crate::{
4879        ArtifactSubKind, BaseKind, BindConfig, Document, FileSubKind, Kind, Selector, Specific,
4880        StarSub, Strategy, Surface,
4881    };
4882    use crate::point::{PointSeg, PointVar};
4883
4884    pub fn result<I: Span, R>(result: Result<(I, R), Err<ErrorTree<I>>>) -> Result<R, SpaceErr> {
4885        match result {
4886            Ok((_, e)) => Ok(e),
4887            Err(err) => Err(find_parse_err(&err)),
4888        }
4889    }
4890
4891    /*
4892    pub fn just_msg<R, E: From<String>>(
4893        result: Result<(Span, R), Err<ErrorTree<Span>>>,
4894    ) -> Result<R, E> {
4895        match result {
4896            Ok((_, e)) => Ok(e),
4897            Err(err) => match find(&err) {
4898                Ok((message, _)) => Err(E::from(message)),
4899                Err(err) => Err(E::from(err)),
4900            },
4901        }
4902    }
4903
4904     */
4905
4906    fn create_err_report<I: Span>(context: &str, loc: I) -> SpaceErr {
4907        let mut builder = Report::build(ReportKind::Error, (), 23);
4908
4909        match NestedBlockKind::error_message(&loc, context) {
4910            Ok(message) => {
4911                let builder = builder.with_message(message).with_label(
4912                    Label::new(loc.location_offset()..loc.location_offset()).with_message(message),
4913                );
4914                return ParseErrs::from_report(builder.finish(), loc.extra()).into();
4915            }
4916            Err(_) => {}
4917        }
4918
4919        let builder = match context {
4920                "var" => {
4921                    let f = |input| {preceded(tag("$"),many0(alt((tag("{"),alphanumeric1,tag("-"),tag("_"),multispace1))))(input)};
4922                    let len = len(f)(loc.clone())+1;
4923                    builder.with_message("Variables should be lowercase skewer with a leading alphabet character and surrounded by ${} i.e.:'${var-name}' ").with_label(Label::new(loc.location_offset()..loc.location_offset()+len).with_message("Bad Variable Substitution"))
4924                },
4925                "assignment:plus" => {
4926                    builder.with_message("Expecting a preceding '+' (create variable operator)").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("expected '+'"))
4927                }
4928                "assignment:equals" => {
4929                    builder.with_message("Expecting a preceding '=' for assignment").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("expecting '='"))
4930                }
4931                "assignment:value" => {
4932                    builder.with_message("Expecting a value").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("expecting value"))
4933                }
4934                "capture-path" => {
4935                    builder.with_message("Invalid capture path. Legal characters are filesystem characters plus captures $(var=.*) i.e. /users/$(user=.*)").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("Illegal capture path"))
4936
4937                }
4938                "point" => {
4939                        builder.with_message("Invalid Point").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("Invalid Point"))
4940                    },
4941
4942                "resolver-not-available" => {
4943                    builder.with_message("Var & Working Point resolution are not available in this context").with_label(Label::new(loc.location_offset()..loc.location_offset()+loc.len()).with_message("resolution not available"))
4944                }
4945                "var-resolver-not-available" => {
4946                    builder.with_message("Variable resolution is not available in this context").with_label(Label::new(loc.location_offset()..loc.location_offset()+loc.len()).with_message("var resolution not available"))
4947                }
4948                "ctx-resolver-not-available" => {
4949                    builder.with_message("WorkingPoint resolution is not available in this context").with_label(Label::new(loc.location_offset()..loc.location_offset()+loc.len()).with_message("working point resolution not available"))
4950                }
4951
4952                "regex" => {
4953                    let span = result(nospace1(loc.clone()));
4954                            match span {
4955                                Ok(span) => {
4956                                    match Regex::new(loc.to_string().as_str()) {
4957                                        Ok(_) => {
4958                                            builder.with_message("internal parse error: regex error in this expression")
4959                                        }
4960                                        Err(err) => {
4961                                            match err {
4962                                                Error::Syntax(syntax) => {
4963                                                    builder.with_message(format!("Regex Syntax Error: '{}'",syntax)).with_label(Label::new(span.location_offset()..span.location_offset()+span.len()).with_message("regex syntax error"))
4964                                                }
4965                                                Error::CompiledTooBig(size) => {
4966                                                    builder.with_message("Regex compiled too big").with_label(Label::new(span.location_offset()..span.location_offset()+span.len()).with_message("regex compiled too big"))
4967                                                }
4968                                                _ => {
4969
4970                                                    builder.with_message("Regex is nonexhaustive").with_label(Label::new(span.location_offset()..span.location_offset()+span.len()).with_message("non-exhaustive regex"))
4971
4972                                                }
4973                                            }
4974                                        }
4975                                    }
4976                                }
4977                        Err(_) => {
4978                            builder.with_message("internal parse error: could not identify regex")
4979                        }
4980                    }
4981                },
4982                "expect-camel-case" => { builder.with_message("expecting a CamelCase expression").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("expecting CamelCase"))},
4983                "expect-skewer-case" => { builder.with_message("expecting a skewer-case expression").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("expecting skewer-case"))},
4984                "parsed-scopes" => { builder.with_message("expecting a properly formed scope").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("not a scope"))},
4985                "scope" => { builder.with_message("expecting a properly formed scope").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("not a scope"))},
4986                "root-scope:block" => { builder.with_message("expecting root scope block {}").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("Expecting Scope Block"))},
4987                "pipeline:stop:expecting" =>{ builder.with_message("expecting a pipeline stop: point, call, or return ('&')").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("Expecting Pipeline Stop"))},
4988                "pipeline:step" =>{ builder.with_message("expecting a pipeline step ('->', '=>', '-[ Bin ]->', etc...)").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("Expecting Pipeline Step"))},
4989                "pipeline:step:entry" =>{ builder.with_message("expecting a pipeline step entry ('-' or '=') to form a pipeline step i.e. '->' or '=>'").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("Expecting Pipeline Entry"))},
4990                "pipeline:step:exit" =>{ builder.with_message("expecting a pipeline step exit i.e. '->' or '=>'").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("Expecting Pipeline Exit"))},
4991                "pipeline:step:payload" =>{ builder.with_message("Invalid payload filter").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("invalid payload filter"))},
4992                "scope:expect-space-after-pipeline-step" =>{ builder.with_message("expecting a space after selection pipeline step (->)").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("Expecting Space"))},
4993                "scope-selector-name:expect-alphanumeric-leading" => { builder.with_message("expecting a valid scope selector name starting with an alphabetic character").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("Expecting Alpha Char"))},
4994                "scope-selector-name:expect-termination" => { builder.with_message("expecting scope selector to be followed by a space, a filter declaration: '(filter)->' or a sub scope selector: '<SubScope> or subscope terminator '>' '").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("Bad Scope Selector Termination"))},
4995                "scope-selector-version-closing-tag" =>{ builder.with_message("expecting a closing parenthesis for the root version declaration (no spaces allowed) -> i.e. Bind(version=1.0.0)->").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("missing closing parenthesis"))}
4996                "scope-selector-version-missing-kazing"=> { builder.with_message("The version declaration needs a little style.  Try adding a '->' to it.  Make sure there are no spaces between the parenthesis and the -> i.e. Bind(version=1.0.0)->").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("missing stylish arrow"))}
4997                "scope-selector-version" => { builder.with_message("Root config selector requires a version declaration with NO SPACES between the name and the version filter example: Bind(version=1.0.0)->").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("bad version declaration"))}
4998                "scope-selector-name" => { builder.with_message("Expecting an alphanumeric scope selector name. example: Pipeline").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("expecting scope selector"))}
4999                "root-scope-selector-name" => { builder.with_message("Expecting an alphanumeric root scope selector name and version. example: Bind(version=1.0.0)->").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("expecting scope selector"))}
5000                "consume" => { builder.with_message("Expected to be able to consume the entire String")}
5001                "point:space_segment:dot_dupes" => { builder.with_message("Space Segment cannot have consecutive dots i.e. '..'").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("Consecutive dots not allowed"))}
5002                "point:version:root_not_trailing" =>{ builder.with_message("Root filesystem is the only segment allowed to follow a bundle version i.e. 'space:base:2.0.0-version:/dir/somefile.txt'").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("Only root file segment ':/' allowed here"))}
5003                "point:space_segment_leading" => {builder.with_message("The leading character of a Space segment must be a lowercase letter").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("Invalid Leading Character"))}
5004                "point:space_segment" => {builder.with_message("A Point Space Segment must be all lowercase, alphanumeric with dashes and dots.  It follows Host and Domain name rules i.e. 'localhost', 'mechtron.io'").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("Invalid Space Segment"))}
5005                "point:bad_leading" => {builder.with_message("The leading character must be a lowercase letter (for Base Segments) or a digit (for Version Segments)").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("Invalid Leading Character"))}
5006                "point:base_segment" => {builder.with_message("A Point Base Segment must be 'skewer-case': all lowercase alphanumeric with dashes. The leading character must be a letter.").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("Invalid Base Segment Character"))}
5007                "point:dir_pop" => {builder.with_message("A Point Directory Pop '..'").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("Something is Wrong"))}
5008                "point:dir_segment" => {builder.with_message("A Point Dir Segment follows legal filesystem characters and must end in a '/'").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("Illegal Character"))}
5009                "point:root_filesystem_segment" => {builder.with_message("Root FileSystem ':/'").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("Illegal Character"))}
5010                "point:file_segment" => {builder.with_message("A Point File Segment follows legal filesystem characters").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("Illegal Character"))}
5011                "point:file_or_directory"=> {builder.with_message("A Point File Segment (Files & Directories) follows legal filesystem characters").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("Illegal Character"))}
5012                "point:version_segment" => {builder.with_message("A Version Segment allows all legal SemVer characters").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("Illegal Character"))}
5013                "filter-name" => {builder.with_message("Filter name must be skewer case with leading character").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("Invalid filter name"))}
5014                "kind-base" => {builder.with_message("Invalid Base Kind").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("Base Kind not recognized"))}
5015            "command" => {builder.with_message("Unrecognized Command").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("Invalid"))}
5016                "parsed-scope-selector-kazing" => {builder.with_message("Selector needs some style with the '->' operator either right after the Selector i.e.: 'Pipeline ->' or as part of the filter declaration i.e. 'Pipeline(auth)->'").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("Missing or Invalid Kazing Operator( -> )"))}
5017                "variable" => {
5018                        builder.with_message("variable name must be alphanumeric lowercase, dashes and dots.  Variables are preceded by the '$' operator and must be sorounded by curly brackets ${env.valid-variable-name}")
5019                    },
5020                "variable:close" => {
5021                    builder.with_message("variable name must be alphanumeric lowercase, dashes and dots.  Variables are preceded by the '$' operator and must be sorounded by curly brackets with no spaces ${env.valid-variable-name}").with_label(Label::new(loc.location_offset()..loc.location_offset()).with_message("Bad Variable Substitution"))
5022                },
5023
5024                "child_perms" => {
5025                        builder.with_message("expecting child permissions form csd (Create, Select, Delete) uppercase indicates set permission (CSD==full permission, csd==no permission)")
5026                    },
5027                    "particle_perms" => {
5028                        builder.with_message("expecting particle permissions form rwx (Read, Write, Execute) uppercase indicates set permission (RWX==full permission, rwx==no permission)")
5029                    },
5030                    "permissions" => {
5031                        builder.with_message("expecting permissions form 'csd-rwx' (Create,Select,Delete)-(Read,Write,Execute) uppercase indicates set permission (CSD-RWX==full permission, csd-rwx==no permission)")
5032                    }
5033                    "permissions_mask" => {
5034                        builder.with_message("expecting permissions mask symbol '+' for 'Or' mask and '&' for 'And' mask. Example:  &csd-RwX removes ----R-X from current permission")
5035                    }
5036                    "privilege" => {
5037                        builder.with_message("privilege name must be '*' for 'full' privileges or an alphanumeric lowercase, dashes and colons i.e. 'props:email:read'")
5038                    },
5039                    "access_grant:perm" => {
5040                        builder.with_message("expecting permissions mask symbol '+' for 'Or' mask and '&' for 'And' mask. Example:  &csd-RwX removes ----R-X from current permission")
5041                    },
5042                    "access_grant:priv" => {
5043                        builder.with_message("privilege name must be '*' for 'full' privileges or an alphanumeric lowercase, dashes and colons i.e. 'props:email:read'")
5044                    },
5045                    "access_grant:on" => {
5046                        builder.with_message("expecting grant 'on' i.e.: 'grant perm +cSd+RwX on localhost:app:** to localhost:app:users:**<User>'")
5047                    },
5048                    "access_grant:to" => {
5049                        builder.with_message("expecting grant 'to' i.e.: 'grant perm +cSd+RwX on localhost:app:** to localhost:app:users:**<User>'")
5050                    },
5051                    "point-subst-brute-force" => {
5052                        builder.with_message("not expecting variables or working point context '.'/'..' in this point")
5053                    },
5054                    "access_grant_kind" => {
5055                        builder.with_message("expecting access grant kind ['super','perm','priv']")
5056                    },
5057
5058                    what => {
5059                        builder.with_message(format!("internal parser error: cannot determine an error message for parse context: {}",what))
5060                    }
5061                };
5062
5063        //            let source = String::from_utf8(loc.get_line_beginning().to_vec() ).unwrap_or("could not parse utf8 of original source".to_string() );
5064        ParseErrs::from_report(builder.finish(), loc.extra()).into()
5065    }
5066    pub fn find_parse_err<I: Span>(err: &Err<ErrorTree<I>>) -> SpaceErr {
5067        match err {
5068            Err::Incomplete(_) => "internal parser error: Incomplete".into(),
5069            Err::Error(err) => find_tree(err),
5070            Err::Failure(err) => find_tree(err),
5071        }
5072    }
5073
5074    pub enum ErrFind {
5075        Context(String),
5076        Message(String),
5077    }
5078
5079    pub fn find_tree<I: Span>(err: &ErrorTree<I>) -> SpaceErr {
5080        match err {
5081            ErrorTree::Stack { base, contexts } => {
5082                let (span, context) = contexts.first().unwrap();
5083                match context {
5084                        StackContext::Context(context) => {
5085                            create_err_report(*context, span.clone())
5086                        }
5087                        _ => "internal parser error: could not find a parse context in order to generate a useful error message".into()
5088                    }
5089            }
5090            ErrorTree::Base { location, kind } => create_err_report("eof", location.clone()),
5091            ErrorTree::Alt(alts) => {
5092                for alt in alts {
5093                    return find_tree(alt);
5094                }
5095
5096                "internal parser error: ErrorTree::Alt could not find a suitable context error in the various alts".into()
5097            }
5098        }
5099    }
5100
5101    pub fn first_context<I: Span>(
5102        orig: Err<ErrorTree<I>>,
5103    ) -> Result<(String, Err<ErrorTree<I>>), ()> {
5104        match &orig {
5105            Err::Error(err) => match err {
5106                ErrorTree::Stack { base, contexts } => {
5107                    let (_, context) = contexts.first().unwrap();
5108                    match context {
5109                        StackContext::Context(context) => Ok((context.to_string(), orig)),
5110                        _ => Err(()),
5111                    }
5112                }
5113                _ => Err(()),
5114            },
5115            _ => Err(()),
5116        }
5117    }
5118}
5119
5120fn inclusive_any_segment<I: Span>(input: I) -> Res<I, PointSegSelector> {
5121    alt((tag("+*"), tag("ROOT+*")))(input).map(|(next, _)| (next, PointSegSelector::InclusiveAny))
5122}
5123
5124fn inclusive_recursive_segment<I: Span>(input: I) -> Res<I, PointSegSelector> {
5125    alt((tag("+**"), tag("ROOT+**")))(input)
5126        .map(|(next, _)| (next, PointSegSelector::InclusiveRecursive))
5127}
5128
5129fn any_segment<I: Span>(input: I) -> Res<I, PointSegSelector> {
5130    tag("*")(input).map(|(next, _)| (next, PointSegSelector::Any))
5131}
5132
5133fn recursive_segment<I: Span>(input: I) -> Res<I, PointSegSelector> {
5134    tag("**")(input).map(|(next, _)| (next, PointSegSelector::Recursive))
5135}
5136
5137fn exact_space_segment<I: Span>(input: I) -> Res<I, PointSegSelector> {
5138    point_segment_chars(input).map(|(next, segment)| {
5139        (
5140            next,
5141            PointSegSelector::Exact(ExactPointSeg::PointSeg(PointSeg::Space(
5142                segment.to_string(),
5143            ))),
5144        )
5145    })
5146}
5147
5148fn exact_base_segment<I: Span>(input: I) -> Res<I, PointSegSelector> {
5149    point_segment_chars(input).map(|(next, segment)| {
5150        (
5151            next,
5152            PointSegSelector::Exact(ExactPointSeg::PointSeg(PointSeg::Base(segment.to_string()))),
5153        )
5154    })
5155}
5156
5157fn exact_file_segment<I: Span>(input: I) -> Res<I, PointSegSelector> {
5158    file_chars(input).map(|(next, segment)| {
5159        (
5160            next,
5161            PointSegSelector::Exact(ExactPointSeg::PointSeg(PointSeg::File(segment.to_string()))),
5162        )
5163    })
5164}
5165
5166fn exact_dir_segment<I: Span>(input: I) -> Res<I, PointSegSelector> {
5167    file_chars(input).map(|(next, segment)| {
5168        (
5169            next,
5170            PointSegSelector::Exact(ExactPointSeg::PointSeg(PointSeg::Dir(segment.to_string()))),
5171        )
5172    })
5173}
5174
5175pub fn parse_version_chars_str<I: Span, O: FromStr>(input: I) -> Res<I, O> {
5176    let (next, rtn) = recognize(version_chars)(input)?;
5177    match O::from_str(rtn.to_string().as_str()) {
5178        Ok(rtn) => Ok((next, rtn)),
5179        Err(err) => Err(nom::Err::Error(ErrorTree::from_error_kind(
5180            next,
5181            ErrorKind::Fail,
5182        ))),
5183    }
5184}
5185
5186fn exact_version_segment<I: Span>(input: I) -> Res<I, PointSegSelector> {
5187    version_req(input).map(|(next, version_req)| (next, PointSegSelector::Version(version_req)))
5188}
5189
5190fn version_req_segment<I: Span>(input: I) -> Res<I, PointSegSelector> {
5191    delimited(tag("("), version_req, tag(")"))(input)
5192        .map(|(next, version_req)| (next, PointSegSelector::Version(version_req)))
5193}
5194
5195pub fn point_segment_selector<I: Span>(input: I) -> Res<I, PointSegSelector> {
5196    alt((
5197        inclusive_recursive_segment,
5198        inclusive_any_segment,
5199        recursive_segment,
5200        any_segment,
5201        exact_space_segment,
5202    ))(input)
5203}
5204
5205fn base_segment<I: Span>(input: I) -> Res<I, PointSegSelector> {
5206    alt((recursive_segment, any_segment, exact_base_segment))(input)
5207}
5208
5209fn file_segment<I: Span>(input: I) -> Res<I, PointSegSelector> {
5210    alt((recursive_segment, any_segment, exact_file_segment))(input)
5211}
5212
5213fn dir_segment<I: Span>(input: I) -> Res<I, PointSegSelector> {
5214    terminated(
5215        alt((recursive_segment, any_segment, exact_dir_segment)),
5216        tag("/"),
5217    )(input)
5218}
5219
5220fn dir_segment_meat<I: Span>(input: I) -> Res<I, PointSegSelector> {
5221    alt((recursive_segment, any_segment, exact_dir_segment))(input)
5222}
5223
5224fn version_segment<I: Span>(input: I) -> Res<I, PointSegSelector> {
5225    alt((
5226        recursive_segment,
5227        any_segment,
5228        exact_version_segment,
5229        version_req_segment,
5230    ))(input)
5231}
5232
5233/*
5234pub fn pattern<'r, O, E: ParseError<&'r str>, V>(
5235    mut value: V,
5236) -> impl FnMut(&'r str) -> IResult<&str, Pattern<O>, E>
5237where
5238    V: Parser<&'r str, O, E>,
5239{
5240    move |input: &str| {
5241        let x: Res<Span, Span> = tag("*")(input);
5242        match x {
5243            Ok((next, _)) => Ok((next, Pattern::Any)),
5244            Err(_) => {
5245                let (next, p) = value.parse(input)?;
5246                let pattern = Pattern::Exact(p);
5247                Ok((next, pattern))
5248            }
5249        }
5250    }
5251}
5252
5253 */
5254pub fn parse_star_key<I: Span>(input: I) -> Res<I, StarKey> {
5255    let (next, (_, constelation, _, name, index)) = context(
5256        "star",
5257        tuple((
5258            tag("STAR::"),
5259            lowercase_alphanumeric,
5260            tag(":"),
5261            lowercase_alphanumeric,
5262            delimited(tag("["), digit1, tag("]")),
5263        )),
5264    )(input.clone())?;
5265    let constelation = constelation.to_string();
5266    let name = name.to_string();
5267    let index = match index.to_string().parse::<u16>() {
5268        Ok(index) => index,
5269        Err(err) => {
5270            return Err(nom::Err::Failure(ErrorTree::from_error_kind(
5271                input,
5272                ErrorKind::Digit,
5273            )))
5274        }
5275    };
5276
5277    Ok((
5278        next,
5279        StarKey {
5280            constellation: constelation,
5281            name,
5282            index,
5283        },
5284    ))
5285}
5286
5287pub fn pattern<I: Span, O, E: ParseError<I>, V>(
5288    mut value: V,
5289) -> impl FnMut(I) -> IResult<I, Pattern<O>, E>
5290where
5291    V: Parser<I, O, E>,
5292{
5293    move |input: I| {
5294        let x: Res<I, I> = tag("*")(input.clone());
5295        match x {
5296            Ok((next, _)) => Ok((next, Pattern::Any)),
5297            Err(_) => {
5298                let (next, p) = value.parse(input)?;
5299                let pattern = Pattern::Exact(p);
5300                Ok((next, pattern))
5301            }
5302        }
5303    }
5304}
5305
5306/*
5307pub fn context<I: Clone, E: ContextError<I>, F, O>(
5308    context: &'static str,
5309    mut f: F,
5310) -> impl FnMut(I) -> IResult<I, O, E>
5311    where
5312        F: Parser<I, O, E>,
5313{
5314    move |i: I| match f.parse(i.clone()) {
5315        Ok(o) => Ok(o),
5316        Err(Err::Incomplete(i)) => Err(Err::Incomplete(i)),
5317        Err(Err::Error(e)) => Err(Err::Error(E::add_context(i, context, e))),
5318        Err(Err::Failure(e)) => Err(Err::Failure(E::add_context(i, context, e))),
5319    }
5320}
5321
5322 */
5323pub fn value_pattern<I: Span, O, E: ParseError<I>, F>(
5324    mut f: F,
5325) -> impl FnMut(I) -> IResult<I, ValuePattern<O>, E>
5326where
5327    I: InputLength + InputTake + Compare<&'static str>,
5328    F: Parser<I, O, E>,
5329    E: nom::error::ContextError<I>,
5330{
5331    move |input: I| match tag::<&'static str, I, E>("*")(input.clone()) {
5332        Ok((next, _)) => Ok((next, ValuePattern::Any)),
5333        Err(err) => f
5334            .parse(input.clone())
5335            .map(|(next, res)| (next, ValuePattern::Pattern(res))),
5336    }
5337}
5338/*
5339pub fn value_pattern<E,F,O>(
5340    mut f: F
5341) -> impl Fn(&str) -> IResult<&str, ValuePattern<O>, E>
5342where F: Parser<&'static str,O,E>, E: ContextError<&'static str> {
5343    move |input: &str| match tag::<&str,&'static str,ErrorTree<&'static str>>("*")(input) {
5344        Ok((next, _)) => Ok((next, ValuePattern::Any)),
5345        Err(err) => {
5346            match f.parse(input.clone()) {
5347                Ok((input,output)) => {Ok((input,ValuePattern::Pattern(output)))}
5348                Err(Err::Incomplete(i)) => Err(Err::Incomplete(i)),
5349                Err(Err::Error(e)) => Err(Err::Error(E::add_context(input.clone(), "value_pattern", e))),
5350                Err(Err::Failure(e)) => Err(Err::Failure(E::add_context(input.clone(), "value_pattern", e))),
5351            }
5352        }
5353    }
5354}
5355
5356 */
5357
5358/*
5359pub fn value_pattern<P>(
5360    parse: fn<I:Span>(input: Span) -> Res<Span, P>,
5361) -> impl Fn(&str) -> Res<Span, ValuePattern<P>> {
5362    move |input: &str| match tag::<&str, &str, VerboseError<&str>>("*")(input) {
5363        Ok((next, _)) => Ok((next, ValuePattern::Any)),
5364        Err(_) => {
5365            let (next, p) = parse(input)?;
5366            let pattern = ValuePattern::Pattern(p);
5367            Ok((next, pattern))
5368        }
5369    }
5370}
5371 */
5372
5373pub fn version_req<I: Span>(input: I) -> Res<I, VersionReq> {
5374    let (next, version) = version_req_chars(input.clone())?;
5375    let version = version.to_string();
5376    let str_input = version.as_str();
5377    let rtn = semver::VersionReq::parse(str_input);
5378
5379    match rtn {
5380        Ok(version) => Ok((next, VersionReq { version })),
5381        Err(err) => {
5382            let tree = Err::Error(ErrorTree::from_error_kind(input, ErrorKind::Fail));
5383            Err(tree)
5384        }
5385    }
5386}
5387
5388fn rec_domain<I: Span>(input: I) -> Res<I, I> {
5389    recognize(tuple((
5390        many1(terminated(skewer_chars, tag("."))),
5391        skewer_chars,
5392    )))(input)
5393}
5394
5395// can be a hostname or domain name
5396fn space<I: Span>(input: I) -> Res<I, I> {
5397    recognize(alt((skewer_chars, rec_domain)))(input)
5398}
5399
5400pub fn specific_selector<I: Span>(input: I) -> Res<I, SpecificSelector> {
5401    tuple((
5402        pattern(domain),
5403        tag(":"),
5404        pattern(domain),
5405        tag(":"),
5406        pattern(skewer_case),
5407        tag(":"),
5408        pattern(skewer_case),
5409        tag(":"),
5410        delimited(tag("("), version_req, tag(")")),
5411    ))(input)
5412    .map(
5413        |(next, (provider, _, vendor, _, product, _, variant, _, version))| {
5414            let specific = SpecificSelector {
5415                provider,
5416                vendor,
5417                product,
5418                variant,
5419                version,
5420            };
5421            (next, specific)
5422        },
5423    )
5424}
5425
5426pub fn rec_domain_pattern<I: Span>(input: I) -> Res<I, Pattern<I>> {
5427    pattern(rec_domain)(input)
5428}
5429pub fn rec_skewer_pattern<I: Span>(input: I) -> Res<I, Pattern<I>> {
5430    pattern(skewer_chars)(input)
5431}
5432
5433pub fn specific_version_req<I: Span>(input: I) -> Res<I, VersionReq> {
5434    delimited(tag("("), version_req, tag(")"))(input)
5435}
5436
5437#[derive(Clone)]
5438pub struct SkewerPatternParser();
5439impl SubstParser<Pattern<String>> for SkewerPatternParser {
5440    fn parse_span<I: Span>(&self, span: I) -> Res<I, Pattern<String>> {
5441        let (next, pattern) = rec_skewer_pattern(span)?;
5442        let pattern = pattern.to_string_version();
5443        Ok((next, pattern))
5444    }
5445}
5446
5447#[derive(Clone)]
5448pub struct DomainPatternParser();
5449impl SubstParser<Pattern<String>> for DomainPatternParser {
5450    fn parse_span<I: Span>(&self, span: I) -> Res<I, Pattern<String>> {
5451        let (next, pattern) = rec_domain_pattern(span)?;
5452        let pattern = pattern.to_string_version();
5453        Ok((next, pattern))
5454    }
5455}
5456
5457pub fn kind<I: Span>(input: I) -> Res<I, Kind> {
5458    let (next, base) = kind_base(input.clone())?;
5459    unwrap_block(
5460        BlockKind::Nested(NestedBlockKind::Angle),
5461        resolve_kind(base),
5462    )(next)
5463}
5464
5465pub fn rec_kind<I: Span>(input: I) -> Res<I, I> {
5466    recognize(kind_parts)(input)
5467}
5468
5469pub fn kind_lex<I: Span>(input: I) -> Res<I, KindLex> {
5470    tuple((
5471        camel_case,
5472        opt(delimited(
5473            tag("<"),
5474            tuple((camel_case, opt(delimited(tag("<"), specific, tag(">"))))),
5475            tag(">"),
5476        )),
5477    ))(input)
5478    .map(|(next, (kind, rest))| {
5479        let mut rtn = KindLex {
5480            base: kind,
5481            sub: Option::None,
5482            specific: Option::None,
5483        };
5484
5485        match rest {
5486            Some((sub, specific)) => {
5487                rtn.sub = Option::Some(sub);
5488                match specific {
5489                    Some(specific) => {
5490                        rtn.specific = Option::Some(specific);
5491                    }
5492                    None => {}
5493                }
5494            }
5495            None => {}
5496        }
5497
5498        (next, rtn)
5499    })
5500}
5501
5502pub fn kind_parts<I: Span>(input: I) -> Res<I, KindParts> {
5503    tuple((
5504        kind_base,
5505        opt(delimited(
5506            tag("<"),
5507            tuple((camel_case, opt(delimited(tag("<"), specific, tag(">"))))),
5508            tag(">"),
5509        )),
5510    ))(input)
5511    .map(|(next, (base, rest))| {
5512        let mut rtn = KindParts {
5513            base,
5514            sub: Option::None,
5515            specific: Option::None,
5516        };
5517
5518        match rest {
5519            Some((sub, specific)) => {
5520                rtn.sub = Option::Some(sub);
5521                match specific {
5522                    Some(specific) => {
5523                        rtn.specific = Option::Some(specific);
5524                    }
5525                    None => {}
5526                }
5527            }
5528            None => {}
5529        }
5530
5531        (next, rtn)
5532    })
5533}
5534
5535pub fn delim_kind<I: Span>(input: I) -> Res<I, Kind> {
5536    delimited(tag("<"), kind, tag(">"))(input)
5537}
5538
5539pub fn delim_kind_lex<I: Span>(input: I) -> Res<I, KindLex> {
5540    delimited(tag("<"), kind_lex, tag(">"))(input)
5541}
5542
5543pub fn delim_kind_parts<I: Span>(input: I) -> Res<I, KindParts> {
5544    delimited(tag("<"), kind_parts, tag(">"))(input)
5545}
5546
5547pub fn consume_kind<I: Span>(input: I) -> Result<KindParts, SpaceErr> {
5548    let (_, kind_parts) = all_consuming(kind_parts)(input)?;
5549
5550    Ok(kind_parts.try_into()?)
5551}
5552
5553pub fn to_string<I: Span, F>(mut f: F) -> impl FnMut(I) -> Res<I, String>
5554where
5555    F: FnMut(I) -> Res<I, I> + Copy,
5556{
5557    move |input: I| {
5558        f.parse(input)
5559            .map(|(next, output)| (next, output.to_string()))
5560    }
5561}
5562
5563pub fn sub_kind_selector<I: Span>(input: I) -> Res<I, SubKindSelector> {
5564    pattern(camel_case)(input).map(|(next, selector)| match selector {
5565        Pattern::Any => (next, Pattern::Any),
5566        Pattern::Exact(sub) => (next, Pattern::Exact(Some(sub))),
5567    })
5568}
5569
5570pub fn kind_base<I: Span>(input: I) -> Res<I, BaseKind> {
5571    let (next, kind) = context("kind-base", camel_case)(input.clone())?;
5572
5573    match BaseKind::try_from(kind) {
5574        Ok(kind) => Ok((next, kind)),
5575        Err(err) => {
5576            let err = ErrorTree::from_error_kind(input.clone(), ErrorKind::Fail);
5577            Err(nom::Err::Error(ErrorTree::add_context(
5578                input,
5579                "kind-base",
5580                err,
5581            )))
5582        }
5583    }
5584}
5585
5586pub fn resolve_kind<I: Span>(base: BaseKind) -> impl FnMut(I) -> Res<I, Kind> {
5587    move |input: I| {
5588        let (next, sub) = context("kind-sub", camel_case)(input.clone())?;
5589        match base {
5590            BaseKind::Database => match sub.as_str() {
5591                "Relational" => {
5592                    let (next, specific) =
5593                        context("specific", delimited(tag("<"), specific, tag(">")))(next)?;
5594                    Ok((next, Kind::Database(DatabaseSubKind::Relational(specific))))
5595                }
5596                _ => {
5597                    let err = ErrorTree::from_error_kind(input.clone(), ErrorKind::Fail);
5598                    Err(nom::Err::Error(ErrorTree::add_context(
5599                        input,
5600                        "kind-sub:not-found",
5601                        err,
5602                    )))
5603                }
5604            },
5605            BaseKind::UserBase => match sub.as_str() {
5606                "OAuth" => {
5607                    let (next, specific) =
5608                        context("specific", delimited(tag("<"), specific, tag(">")))(next)?;
5609                    Ok((next, Kind::UserBase(UserBaseSubKind::OAuth(specific))))
5610                }
5611                _ => {
5612                    let err = ErrorTree::from_error_kind(input.clone(), ErrorKind::Fail);
5613                    Err(nom::Err::Error(ErrorTree::add_context(
5614                        input,
5615                        "kind-sub:not-found",
5616                        err,
5617                    )))
5618                }
5619            },
5620            BaseKind::Native => match NativeSub::from_str(sub.as_str()) {
5621                Ok(sub) => Ok((next, Kind::Native(sub))),
5622                Err(err) => {
5623                    let err = ErrorTree::from_error_kind(input.clone(), ErrorKind::Fail);
5624                    Err(nom::Err::Error(ErrorTree::add_context(
5625                        input,
5626                        "kind-sub:not-accepted",
5627                        err,
5628                    )))
5629                }
5630            },
5631            BaseKind::Artifact => match ArtifactSubKind::from_str(sub.as_str()) {
5632                Ok(sub) => Ok((next, Kind::Artifact(sub))),
5633                Err(err) => {
5634                    let err = ErrorTree::from_error_kind(input.clone(), ErrorKind::Fail);
5635                    Err(nom::Err::Error(ErrorTree::add_context(
5636                        input,
5637                        "kind-sub:not-accepted",
5638                        err,
5639                    )))
5640                }
5641            },
5642            BaseKind::Star => match StarSub::from_str(sub.as_str()) {
5643                Ok(sub) => Ok((next, Kind::Star(sub))),
5644                Err(err) => {
5645                    let err = ErrorTree::from_error_kind(input.clone(), ErrorKind::Fail);
5646                    Err(nom::Err::Error(ErrorTree::add_context(
5647                        input,
5648                        "kind-sub:not-accepted",
5649                        err,
5650                    )))
5651                }
5652            },
5653            BaseKind::File => match FileSubKind::from_str(sub.as_str()) {
5654                Ok(sub) => Ok((next, Kind::File(sub))),
5655                Err(err) => {
5656                    let err = ErrorTree::from_error_kind(input.clone(), ErrorKind::Fail);
5657                    Err(nom::Err::Error(ErrorTree::add_context(
5658                        input,
5659                        "kind-sub:not-accepted",
5660                        err,
5661                    )))
5662                }
5663            },
5664            BaseKind::Root => Ok((next, Kind::Root)),
5665            BaseKind::Space => Ok((next, Kind::Space)),
5666            BaseKind::Base => Ok((next, Kind::Base)),
5667            BaseKind::User => Ok((next, Kind::User)),
5668            BaseKind::App => Ok((next, Kind::App)),
5669            BaseKind::Mechtron => Ok((next, Kind::Mechtron)),
5670            BaseKind::FileSystem => Ok((next, Kind::FileSystem)),
5671            BaseKind::BundleSeries => Ok((next, Kind::BundleSeries)),
5672            BaseKind::Bundle => Ok((next, Kind::Bundle)),
5673            BaseKind::Control => Ok((next, Kind::Control)),
5674            BaseKind::Portal => Ok((next, Kind::Portal)),
5675            BaseKind::Repo => Ok((next, Kind::Repo)),
5676            BaseKind::Driver => Ok((next, Kind::Driver)),
5677            BaseKind::Global => Ok((next, Kind::Global)),
5678            BaseKind::Host => Ok((next, Kind::Host)),
5679            BaseKind::Guest => Ok((next, Kind::Guest)),
5680        }
5681    }
5682}
5683
5684pub fn kind_base_selector<I: Span>(input: I) -> Res<I, KindBaseSelector> {
5685    pattern(kind_base)(input)
5686}
5687
5688pub fn kind_selector<I: Span>(input: I) -> Res<I, KindSelector> {
5689    delimited(
5690        tag("<"),
5691        tuple((
5692            kind_base_selector,
5693            opt(delimited(
5694                tag("<"),
5695                tuple((
5696                    sub_kind_selector,
5697                    opt(delimited(
5698                        tag("<"),
5699                        value_pattern(specific_selector),
5700                        tag(">"),
5701                    )),
5702                )),
5703                tag(">"),
5704            )),
5705        )),
5706        tag(">"),
5707    )(input)
5708    .map(|(next, (kind, sub_kind_and_specific))| {
5709        let (sub_kind, specific) = match sub_kind_and_specific {
5710            None => (Pattern::Any, ValuePattern::Any),
5711            Some((kind, specific)) => (
5712                kind,
5713                match specific {
5714                    None => ValuePattern::Any,
5715                    Some(specific) => specific,
5716                },
5717            ),
5718        };
5719
5720        let tks = KindSelector {
5721            base: kind,
5722            sub: sub_kind,
5723            specific,
5724        };
5725
5726        (next, tks)
5727    })
5728}
5729
5730fn space_hop<I: Span>(input: I) -> Res<I, Hop> {
5731    tuple((point_segment_selector, opt(kind_selector), opt(tag("+"))))(input).map(
5732        |(next, (segment_selector, kind_selector, inclusive))| {
5733            let kind_selector = match kind_selector {
5734                None => KindSelector::any(),
5735                Some(tks) => tks,
5736            };
5737            let inclusive = inclusive.is_some();
5738            (
5739                next,
5740                Hop {
5741                    inclusive,
5742                    segment_selector,
5743                    kind_selector,
5744                },
5745            )
5746        },
5747    )
5748}
5749
5750fn base_hop<I: Span>(input: I) -> Res<I, Hop> {
5751    tuple((base_segment, opt(kind_selector), opt(tag("+"))))(input).map(
5752        |(next, (segment, tks, inclusive))| {
5753            let tks = match tks {
5754                None => KindSelector::any(),
5755                Some(tks) => tks,
5756            };
5757            let inclusive = inclusive.is_some();
5758            (
5759                next,
5760                Hop {
5761                    inclusive,
5762                    segment_selector: segment,
5763                    kind_selector: tks,
5764                },
5765            )
5766        },
5767    )
5768}
5769
5770fn file_hop<I: Span>(input: I) -> Res<I, Hop> {
5771    tuple((file_segment, opt(tag("+"))))(input).map(|(next, (segment, inclusive))| {
5772        let tks = KindSelector {
5773            base: Pattern::Exact(BaseKind::File),
5774            sub: Pattern::Any,
5775            specific: ValuePattern::Any,
5776        };
5777        let inclusive = inclusive.is_some();
5778        (
5779            next,
5780            Hop {
5781                inclusive,
5782                segment_selector: segment,
5783                kind_selector: tks,
5784            },
5785        )
5786    })
5787}
5788
5789fn dir_hop<I: Span>(input: I) -> Res<I, Hop> {
5790    tuple((dir_segment, opt(tag("+"))))(input).map(|(next, (segment, inclusive))| {
5791        let tks = KindSelector::any();
5792        let inclusive = inclusive.is_some();
5793        (
5794            next,
5795            Hop {
5796                inclusive,
5797                segment_selector: segment,
5798                kind_selector: tks,
5799            },
5800        )
5801    })
5802}
5803
5804fn version_hop<I: Span>(input: I) -> Res<I, Hop> {
5805    tuple((version_segment, opt(kind_selector), opt(tag("+"))))(input).map(
5806        |(next, (segment, tks, inclusive))| {
5807            let tks = match tks {
5808                None => KindSelector::any(),
5809                Some(tks) => tks,
5810            };
5811            let inclusive = inclusive.is_some();
5812            (
5813                next,
5814                Hop {
5815                    inclusive,
5816                    segment_selector: segment,
5817                    kind_selector: tks,
5818                },
5819            )
5820        },
5821    )
5822}
5823
5824pub fn point_selector<I: Span>(input: I) -> Res<I, Selector> {
5825    context(
5826        "point_kind_pattern",
5827        tuple((
5828            space_hop,
5829            many0(preceded(tag(":"), base_hop)),
5830            opt(preceded(tag(":"), version_hop)),
5831            opt(preceded(tag(":/"), tuple((many0(dir_hop), opt(file_hop))))),
5832        )),
5833    )(input)
5834    .map(
5835        |(next, (space_hop, base_hops, version_hop, filesystem_hops))| {
5836            let mut hops = vec![];
5837            hops.push(space_hop);
5838            for base_hop in base_hops {
5839                hops.push(base_hop);
5840            }
5841            if let Option::Some(version_hop) = version_hop {
5842                hops.push(version_hop);
5843            }
5844            if let Some((dir_hops, file_hop)) = filesystem_hops {
5845                // first push the filesystem root
5846                hops.push(Hop {
5847                    inclusive: false,
5848                    segment_selector: PointSegSelector::Exact(ExactPointSeg::PointSeg(
5849                        PointSeg::FilesystemRootDir,
5850                    )),
5851                    kind_selector: KindSelector {
5852                        base: Pattern::Exact(BaseKind::File),
5853                        sub: Pattern::Any,
5854                        specific: ValuePattern::Any,
5855                    },
5856                });
5857                for dir_hop in dir_hops {
5858                    hops.push(dir_hop);
5859                }
5860                if let Some(file_hop) = file_hop {
5861                    hops.push(file_hop);
5862                }
5863            }
5864
5865            let rtn = Selector { hops };
5866
5867            (next, rtn)
5868        },
5869    )
5870}
5871
5872pub fn point_and_kind<I: Span>(input: I) -> Res<I, PointKindVar> {
5873    tuple((point_var, kind))(input)
5874        .map(|(next, (point, kind))| (next, PointKindVar { point, kind }))
5875}
5876
5877/*
5878fn version_req<I:Span>(input: Span) -> Res<Span, VersionReq> {
5879    let str_input = *input.fragment();
5880    let rtn:IResult<&str,VersionReq,ErrorTree<&str>> = parse_from_str(version_req_chars).parse(str_input);
5881
5882    match rtn {
5883        Ok((next,version_req)) => {
5884            Ok((span(next), version_req))
5885        }
5886        Err(err) => {
5887            let tree = Err::Error(ErrorTree::from_error_kind(input, ErrorKind::Fail));
5888            Err(tree)
5889        }
5890    }
5891}
5892
5893 */
5894
5895pub fn version<I: Span>(input: I) -> Res<I, Version> {
5896    let (next, version) = rec_version(input.clone())?;
5897    let version = version.to_string();
5898    let str_input = version.as_str();
5899    let rtn = semver::Version::parse(str_input);
5900
5901    match rtn {
5902        Ok(version) => Ok((next, Version { version })),
5903        Err(err) => {
5904            let tree = Err::Error(ErrorTree::from_error_kind(input, ErrorKind::Fail));
5905            Err(tree)
5906        }
5907    }
5908}
5909
5910pub fn specific<I: Span>(input: I) -> Res<I, Specific> {
5911    tuple((
5912        domain,
5913        tag(":"),
5914        domain,
5915        tag(":"),
5916        skewer_case,
5917        tag(":"),
5918        skewer_case,
5919        tag(":"),
5920        version,
5921    ))(input)
5922    .map(
5923        |(next, (provider, _, vendor, _, product, _, variant, _, version))| {
5924            let specific = Specific {
5925                provider,
5926                vendor,
5927                product,
5928                variant,
5929                version,
5930            };
5931            (next, specific)
5932        },
5933    )
5934}
5935//}
5936
5937pub fn args<T>(i: T) -> Res<T, T>
5938where
5939    T: InputTakeAtPosition + nom::InputLength,
5940    <T as InputTakeAtPosition>::Item: AsChar,
5941{
5942    i.split_at_position1_complete(
5943        |item| {
5944            let char_item = item.as_char();
5945            !(char_item == '-')
5946                && !(char_item == '"')
5947                && !(char_item == '_')
5948                && !(char_item == '{')
5949                && !(char_item == '}')
5950                && !(char_item == '(')
5951                && !(char_item == ')')
5952                && !(char_item == '[')
5953                && !(char_item == ']')
5954                && !(char_item == ' ')
5955                && !(char_item == '\n')
5956                && !(char_item == '\t')
5957                && !(char_item == '\r')
5958                && !(char_item == '\'')
5959                && !((char_item.is_alphanumeric()) || char_item.is_dec_digit())
5960        },
5961        ErrorKind::AlphaNumeric,
5962    )
5963}
5964
5965pub fn skewer<T>(i: T) -> Res<T, T>
5966where
5967    T: InputTakeAtPosition + nom::InputLength,
5968    <T as InputTakeAtPosition>::Item: AsChar,
5969{
5970    i.split_at_position1_complete(
5971        |item| {
5972            let char_item = item.as_char();
5973            !(char_item == '-')
5974                && !((char_item.is_alpha() && char_item.is_lowercase()) || char_item.is_dec_digit())
5975        },
5976        ErrorKind::AlphaNumeric,
5977    )
5978}
5979
5980pub fn skewer_or_snake<T>(i: T) -> Res<T, T>
5981where
5982    T: InputTakeAtPosition + nom::InputLength,
5983    <T as InputTakeAtPosition>::Item: AsChar,
5984{
5985    i.split_at_position1_complete(
5986        |item| {
5987            let char_item = item.as_char();
5988            !(char_item == '-')
5989                && !(char_item == '_')
5990                && !((char_item.is_alpha() && char_item.is_lowercase()) || char_item.is_dec_digit())
5991        },
5992        ErrorKind::AlphaNumeric,
5993    )
5994}
5995
5996pub fn not_quote<T>(i: T) -> Res<T, T>
5997where
5998    T: InputTakeAtPosition + nom::InputLength,
5999    <T as InputTakeAtPosition>::Item: AsChar,
6000{
6001    i.split_at_position1_complete(
6002        |item| {
6003            let char_item = item.as_char();
6004            (char_item == '"')
6005        },
6006        ErrorKind::AlphaNumeric,
6007    )
6008}
6009
6010pub fn filename<T>(i: T) -> Res<T, T>
6011where
6012    T: InputTakeAtPosition + nom::InputLength,
6013    <T as InputTakeAtPosition>::Item: AsChar,
6014{
6015    i.split_at_position1_complete(
6016        |item| {
6017            let char_item = item.as_char();
6018            !(char_item == '-') && !(char_item.is_alpha() || char_item.is_dec_digit())
6019        },
6020        ErrorKind::AlphaNumeric,
6021    )
6022}
6023
6024pub fn primitive_def<I: Span>(input: I) -> Res<I, PayloadType2Def<PointVar>> {
6025    tuple((
6026        payload,
6027        opt(preceded(tag("~"), opt(format))),
6028        opt(preceded(tag("~"), call_with_config)),
6029    ))(input)
6030    .map(|(next, (primitive, format, verifier))| {
6031        (
6032            next,
6033            PayloadType2Def {
6034                primitive,
6035                format: match format {
6036                    Some(Some(format)) => Some(format),
6037                    _ => Option::None,
6038                },
6039                verifier,
6040            },
6041        )
6042    })
6043}
6044
6045pub fn payload<I: Span>(input: I) -> Res<I, SubstanceKind> {
6046    parse_camel_case_str(input)
6047}
6048
6049pub fn consume_primitive_def<I: Span>(input: I) -> Res<I, PayloadType2Def<PointVar>> {
6050    all_consuming(primitive_def)(input)
6051}
6052
6053pub fn call_with_config<I: Span>(input: I) -> Res<I, CallWithConfigVar> {
6054    tuple((call, opt(preceded(tag("+"), point_var))))(input)
6055        .map(|(next, (call, config))| (next, CallWithConfigVar { call, config }))
6056}
6057
6058pub fn parse_alpha1_str<I: Span, O: FromStr>(input: I) -> Res<I, O> {
6059    let (next, rtn) = recognize(alpha1)(input)?;
6060    match O::from_str(rtn.to_string().as_str()) {
6061        Ok(rtn) => Ok((next, rtn)),
6062        Err(err) => Err(nom::Err::Error(ErrorTree::from_error_kind(
6063            next,
6064            ErrorKind::Fail,
6065        ))),
6066    }
6067}
6068
6069pub fn rc_command<I: Span>(input: I) -> Res<I, CmdKind> {
6070    parse_alpha1_str(input)
6071}
6072
6073pub fn ext_call<I: Span>(input: I) -> Res<I, CallKind> {
6074    tuple((
6075        delimited(tag("Ext<"), ext_method, tag(">")),
6076        opt(subst_path),
6077    ))(input)
6078    .map(|(next, (method, path))| {
6079        let path = match path {
6080            None => subst(filepath_chars)(new_span("/")).unwrap().1.stringify(),
6081            Some(path) => path.stringify(),
6082        };
6083        (next, CallKind::Ext(ExtCall::new(method, path)))
6084    })
6085}
6086
6087pub fn http_call<I: Span>(input: I) -> Res<I, CallKind> {
6088    tuple((
6089        delimited(tag("Http<"), http_method, tag(">")),
6090        opt(subst_path),
6091    ))(input)
6092    .map(|(next, (method, path))| {
6093        let path = match path {
6094            None => subst(filepath_chars)(new_span("/")).unwrap().1.stringify(),
6095            Some(path) => path.stringify(),
6096        };
6097        (next, CallKind::Http(HttpCall::new(method, path)))
6098    })
6099}
6100
6101pub fn call_kind<I: Span>(input: I) -> Res<I, CallKind> {
6102    alt((ext_call, http_call))(input)
6103}
6104
6105pub fn call<I: Span>(input: I) -> Res<I, CallVar> {
6106    tuple((point_var, preceded(tag("^"), call_kind)))(input)
6107        .map(|(next, (point, kind))| (next, CallVar { point, kind }))
6108}
6109
6110pub fn consume_call<I: Span>(input: I) -> Res<I, CallVar> {
6111    all_consuming(call)(input)
6112}
6113
6114pub fn labeled_primitive_def<I: Span>(input: I) -> Res<I, LabeledPrimitiveTypeDef<PointVar>> {
6115    tuple((skewer, delimited(tag("<"), primitive_def, tag(">"))))(input).map(
6116        |(next, (label, primitive_def))| {
6117            let labeled_def = LabeledPrimitiveTypeDef {
6118                label: label.to_string(),
6119                def: primitive_def,
6120            };
6121            (next, labeled_def)
6122        },
6123    )
6124}
6125
6126pub fn digit_range<I: Span>(input: I) -> Res<I, NumRange> {
6127    tuple((digit1, tag("-"), digit1))(input).map(|(next, (min, _, max))| {
6128        let min: usize = usize::from_str(min.to_string().as_str()).expect("usize");
6129        let max: usize = usize::from_str(max.to_string().as_str()).expect("usize");
6130        let range = NumRange::MinMax { min, max };
6131
6132        (next, range)
6133    })
6134}
6135
6136pub fn exact_range<I: Span>(input: I) -> Res<I, NumRange> {
6137    digit1(input).map(|(next, exact)| {
6138        (
6139            next,
6140            NumRange::Exact(
6141                usize::from_str(exact.to_string().as_str())
6142                    .expect("expect to be able to change digit string into usize"),
6143            ),
6144        )
6145    })
6146}
6147
6148pub fn range<I: Span>(input: I) -> Res<I, NumRange> {
6149    delimited(
6150        multispace0,
6151        opt(alt((digit_range, exact_range))),
6152        multispace0,
6153    )(input)
6154    .map(|(next, range)| {
6155        let range = match range {
6156            Some(range) => range,
6157            None => NumRange::Any,
6158        };
6159        (next, range)
6160    })
6161}
6162
6163pub fn primitive_data_struct<I: Span>(input: I) -> Res<I, SubstanceTypePatternDef<PointVar>> {
6164    context("selector", payload)(input)
6165        .map(|(next, primitive)| (next, SubstanceTypePatternDef::Primitive(primitive)))
6166}
6167
6168pub fn array_data_struct<I: Span>(input: I) -> Res<I, SubstanceTypePatternDef<PointVar>> {
6169    context(
6170        "selector",
6171        tuple((
6172            payload,
6173            context("array", delimited(tag("["), range, tag("]"))),
6174        )),
6175    )(input)
6176    .map(|(next, (primitive, range))| {
6177        (
6178            next,
6179            SubstanceTypePatternDef::List(ListPattern { primitive, range }),
6180        )
6181    })
6182}
6183
6184pub fn map_entry_pattern_any<I: Span>(input: I) -> Res<I, ValuePattern<MapEntryPatternVar>> {
6185    delimited(multispace0, tag("*"), multispace0)(input).map(|(next, _)| (next, ValuePattern::Any))
6186}
6187
6188pub fn map_entry_pattern<I: Span>(input: I) -> Res<I, MapEntryPatternVar> {
6189    tuple((skewer, opt(delimited(tag("<"), payload_pattern, tag(">")))))(input).map(
6190        |(next, (key_con, payload_con))| {
6191            let payload_con = match payload_con {
6192                None => ValuePattern::Any,
6193                Some(payload_con) => payload_con,
6194            };
6195
6196            let map_entry_con = MapEntryPatternVar {
6197                key: key_con.to_string(),
6198                payload: payload_con,
6199            };
6200            (next, map_entry_con)
6201        },
6202    )
6203}
6204
6205pub fn map_entry_patterns<I: Span>(input: I) -> Res<I, Vec<MapEntryPatternVar>> {
6206    separated_list0(
6207        delimited(multispace0, tag(","), multispace0),
6208        map_entry_pattern,
6209    )(input)
6210}
6211
6212pub fn consume_map_entry_pattern<I: Span>(input: I) -> Res<I, MapEntryPatternVar> {
6213    all_consuming(map_entry_pattern)(input)
6214}
6215
6216pub fn required_map_entry_pattern<I: Span>(input: I) -> Res<I, Vec<MapEntryPatternVar>> {
6217    delimited(tag("["), map_entry_patterns, tag("]"))(input).map(|(next, params)| (next, params))
6218}
6219
6220pub fn allowed_map_entry_pattern<I: Span>(input: I) -> Res<I, ValuePattern<SubstancePatternVar>> {
6221    payload_pattern(input).map(|(next, con)| (next, con))
6222}
6223
6224//  [ required1<Bin>, required2<Text> ] *<Bin>
6225pub fn map_pattern_params<I: Span>(input: I) -> Res<I, MapPatternVar> {
6226    tuple((
6227        opt(map_entry_patterns),
6228        multispace0,
6229        opt(allowed_map_entry_pattern),
6230    ))(input)
6231    .map(|(next, (required, _, allowed))| {
6232        let mut required_map = HashMap::new();
6233        match required {
6234            Option::Some(required) => {
6235                for require in required {
6236                    required_map.insert(require.key, require.payload);
6237                }
6238            }
6239            Option::None => {}
6240        }
6241
6242        let allowed = match allowed {
6243            Some(allowed) => allowed,
6244            None => ValuePattern::None,
6245        };
6246
6247        let con = MapPatternVar::new(required_map, allowed);
6248
6249        (next, con)
6250    })
6251}
6252
6253pub fn format<I: Span>(input: I) -> Res<I, SubstanceFormat> {
6254    let (next, format) = recognize(alpha1)(input)?;
6255    match SubstanceFormat::from_str(format.to_string().as_str()) {
6256        Ok(format) => Ok((next, format)),
6257        Err(err) => Err(nom::Err::Error(ErrorTree::from_error_kind(
6258            next,
6259            ErrorKind::Fail,
6260        ))),
6261    }
6262}
6263
6264enum MapConParam {
6265    Required(Vec<ValuePattern<MapEntryPattern>>),
6266    Allowed(ValuePattern<SubstancePattern>),
6267}
6268
6269// EXAMPLE:
6270//  Map { [ required1<Bin>, required2<Text> ] *<Bin> }
6271pub fn map_pattern<I: Span>(input: I) -> Res<I, MapPatternVar> {
6272    tuple((
6273        delimited(multispace0, tag("Map"), multispace0),
6274        opt(delimited(
6275            tag("{"),
6276            delimited(multispace0, map_pattern_params, multispace0),
6277            tag("}"),
6278        )),
6279    ))(input)
6280    .map(|(next, (_, entries))| {
6281        let mut entries = entries;
6282        let con = match entries {
6283            None => MapPatternVar::any(),
6284            Some(con) => con,
6285        };
6286
6287        (next, con)
6288    })
6289}
6290
6291pub fn value_constrained_map_pattern<I: Span>(input: I) -> Res<I, ValuePattern<MapPatternVar>> {
6292    value_pattern(map_pattern)(input)
6293}
6294
6295pub fn ext_action<I: Span>(input: I) -> Res<I, ValuePattern<StringMatcher>> {
6296    value_pattern(camel_case_to_string_matcher)(input)
6297}
6298
6299pub fn parse_camel_case_str<I: Span, O: FromStr>(input: I) -> Res<I, O> {
6300    let (next, rtn) = recognize(camel_case_chars)(input)?;
6301    match O::from_str(rtn.to_string().as_str()) {
6302        Ok(rtn) => Ok((next, rtn)),
6303        Err(err) => Err(nom::Err::Error(ErrorTree::from_error_kind(
6304            next,
6305            ErrorKind::Fail,
6306        ))),
6307    }
6308}
6309
6310pub fn http_method<I: Span>(input: I) -> Res<I, HttpMethod> {
6311    context("http_method", parse_camel_case_str).parse(input)
6312}
6313
6314pub fn http_method_pattern<I: Span>(input: I) -> Res<I, HttpMethodPattern> {
6315    context("@http_method_pattern", method_pattern(http_method))(input)
6316}
6317
6318pub fn method_pattern<I: Clone, E: ParseError<I>, F>(
6319    mut f: F,
6320) -> impl FnMut(I) -> IResult<I, HttpMethodPattern, E>
6321where
6322    I: InputLength + InputTake + Compare<&'static str>,
6323    F: Parser<I, HttpMethod, E>,
6324    E: nom::error::ContextError<I>,
6325{
6326    move |input: I| match tag::<&'static str, I, E>("*")(input.clone()) {
6327        Ok((next, _)) => Ok((next, HttpMethodPattern::Any)),
6328        Err(err) => f
6329            .parse(input.clone())
6330            .map(|(next, res)| (next, HttpMethodPattern::Pattern(res))),
6331    }
6332}
6333
6334pub fn ext_method<I: Span>(input: I) -> Res<I, ExtMethod> {
6335    let (next, ext_method) = camel_case_chars(input.clone())?;
6336
6337    match ExtMethod::new(ext_method.to_string()) {
6338        Ok(method) => Ok((next, method)),
6339        Err(err) => Err(nom::Err::Error(ErrorTree::from_error_kind(
6340            input,
6341            ErrorKind::Fail,
6342        ))),
6343    }
6344}
6345
6346pub fn sys_method<I: Span>(input: I) -> Res<I, HypMethod> {
6347    let (next, sys_method) = camel_case_chars(input.clone())?;
6348
6349    match HypMethod::from_str(sys_method.to_string().as_str()) {
6350        Ok(method) => Ok((next, method)),
6351        Err(err) => Err(nom::Err::Error(ErrorTree::from_error_kind(
6352            input,
6353            ErrorKind::Fail,
6354        ))),
6355    }
6356}
6357
6358pub fn cmd_method<I: Span>(input: I) -> Res<I, CmdMethod> {
6359    let (next, method) = camel_case_chars(input.clone())?;
6360
6361    match CmdMethod::from_str(method.to_string().as_str()) {
6362        Ok(method) => Ok((next, method)),
6363        Err(err) => Err(nom::Err::Error(ErrorTree::from_error_kind(
6364            input,
6365            ErrorKind::Fail,
6366        ))),
6367    }
6368}
6369
6370pub fn wrapped_ext_method<I: Span>(input: I) -> Res<I, Method> {
6371    let (next, ext_method) = ext_method(input.clone())?;
6372
6373    match ExtMethod::new(ext_method.to_string()) {
6374        Ok(method) => Ok((next, Method::Ext(method))),
6375        Err(err) => Err(nom::Err::Error(ErrorTree::from_error_kind(
6376            input,
6377            ErrorKind::Fail,
6378        ))),
6379    }
6380}
6381
6382pub fn wrapped_http_method<I: Span>(input: I) -> Res<I, Method> {
6383    http_method(input).map(|(next, method)| (next, Method::Http(method)))
6384}
6385
6386pub fn wrapped_sys_method<I: Span>(input: I) -> Res<I, Method> {
6387    sys_method(input).map(|(next, method)| (next, Method::Hyp(method)))
6388}
6389
6390pub fn wrapped_cmd_method<I: Span>(input: I) -> Res<I, Method> {
6391    cmd_method(input).map(|(next, method)| (next, Method::Cmd(method)))
6392}
6393
6394pub fn rc_command_type<I: Span>(input: I) -> Res<I, CmdKind> {
6395    parse_alpha1_str(input)
6396}
6397
6398pub fn map_pattern_payload_structure<I: Span>(
6399    input: I,
6400) -> Res<I, SubstanceTypePatternDef<PointVar>> {
6401    map_pattern(input).map(|(next, con)| (next, SubstanceTypePatternDef::Map(Box::new(con))))
6402}
6403
6404pub fn payload_structure<I: Span>(input: I) -> Res<I, SubstanceTypePatternDef<PointVar>> {
6405    alt((
6406        array_data_struct,
6407        primitive_data_struct,
6408        map_pattern_payload_structure,
6409    ))(input)
6410}
6411
6412pub fn payload_structure_with_validation<I: Span>(input: I) -> Res<I, SubstancePatternVar> {
6413    tuple((
6414        context("selector", payload_structure),
6415        opt(preceded(tag("~"), opt(format))),
6416        opt(preceded(tag("~"), call_with_config)),
6417    ))(input)
6418    .map(|(next, (data, format, verifier))| {
6419        (
6420            next,
6421            SubstancePatternVar {
6422                structure: data,
6423                format: match format {
6424                    Some(Some(format)) => Some(format),
6425                    _ => Option::None,
6426                },
6427                validator: verifier,
6428            },
6429        )
6430    })
6431}
6432
6433pub fn consume_payload_structure<I: Span>(input: I) -> Res<I, SubstanceTypePatternVar> {
6434    all_consuming(payload_structure)(input)
6435}
6436
6437pub fn consume_data_struct_def<I: Span>(input: I) -> Res<I, SubstancePatternVar> {
6438    all_consuming(payload_structure_with_validation)(input)
6439}
6440
6441pub fn payload_pattern_any<I: Span>(input: I) -> Res<I, ValuePattern<SubstancePatternVar>> {
6442    tag("*")(input).map(|(next, _)| (next, ValuePattern::Any))
6443}
6444
6445pub fn payload_pattern<I: Span>(input: I) -> Res<I, ValuePattern<SubstancePatternVar>> {
6446    context(
6447        "@payload-pattern",
6448        value_pattern(payload_structure_with_validation),
6449    )(input)
6450    .map(|(next, payload_pattern)| (next, payload_pattern))
6451}
6452
6453pub fn payload_filter_block_empty<I: Span>(input: I) -> Res<I, PatternBlockVar> {
6454    multispace0(input.clone()).map(|(next, _)| (input, PatternBlockVar::None))
6455}
6456
6457pub fn payload_filter_block_any<I: Span>(input: I) -> Res<I, PatternBlockVar> {
6458    let (next, _) = delimited(multispace0, context("selector", tag("*")), multispace0)(input)?;
6459
6460    Ok((next, PatternBlockVar::Any))
6461}
6462
6463pub fn payload_filter_block_def<I: Span>(input: I) -> Res<I, PatternBlockVar> {
6464    payload_structure_with_validation(input)
6465        .map(|(next, pattern)| (next, PatternBlockVar::Pattern(pattern)))
6466}
6467
6468fn insert_block_pattern<I: Span>(input: I) -> Res<I, UploadBlock> {
6469    delimited(multispace0, filename, multispace0)(input).map(|(next, filename)| {
6470        (
6471            next,
6472            UploadBlock {
6473                name: filename.to_string(),
6474            },
6475        )
6476    })
6477}
6478
6479/*
6480pub fn text_payload_block<I:Span>(input: Span) -> Res<Span, PayloadBlock> {
6481    delimited(
6482        tag("+["),
6483        tuple((
6484            multispace0,
6485            delimited(tag("\""), not_quote, tag("\"")),
6486            multispace0,
6487        )),
6488        tag("]"),
6489    )(input)
6490    .map(|(next, (_, text, _))| {
6491        (
6492            next,
6493            PayloadBlock::CreatePayload(Payload::Text(text.to_string())),
6494        )
6495    })
6496}*/
6497
6498pub fn upload_payload_block<I: Span>(input: I) -> Res<I, UploadBlock> {
6499    delimited(multispace0, file_chars, multispace0)(input).map(|(next, filename)| {
6500        (
6501            next,
6502            UploadBlock {
6503                name: filename.to_string(),
6504            },
6505        )
6506    })
6507}
6508
6509pub fn upload_block<I: Span>(input: I) -> Res<I, UploadBlock> {
6510    delimited(tag("^["), upload_payload_block, tag("]->"))(input)
6511}
6512
6513pub fn upload_blocks<I: Span>(input: I) -> Res<I, Vec<UploadBlock>> {
6514    many0(pair(take_until("^["), upload_block))(input).map(|(next, blocks)| {
6515        let mut rtn = vec![];
6516        for (_, block) in blocks {
6517            rtn.push(block);
6518        }
6519        (next, rtn)
6520    })
6521}
6522
6523pub fn request_payload_filter_block<I: Span>(input: I) -> Res<I, PayloadBlockVar> {
6524    tuple((
6525        multispace0,
6526        alt((
6527            payload_filter_block_any,
6528            payload_filter_block_def,
6529            payload_filter_block_empty,
6530        )),
6531        multispace0,
6532    ))(input)
6533    .map(|(next, (_, block, _))| (next, PayloadBlockVar::DirectPattern(block)))
6534}
6535
6536pub fn response_payload_filter_block<I: Span>(input: I) -> Res<I, PayloadBlockVar> {
6537    context(
6538        "response-payload-filter-block",
6539        terminated(
6540            tuple((
6541                multispace0,
6542                alt((
6543                    payload_filter_block_any,
6544                    payload_filter_block_def,
6545                    payload_filter_block_empty,
6546                    fail,
6547                )),
6548                multispace0,
6549            )),
6550            tag("]"),
6551        ),
6552    )(input)
6553    .map(|(next, (_, block, _))| (next, PayloadBlockVar::ReflectPattern(block)))
6554}
6555
6556pub fn rough_pipeline_step<I: Span>(input: I) -> Res<I, I> {
6557    recognize(tuple((
6558        many0(preceded(
6559            alt((tag("-"), tag("="), tag("+"))),
6560            any_soround_lex_block,
6561        )),
6562        alt((tag("->"), tag("=>"))),
6563    )))(input)
6564}
6565
6566pub fn consume_pipeline_block<I: Span>(input: I) -> Res<I, PayloadBlockVar> {
6567    all_consuming(request_payload_filter_block)(input)
6568}
6569
6570/*
6571pub fn remove_comments_from_span( span: Span )-> Res<Span,Span> {
6572    let (next,no_comments) = remove_comments(span.clone())?;
6573    let new = LocatedSpan::new_extra(no_comments.as_str(), span.extra.clone() );
6574    Ok((next,new))
6575}
6576 */
6577
6578pub fn strip_comments<I: Span>(input: I) -> Res<I, String>
6579where
6580    I: InputTakeAtPosition + nom::InputLength + Clone + ToString,
6581    <I as InputTakeAtPosition>::Item: AsChar,
6582{
6583    many0(alt((no_comment, comment)))(input).map(|(next, texts)| {
6584        let mut rtn = String::new();
6585        for t in texts {
6586            match t {
6587                TextType::NoComment(span) => {
6588                    rtn.push_str(span.to_string().as_str());
6589                }
6590                TextType::Comment(span) => {
6591                    for i in 0..span.input_len() {
6592                        // replace with whitespace
6593                        rtn.push_str(" ");
6594                    }
6595                }
6596            }
6597        }
6598
6599        // create with the new string, but use old string as reference
6600        //let span = LocatedSpan::new_extra(rtn.as_str(), input.extra.clone() );
6601        (next, rtn)
6602    })
6603}
6604
6605/*
6606pub fn strip<I:Span>(input: Span) -> Result<Span, ExtErr>
6607{
6608    let (_, stripped) = strip_comments(input.clone())?;
6609    let span = LocatedSpan::new_extra(stripped.as_str().clone(), Arc::new(input.to_string()));
6610    Ok(span)
6611}
6612
6613 */
6614
6615pub fn no_comment<T: Span>(i: T) -> Res<T, TextType<T>>
6616where
6617    T: InputTakeAtPosition + nom::InputLength,
6618    <T as InputTakeAtPosition>::Item: AsChar,
6619{
6620    i.split_at_position1_complete(
6621        |item| {
6622            let char_item = item.as_char();
6623            char_item == '#'
6624        },
6625        ErrorKind::AlphaNumeric,
6626    )
6627    .map(|(next, comment)| (next, TextType::NoComment(comment)))
6628}
6629
6630pub fn comment<T: Span>(i: T) -> Res<T, TextType<T>>
6631where
6632    T: InputTakeAtPosition + nom::InputLength,
6633    <T as InputTakeAtPosition>::Item: AsChar,
6634{
6635    i.split_at_position1_complete(
6636        |item| {
6637            let char_item = item.as_char();
6638            char_item == '\n'
6639        },
6640        ErrorKind::AlphaNumeric,
6641    )
6642    .map(|(next, comment)| (next, TextType::Comment(comment)))
6643}
6644
6645pub fn bind_config(src: &str) -> Result<BindConfig, SpaceErr> {
6646    let document = doc(src)?;
6647    match document {
6648        Document::BindConfig(bind_config) => Ok(bind_config),
6649        _ => Err("not a bind config".into()),
6650    }
6651}
6652
6653pub fn mechtron_config(src: &str) -> Result<MechtronConfig, SpaceErr> {
6654    let document = doc(src)?;
6655    match document {
6656        Document::MechtronConfig(mechtron_config) => Ok(mechtron_config),
6657        _ => Err("not a Mechtron config".into()),
6658    }
6659}
6660
6661pub fn doc(src: &str) -> Result<Document, SpaceErr> {
6662    let src = src.to_string();
6663    let (next, stripped) = strip_comments(new_span(src.as_str()))?;
6664    let span = span_with_extra(stripped.as_str(), Arc::new(src.to_string()));
6665    let lex_root_scope = lex_root_scope(span.clone())?;
6666    let root_scope_selector = lex_root_scope.selector.clone().to_concrete()?;
6667    if root_scope_selector.name.as_str() == "Mechtron" {
6668        if root_scope_selector.version == Version::from_str("1.0.0")? {
6669            let mechtron = result(parse_mechtron_config(lex_root_scope.block.content.clone()))?;
6670
6671            let mechtron = MechtronConfig::new(mechtron)?;
6672            return Ok(Document::MechtronConfig(mechtron));
6673        } else {
6674            let message = format!(
6675                "ConfigParser does not know how to process a Bind at version '{}'",
6676                root_scope_selector.version.to_string()
6677            );
6678            let mut builder = Report::build(ReportKind::Error, (), 0);
6679            let report = builder
6680                .with_message(message)
6681                .with_label(
6682                    Label::new(
6683                        lex_root_scope.selector.version.span.location_offset()
6684                            ..lex_root_scope.selector.version.span.location_offset()
6685                                + lex_root_scope.selector.version.span.len(),
6686                    )
6687                    .with_message("Unsupported Bind Config Version"),
6688                )
6689                .finish();
6690            Err(ParseErrs::from_report(report, lex_root_scope.block.content.extra.clone()).into())
6691        }
6692    } else if root_scope_selector.name.as_str() == "Bind" {
6693        if root_scope_selector.version == Version::from_str("1.0.0")? {
6694            let bind = parse_bind_config(lex_root_scope.block.content.clone())?;
6695
6696            return Ok(Document::BindConfig(bind));
6697        } else {
6698            let message = format!(
6699                "ConfigParser does not know how to process a Bind at version '{}'",
6700                root_scope_selector.version.to_string()
6701            );
6702            let mut builder = Report::build(ReportKind::Error, (), 0);
6703            let report = builder
6704                .with_message(message)
6705                .with_label(
6706                    Label::new(
6707                        lex_root_scope.selector.version.span.location_offset()
6708                            ..lex_root_scope.selector.version.span.location_offset()
6709                                + lex_root_scope.selector.version.span.len(),
6710                    )
6711                    .with_message("Unsupported Bind Config Version"),
6712                )
6713                .finish();
6714            Err(ParseErrs::from_report(report, lex_root_scope.block.content.extra.clone()).into())
6715        }
6716    } else {
6717        let message = format!(
6718            "ConfigParser does not know how to process a '{}'",
6719            lex_root_scope.selector.name.to_string(),
6720        );
6721        let mut builder = Report::build(ReportKind::Error, (), 0);
6722        let report = builder
6723            .with_message(message)
6724            .with_label(
6725                Label::new(
6726                    lex_root_scope.selector.name.location_offset()
6727                        ..lex_root_scope.selector.name.location_offset()
6728                            + lex_root_scope.selector.name.len(),
6729                )
6730                .with_message("Unrecognized Config Kind"),
6731            )
6732            .finish();
6733        Err(ParseErrs::from_report(report, lex_root_scope.block.content.extra.clone()).into())
6734    }
6735}
6736
6737fn parse_mechtron_config<I: Span>(input: I) -> Res<I,Vec<MechtronScope>> {
6738    let (next, (_,( _, (_,assignments)))) = pair( multispace0, context("wasm",tuple((
6739        tag("Wasm"),
6740        alt((tuple((
6741        multispace0,
6742            unwrap_block(BlockKind::Nested(NestedBlockKind::Curly),many0(assignment)))
6743        ),fail))),
6744    )))(input)?;
6745    Ok((next,vec![MechtronScope::WasmScope(assignments)]))
6746}
6747
6748fn assignment<I>(input: I) -> Res<I, Assignment>
6749where
6750    I: Span,
6751{
6752    tuple((
6753        multispace0,
6754        context("assignment:plus", alt( (tag("+"),fail))),
6755        context("assignment:key", alt( (skewer,fail))),
6756        multispace0,
6757        context( "assignment:equals", alt((tag("="),fail))),
6758        multispace0,
6759        context( "assignment:value", alt((nospace1_nosemi,fail))),
6760        multispace0,
6761        opt(tag(";")),
6762        multispace0
6763    ))(input)
6764    .map(|(next, (_, _, k, _, _, _, v, _, _, _))| {
6765        (
6766            next,
6767            Assignment {
6768                key: k.to_string(),
6769                value: v.to_string(),
6770            },
6771        )
6772    })
6773}
6774
6775#[derive(Clone)]
6776pub struct Assignment {
6777    pub key: String,
6778    pub value: String,
6779}
6780
6781fn semantic_mechtron_scope<I: Span>(scope: LexScope<I>) -> Result<MechtronScope, SpaceErr> {
6782    let selector_name = scope.selector.name.to_string();
6783    match selector_name.as_str() {
6784        "Wasm" => {
6785            let assignments = result(many0(assignment)(scope.block.content))?;
6786            Ok(MechtronScope::WasmScope(assignments))
6787        }
6788        what => {
6789            let mut builder = Report::build(ReportKind::Error, (), 0);
6790            let report = builder
6791                .with_message(format!(
6792                    "Unrecognized MechtronConfig selector: '{}'",
6793                    scope.selector.name.to_string()
6794                ))
6795                .with_label(
6796                    Label::new(
6797                        scope.selector.name.location_offset()
6798                            ..scope.selector.name.location_offset() + scope.selector.name.len(),
6799                    )
6800                    .with_message("Unrecognized Selector"),
6801                )
6802                .finish();
6803            Err(ParseErrs::from_report(report, scope.block.content.extra().clone()).into())
6804        }
6805    }
6806}
6807
6808fn parse_bind_config<I: Span>(input: I) -> Result<BindConfig, SpaceErr> {
6809    let lex_scopes = lex_scopes(input)?;
6810    let mut scopes = vec![];
6811    let mut errors = vec![];
6812
6813    for lex_scope in lex_scopes {
6814        match semantic_bind_scope(lex_scope) {
6815            Ok(scope) => {
6816                scopes.push(scope);
6817            }
6818            Err(err) => errors.push(err),
6819        }
6820    }
6821
6822    if !errors.is_empty() {
6823        let errors = ParseErrs::fold(errors);
6824        return Err(errors.into());
6825    }
6826
6827    let mut config = BindConfig::new(scopes);
6828    Ok(config)
6829}
6830
6831fn semantic_bind_scope<I: Span>(scope: LexScope<I>) -> Result<BindScope, SpaceErr> {
6832    let selector_name = scope.selector.name.to_string();
6833    match selector_name.as_str() {
6834        "Route" => {
6835            let scope = lex_child_scopes(scope)?;
6836            let scope = RouteScope::try_from(scope)?;
6837            Ok(BindScope::RequestScope(scope))
6838        }
6839        what => {
6840            let mut builder = Report::build(ReportKind::Error, (), 0);
6841            let report = builder
6842                .with_message(format!(
6843                    "Unrecognized BindConfig selector: '{}'",
6844                    scope.selector.name.to_string()
6845                ))
6846                .with_label(
6847                    Label::new(
6848                        scope.selector.name.location_offset()
6849                            ..scope.selector.name.location_offset() + scope.selector.name.len(),
6850                    )
6851                    .with_message("Unrecognized Selector"),
6852                )
6853                .finish();
6854            Err(ParseErrs::from_report(report, scope.block.content.extra().clone()).into())
6855        }
6856    }
6857}
6858
6859fn parse_bind_pipelines_scope<I: Span>(input: I) -> Result<Spanned<I, BindScopeKind>, ParseErrs> {
6860    unimplemented!()
6861    /*
6862    let (next, lex_scopes) = lex_scopes(input.clone())?;
6863    let mut errs = vec![];
6864    for lex_scope in lex_scopes {
6865        match lex_scope.selector.name.to_string().as_str() {
6866            "Ext" => {}
6867            "Http" => {}
6868            "Rc" => {}
6869            what => {
6870                let mut builder = Report::build(ReportKind::Error, (), 0);
6871                let report = builder
6872                    .with_message(format!("Unrecognized Pipeline scope: '{}'", what))
6873                    .with_label(
6874                        Label::new(input.location_offset()..input.location_offset())
6875                            .with_message("Unrecognized Selector"),
6876                    )
6877                    .finish();
6878                errs.push(ParseErrs::new(report, input.extra.clone()));
6879            }
6880        }
6881    }
6882
6883    if !errs.is_empty() {
6884        Err(ParseErrs::fold(errs))
6885    } else {
6886        Ok(ElemSpan::new(BindBlock::Pipelines, input.clone()))
6887    }
6888
6889     */
6890}
6891
6892pub fn nospace0<I: Span>(input: I) -> Res<I, I> {
6893    recognize(many0(satisfy(|c| !c.is_whitespace())))(input)
6894}
6895
6896pub fn nospace1<I: Span>(input: I) -> Res<I, I> {
6897    recognize(pair(
6898        satisfy(|c| !c.is_whitespace()),
6899        many0(satisfy(|c| !c.is_whitespace())),
6900    ))(input)
6901}
6902pub fn nospace1_nosemi<I: Span>(input: I) -> Res<I, I> {
6903    recognize(pair(
6904        satisfy(|c| !c.is_whitespace() && ';' != c),
6905        many0(satisfy(|c| !c.is_whitespace( ) && ';' != c)),
6906    ))(input)
6907}
6908
6909
6910
6911pub fn no_space_with_blocks<I: Span>(input: I) -> Res<I, I> {
6912    recognize(many1(alt((recognize(any_block), nospace1))))(input)
6913}
6914
6915pub fn pipeline_step_var<I: Span>(input: I) -> Res<I, PipelineStepVar> {
6916    context(
6917        "pipeline:step",
6918        tuple((
6919            alt((
6920                value(WaveDirection::Direct, tag("-")),
6921                value(WaveDirection::Reflect, tag("=")),
6922            )),
6923            opt(pair(
6924                delimited(
6925                    tag("["),
6926                    context("pipeline:step:exit", cut(request_payload_filter_block)),
6927                    tag("]"),
6928                ),
6929                context(
6930                    "pipeline:step:payload",
6931                    cut(alt((
6932                        value(WaveDirection::Direct, tag("-")),
6933                        value(WaveDirection::Reflect, tag("=")),
6934                    ))),
6935                ),
6936            )),
6937            context("pipeline:step:exit", cut(tag(">"))),
6938        )),
6939    )(input)
6940    .map(|(next, (entry, block_and_exit, _))| {
6941        let mut blocks = vec![];
6942        let exit = match block_and_exit {
6943            None => entry.clone(),
6944            Some((block, exit)) => {
6945                blocks.push(block);
6946                exit
6947            }
6948        };
6949
6950        (
6951            next,
6952            PipelineStepVar {
6953                entry,
6954                exit,
6955                blocks,
6956            },
6957        )
6958    })
6959}
6960
6961pub fn core_pipeline_stop<I: Span>(input: I) -> Res<I, PipelineStopVar> {
6962    context(
6963        "Core",
6964        delimited(
6965            tag("(("),
6966            delimited(multispace0, opt(tag("*")), multispace0),
6967            tag("))"),
6968        ),
6969    )(input)
6970    .map(|(next, _)| (next, PipelineStopVar::Core))
6971}
6972
6973pub fn return_pipeline_stop<I: Span>(input: I) -> Res<I, PipelineStopVar> {
6974    tag("&")(input).map(|(next, _)| (next, PipelineStopVar::Reflect))
6975}
6976
6977pub fn call_pipeline_stop<I: Span>(input: I) -> Res<I, PipelineStopVar> {
6978    context("Call", call)(input).map(|(next, call)| (next, PipelineStopVar::Call(call)))
6979}
6980
6981pub fn point_pipeline_stop<I: Span>(input: I) -> Res<I, PipelineStopVar> {
6982    context("pipeline:stop:point", point_var)(input)
6983        .map(|(next, point)| (next, PipelineStopVar::Point(point)))
6984}
6985
6986pub fn pipeline_stop_var<I: Span>(input: I) -> Res<I, PipelineStopVar> {
6987    context(
6988        "Stop",
6989        pair(
6990            context(
6991                "pipeline:stop:expecting",
6992                cut(peek(alt((tag("(("), tag("."), alpha1, tag("&"))))),
6993            ),
6994            alt((
6995                core_pipeline_stop,
6996                return_pipeline_stop,
6997                call_pipeline_stop,
6998                point_pipeline_stop,
6999            )),
7000        ),
7001    )(input)
7002    .map(|(next, (_, pipeline_stop))| (next, pipeline_stop))
7003}
7004
7005pub fn consume_pipeline_step<I: Span>(input: I) -> Res<I, PipelineStepVar> {
7006    all_consuming(pipeline_step_var)(input)
7007}
7008
7009pub fn consume_pipeline_stop<I: Span>(input: I) -> Res<I, PipelineStopVar> {
7010    all_consuming(pipeline_stop_var)(input)
7011}
7012
7013pub fn pipeline_segment<I: Span>(input: I) -> Res<I, PipelineSegmentVar> {
7014    tuple((
7015        multispace0,
7016        pipeline_step_var,
7017        multispace0,
7018        pipeline_stop_var,
7019        multispace0,
7020    ))(input)
7021    .map(|(next, (_, step, _, stop, _))| (next, PipelineSegmentVar { step, stop }))
7022}
7023
7024pub fn pipeline<I: Span>(input: I) -> Res<I, PipelineVar> {
7025    context(
7026        "pipeline",
7027        many0(delimited(multispace0, pipeline_segment, multispace0)),
7028    )(input)
7029    .map(|(next, segments)| (next, PipelineVar { segments }))
7030}
7031
7032pub fn consume_pipeline<I: Span>(input: I) -> Res<I, PipelineVar> {
7033    all_consuming(pipeline)(input)
7034}
7035
7036/*
7037pub fn entity_selectors<I:Span>(input: Span) -> Res<Span, Vec<Selector<PipelineSelector>>> {
7038    many0(delimited(multispace0, entity_selector, multispace0))(input)
7039}
7040
7041pub fn entity_selector<I:Span>(input: Span) -> Res<Span, Selector<PipelineSelector>> {
7042    tuple((entity_pattern, multispace0, pipeline, tag(";")))(input)
7043        .map(|(next, (pattern, _, pipeline, _))| (next, Selector::new(pattern, pipeline)))
7044}
7045
7046pub fn msg_selector<I:Span>(input: Span) -> Res<Span, Selector<ExtPipelineSelector>> {
7047    tuple((msg_pattern_scoped, multispace0, pipeline, tag(";")))(input)
7048        .map(|(next, (pattern, _, pipeline, _))| (next, Selector::new(pattern, pipeline)))
7049}
7050
7051pub fn http_pipeline<I:Span>(input: Span) -> Res<Span, Selector<HttpPipelineSelector>> {
7052    tuple((http_pattern_scoped, multispace0, pipeline, tag(";")))(input)
7053        .map(|(next, (pattern, _, pipeline, _))| (next, Selector::new(pattern, pipeline)))
7054}
7055
7056pub fn rc_selector<I:Span>(input: Span) -> Res<Span, Selector<RcPipelineSelector>> {
7057    tuple((rc_pattern_scoped, multispace0, pipeline, tag(";")))(input)
7058        .map(|(next, (pattern, _, pipeline, _))| (next, Selector::new(pattern, pipeline)))
7059}
7060
7061pub fn consume_selector<I:Span>(input: Span) -> Res<Span, Selector<PipelineSelector>> {
7062    all_consuming(entity_selector)(input)
7063}
7064
7065 */
7066
7067pub fn subst<I: Span, F>(f: F) -> impl FnMut(I) -> Res<I, Subst<I>>
7068where
7069    F: FnMut(I) -> Res<I, I> + Copy,
7070{
7071    move |input: I| {
7072        many1(chunk(f))(input.clone()).map(|(next, chunks)| {
7073            let len: usize = chunks.iter().map(|c| c.len()).sum();
7074            let span = input.slice(0..input.len() - next.len());
7075            let chunks = Subst {
7076                chunks,
7077                trace: span.trace(),
7078            };
7079            (next, chunks)
7080        })
7081    }
7082}
7083
7084pub fn chunk<I: Span, F>(mut f: F) -> impl FnMut(I) -> Res<I, Chunk<I>> + Copy
7085where
7086    F: FnMut(I) -> Res<I, I> + Copy,
7087{
7088    move |input: I| alt((var_chunk, text_chunk(f)))(input)
7089}
7090
7091pub fn text_chunk<I: Span, F>(mut f: F) -> impl FnMut(I) -> Res<I, Chunk<I>> + Copy
7092where
7093    F: FnMut(I) -> Res<I, I> + Copy,
7094{
7095    move |input: I| f(input).map(|(next, text)| (next, Chunk::Text(text)))
7096}
7097
7098pub fn var_chunk<I: Span>(input: I) -> Res<I, Chunk<I>> {
7099    preceded(
7100        tag("$"),
7101        context(
7102            "variable",
7103            cut(delimited(
7104                context("variable:open", cut(tag("{"))),
7105                context("variable:name", variable_name),
7106                context("variable:close", cut(tag("}"))),
7107            )),
7108        ),
7109    )(input)
7110    .map(|(next, variable_name)| (next, Chunk::Var(variable_name)))
7111}
7112/*
7113pub fn unwrap_route_selector(input: &str ) -> Result<RouteSelector,ExtErr> {
7114    let input = new_span(input);
7115    let input = result(unwrap_block( BlockKind::Nested(NestedBlockKind::Parens),input))?;
7116}
7117
7118 */
7119pub fn route_attribute(input: &str) -> Result<RouteSelector, SpaceErr> {
7120    let input = new_span(input);
7121    let (_, (_, lex_route)) = result(pair(
7122        tag("#"),
7123        unwrap_block(
7124            BlockKind::Nested(NestedBlockKind::Square),
7125            pair(
7126                tag("route"),
7127                unwrap_block(
7128                    BlockKind::Nested(NestedBlockKind::Parens),
7129                    unwrap_block(
7130                        BlockKind::Delimited(DelimitedBlockKind::DoubleQuotes),
7131                        nospace0,
7132                    ),
7133                ),
7134            ),
7135        ),
7136    )(input.clone()))?;
7137
7138    route_selector(lex_route)
7139}
7140
7141pub fn route_attribute_value(input: &str) -> Result<RouteSelector, SpaceErr> {
7142    let input = new_span(input);
7143    let lex_route = result(unwrap_block(
7144        BlockKind::Delimited(DelimitedBlockKind::DoubleQuotes),
7145        trim(nospace0),
7146    )(input.clone()))?;
7147
7148    route_selector(lex_route)
7149}
7150
7151/*
7152pub fn topic<I: Span>(input: I) -> Res<I, ValuePattern<Topic>> {
7153    context(
7154        "topic",
7155        delimited(tag("["), value_pattern(skewer_case_chars), tag("]::")),
7156    )(input)
7157    .map(|(next, topic)| {
7158        let topic = match topic {
7159            ValuePattern::Any => ValuePattern::Any,
7160            ValuePattern::None => ValuePattern::None,
7161            ValuePattern::Pattern(topic) => ValuePattern::Pattern(Topic::Tag(topic.to_string())),
7162        };
7163        (next, topic)
7164    })
7165}
7166
7167 */
7168
7169pub fn route_selector<I: Span>(input: I) -> Result<RouteSelector, SpaceErr> {
7170    let (next, (topic, lex_route)) = match pair(
7171        opt(terminated(
7172            unwrap_block(
7173                BlockKind::Nested(NestedBlockKind::Square),
7174                value_pattern(topic),
7175            ),
7176            tag("::"),
7177        )),
7178        lex_route_selector,
7179    )(input.clone())
7180    {
7181        Ok((next, (topic, lex_route))) => (next, (topic, lex_route)),
7182        Err(err) => {
7183            return Err(find_parse_err(&err));
7184        }
7185    };
7186
7187    if next.len() > 0 {
7188        return Err(ParseErrs::from_loc_span(
7189            "could not consume entire route selector",
7190            "extra",
7191            next,
7192        )
7193        .into());
7194    }
7195
7196    let mut names = lex_route.names.clone();
7197    names.reverse();
7198    let method_kind_span = names
7199        .pop()
7200        .ok_or(ParseErrs::from_loc_span(
7201            "expecting MethodKind [ Http, Ext ]",
7202            "expecting MethodKind",
7203            input,
7204        ))?
7205        .clone();
7206    let method_kind = result(value_pattern(method_kind)(method_kind_span.clone()))?;
7207    let method = match &method_kind {
7208        ValuePattern::Any => ValuePattern::Any,
7209        ValuePattern::None => ValuePattern::None,
7210        ValuePattern::Pattern(method_kind) => match method_kind {
7211            MethodKind::Hyp => {
7212                let method = names.pop().ok_or(ParseErrs::from_loc_span(
7213                    "Hyp method requires a sub kind i.e. Hyp<Assign> or Ext<*>",
7214                    "sub kind required",
7215                    method_kind_span,
7216                ))?;
7217                let method = result(value_pattern(sys_method)(method))?;
7218                ValuePattern::Pattern(MethodPattern::Hyp(method))
7219            }
7220            MethodKind::Cmd => {
7221                let method = names.pop().ok_or(ParseErrs::from_loc_span(
7222                    "Cmd method requires a sub kind i.e. Cmd<Bounce>",
7223                    "sub kind required",
7224                    method_kind_span,
7225                ))?;
7226                let method = result(value_pattern(cmd_method)(method))?;
7227                ValuePattern::Pattern(MethodPattern::Cmd(method))
7228            }
7229            MethodKind::Ext => {
7230                let method = names.pop().ok_or(ParseErrs::from_loc_span(
7231                    "Ext method requires a sub kind i.e. Ext<SomeExt> or Ext<*>",
7232                    "sub kind required",
7233                    method_kind_span,
7234                ))?;
7235                let method = result(value_pattern(ext_method)(method))?;
7236                ValuePattern::Pattern(MethodPattern::Ext(method))
7237            }
7238            MethodKind::Http => {
7239                let method = names.pop().ok_or(ParseErrs::from_loc_span(
7240                    "Http method requires a sub kind i.e. Http<Get> or Http<*>",
7241                    "sub kind required",
7242                    method_kind_span,
7243                ))?;
7244                let method = result(value_pattern(http_method)(method))?;
7245                ValuePattern::Pattern(MethodPattern::Http(method))
7246            }
7247        },
7248    };
7249
7250    if !names.is_empty() {
7251        let name = names.pop().unwrap();
7252        return Err(ParseErrs::from_loc_span("Too many SubKinds: only Http/Ext supported with one subkind i.e. Http<Get>, Ext<MyMethod>", "too many subkinds", name).into());
7253    }
7254
7255    let path = match lex_route.path.as_ref() {
7256        None => Regex::new("/.*").unwrap(),
7257        Some(i) => match Regex::new(i.to_string().as_str()) {
7258            Ok(path) => path,
7259            Err(err) => {
7260                return Err(ParseErrs::from_loc_span(
7261                    format!("cannot parse Path regex: '{}'", err.to_string()).as_str(),
7262                    "path regex error",
7263                    i.clone(),
7264                ));
7265            }
7266        },
7267    };
7268
7269    Ok(RouteSelector::new(
7270        topic,
7271        method,
7272        path,
7273        lex_route.filters.to_scope_filters(),
7274    ))
7275}
7276
7277#[cfg(test)]
7278pub mod test {
7279    use std::rc::Rc;
7280    use std::str::FromStr;
7281    use std::sync::Arc;
7282
7283    use bincode::config;
7284    use nom::branch::alt;
7285    use nom::bytes::complete::{escaped, tag};
7286    use nom::character::complete::{alpha1, alphanumeric1, anychar, multispace0};
7287    use nom::character::is_alphanumeric;
7288    use nom::combinator::{all_consuming, eof, not, opt, peek, recognize};
7289    use nom::error::context;
7290    use nom::multi::{many0, many1};
7291    use nom::sequence::{delimited, pair, terminated, tuple};
7292    use nom::IResult;
7293    use nom_locate::LocatedSpan;
7294    use nom_supreme::error::ErrorTree;
7295
7296    use cosmic_nom::{new_span, Res, span_with_extra};
7297
7298    use crate::command::direct::create::{
7299        PointSegTemplate, PointTemplate, PointTemplateCtx, Template,
7300    };
7301    use crate::command::Command;
7302    use crate::config::Document;
7303    use crate::err::{ParseErrs, SpaceErr};
7304    use crate::parse::error::result;
7305    use crate::parse::model::{
7306        BlockKind, DelimitedBlockKind, LexScope, NestedBlockKind, TerminatedBlockKind,
7307    };
7308    use crate::parse::{args, assignment, base_point_segment, base_seg, command_line, comment, consume_point_var, create, create_command, doc, Env, expected_block_terminator_or_non_terminator, lex_block, lex_child_scopes, lex_nested_block, lex_scope, lex_scope_pipeline_step_and_block, lex_scope_selector, lex_scopes, lowercase1, MapResolver, mesh_eos, mesh_seg, nested_block, nested_block_content, next_stacked_name, no_comment, parse_bind_config, parse_include_blocks, parse_inner_block, parse_mechtron_config, path_regex, pipeline, pipeline_segment, pipeline_step_var, pipeline_stop_var, point_non_root_var, point_template, point_var, pop, rec_version, root_ctx_seg, root_scope, root_scope_selector, route_attribute, route_selector, scope_filter, scope_filters, skewer_case_chars, skewer_dot, space_chars, space_no_dupe_dots, space_point_segment, strip_comments, subst, SubstParser, template, var_seg, variable_name, VarResolver, version, version_point_segment, wrapper};
7309    use crate::point::{Point, PointCtx, PointSegVar, RouteSegVar};
7310    use crate::substance::Substance;
7311    use crate::util;
7312    use crate::util::{log, ToResolved};
7313
7314    #[test]
7315    pub fn test_assignment() {
7316        let config = "+bin=some:bin:somewhere;";
7317        let assign = log(result(assignment(new_span(config)))).unwrap();
7318        assert_eq!(assign.key.as_str(), "bin");
7319        assert_eq!(assign.value.as_str(), "some:bin:somewhere");
7320
7321        let config = "    +bin   =    some:bin:somewhere;";
7322        log(result(assignment(new_span(config)))).unwrap();
7323
7324        let config = "    noplus =    some:bin:somewhere;";
7325        assert!(log(result(assignment(new_span(config)))).is_err());
7326        let config = "   +nothing ";
7327        assert!(log(result(assignment(new_span(config)))).is_err());
7328        let config = "   +nothing  = ";
7329        assert!(log(result(assignment(new_span(config)))).is_err());
7330
7331    }
7332
7333
7334    #[test]
7335    pub fn test_mechtron_config() {
7336        let config = r#"
7337
7338Mechtron(version=1.0.0) {
7339    Wasm {
7340      +bin=repo:1.0.0:/wasm/blah.wasm;
7341      +name=my-mechtron;
7342    }
7343}
7344
7345         "#;
7346
7347        let doc = log(doc(config)).unwrap();
7348
7349        if let Document::MechtronConfig(_) = doc {
7350        } else {
7351            assert!(false)
7352        }
7353    }
7354
7355
7356
7357        #[test]
7358    pub fn test_bad_mechtron_config() {
7359        let config = r#"
7360
7361Mechtron(version=1.0.0) {
7362    Wasm
7363    varool
7364      +bin=repo:1.0.0:/wasm/blah.wasm;
7365      +name=my-mechtron;
7366    }
7367}
7368
7369         "#;
7370
7371        let doc = log(doc(config)).is_err();
7372
7373
7374    }
7375
7376
7377    #[test]
7378    pub fn test_message_selector() {
7379        let route =
7380            util::log(route_attribute("#[route(\"[Topic<*>]::Ext<NewSession>\")]")).unwrap();
7381        let route = util::log(route_attribute("#[route(\"Hyp<Assign>\")]")).unwrap();
7382
7383        println!("path: {}", route.path.to_string());
7384        //println!("filters: {}", route.filters.first().unwrap().name)
7385    }
7386
7387    #[test]
7388    pub fn test_create_command() -> Result<(), SpaceErr> {
7389        let command = util::log(result(command_line(new_span("create localhost<Space>"))))?;
7390        let env = Env::new(Point::root());
7391        let command: Command = util::log(command.to_resolved(&env))?;
7392        Ok(())
7393    }
7394
7395//    #[test]
7396    pub fn test_command_line_err() -> Result<(), SpaceErr> {
7397        let command = util::log(result(command_line(new_span("create localhost<bad>"))))?;
7398        let env = Env::new(Point::root());
7399        let command: Command = util::log(command.to_resolved(&env))?;
7400        Ok(())
7401    }
7402
7403    #[test]
7404    pub fn test_template() -> Result<(), SpaceErr> {
7405        let t = util::log(result(all_consuming(template)(new_span(
7406            "localhost<Space>",
7407        ))))?;
7408        let env = Env::new(Point::root());
7409        let t: Template = util::log(t.to_resolved(&env))?;
7410
7411        let t = util::log(result(base_point_segment(new_span(
7412            "localhost:base<Space>",
7413        ))))?;
7414
7415        let (space, bases): (PointSegVar, Vec<PointSegVar>) = util::log(result(tuple((
7416            var_seg(root_ctx_seg(space_point_segment)),
7417            many0(base_seg(var_seg(pop(base_point_segment)))),
7418        ))(
7419            new_span("localhost:base:nopo<Space>"),
7420        )))?;
7421        println!("space: {}", space.to_string());
7422        for base in bases {
7423            println!("\tbase: {}", base.to_string());
7424        }
7425        //let t= util::log(result(all_consuming(template)(new_span("localhost:base<Space>"))))?;
7426        //        let env = Env::new(Point::root());
7427        //       let t: Template = util::log(t.to_resolved(&env))?;
7428
7429        Ok(())
7430    }
7431
7432    #[test]
7433    pub fn test_point_template() -> Result<(), SpaceErr> {
7434        assert!(mesh_eos(new_span(":")).is_ok());
7435        assert!(mesh_eos(new_span("%")).is_ok());
7436        assert!(mesh_eos(new_span("x")).is_err());
7437
7438        assert!(point_var(new_span("localhost:some-%")).is_ok());
7439
7440        util::log(result(all_consuming(point_template)(new_span("localhost"))))?;
7441
7442        let template = util::log(result(point_template(new_span("localhost:other:some-%"))))?;
7443        let template: PointTemplate = util::log(template.collapse())?;
7444        if let PointSegTemplate::Pattern(child) = template.child_segment_template {
7445            assert_eq!(child.as_str(), "some-%")
7446        }
7447
7448        util::log(result(point_template(new_span("my-domain.com"))))?;
7449        util::log(result(point_template(new_span("ROOT"))))?;
7450        Ok(())
7451    }
7452
7453    //    #[test]
7454    pub fn test_point_var() -> Result<(), SpaceErr> {
7455        util::log(result(all_consuming(point_var)(new_span(
7456            "[hub]::my-domain.com:${name}:base",
7457        ))))?;
7458        util::log(result(all_consuming(point_var)(new_span(
7459            "[hub]::my-domain.com:1.0.0:/dorko/x/",
7460        ))))?;
7461        util::log(result(all_consuming(point_var)(new_span(
7462            "[hub]::my-domain.com:1.0.0:/dorko/${x}/",
7463        ))))?;
7464        util::log(result(all_consuming(point_var)(new_span(
7465            "[hub]::.:1.0.0:/dorko/${x}/",
7466        ))))?;
7467        util::log(result(all_consuming(point_var)(new_span(
7468            "[hub]::..:1.0.0:/dorko/${x}/",
7469        ))))?;
7470        let point = util::log(result(point_var(new_span(
7471            "[hub]::my-domain.com:1.0.0:/dorko/${x}/file.txt",
7472        ))))?;
7473        if let Some(PointSegVar::Var(var)) = point.segments.get(4) {
7474            assert_eq!("x", var.name.as_str());
7475        } else {
7476            assert!(false);
7477        }
7478
7479        if let Some(PointSegVar::File(file)) = point.segments.get(5) {
7480            assert_eq!("file.txt", file.as_str());
7481        } else {
7482            assert!(false);
7483        }
7484
7485        let point = util::log(result(point_var(new_span(
7486            "${route}::my-domain.com:${name}:base",
7487        ))))?;
7488
7489        // this one SHOULD fail and an appropriate error should be located at BAD
7490        util::log(result(point_var(new_span(
7491            "${route of routes}::my-domain.com:${BAD}:base",
7492        ))));
7493
7494        if let RouteSegVar::Var(ref var) = point.route {
7495            assert_eq!("route", var.name.as_str());
7496        } else {
7497            assert!(false);
7498        }
7499
7500        if let Some(PointSegVar::Space(space)) = point.segments.get(0) {
7501            assert_eq!("my-domain.com", space.as_str());
7502        } else {
7503            assert!(false);
7504        }
7505
7506        if let Some(PointSegVar::Var(var)) = point.segments.get(1) {
7507            assert_eq!("name", var.name.as_str());
7508        } else {
7509            assert!(false);
7510        }
7511
7512        if let Some(PointSegVar::Base(base)) = point.segments.get(2) {
7513            assert_eq!("base", base.as_str());
7514        } else {
7515            assert!(false);
7516        }
7517
7518        let mut env = Env::new(Point::from_str("my-domain.com")?);
7519        env.set_var("route", Substance::Text("[hub]".to_string()));
7520        env.set_var("name", Substance::Text("zophis".to_string()));
7521        let point: Point = point.to_resolved(&env)?;
7522        println!("point.to_string(): {}", point.to_string());
7523
7524        util::log(
7525            util::log(result(all_consuming(point_var)(new_span(
7526                "[hub]::my-domain.com:1.0.0:/dorko/x/",
7527            ))))?
7528            .to_point(),
7529        );
7530        util::log(
7531            util::log(result(all_consuming(point_var)(new_span(
7532                "[hub]::my-domain.com:1.0.0:/${dorko}/x/",
7533            ))))?
7534            .to_point(),
7535        );
7536        util::log(
7537            util::log(result(all_consuming(point_var)(new_span(
7538                "${not-supported}::my-domain.com:1.0.0:/${dorko}/x/",
7539            ))))?
7540            .to_point(),
7541        );
7542
7543        let point = util::log(result(point_var(new_span("${route}::${root}:base1"))))?;
7544        let mut env = Env::new(Point::from_str("my-domain.com:blah")?);
7545        env.set_var("route", Substance::Text("[hub]".to_string()));
7546        env.set_var("root", Substance::Text("..".to_string()));
7547
7548        let point: PointCtx = util::log(point.to_resolved(&env))?;
7549
7550        /*
7551                let resolver = Env::new(Point::from_str("my-domain.com:under:over")?);
7552                let point = log(consume_point_var("../../hello") )?;
7553        //        let point: Point = log(point.to_resolved(&resolver))?;
7554          //      println!("point.to_string(): {}", point.to_string());
7555                let _: Result<Point, ExtErr> = log(log(result(all_consuming(point_var)(new_span(
7556                    "${not-supported}::my-domain.com:1.0.0:/${dorko}/x/",
7557                )))?
7558                    .to_resolved(&env)));
7559
7560                 */
7561        Ok(())
7562    }
7563
7564    #[test]
7565    pub fn test_point() -> Result<(), SpaceErr> {
7566        util::log(
7567            result(all_consuming(point_var)(new_span(
7568                "[hub]::my-domain.com:name:base",
7569            )))?
7570            .to_point(),
7571        )?;
7572        util::log(
7573            result(all_consuming(point_var)(new_span(
7574                "[hub]::my-domain.com:1.0.0:/dorko/x/",
7575            )))?
7576            .to_point(),
7577        )?;
7578        util::log(
7579            result(all_consuming(point_var)(new_span(
7580                "[hub]::my-domain.com:1.0.0:/dorko/xyz/",
7581            )))?
7582            .to_point(),
7583        )?;
7584
7585        Ok(())
7586    }
7587
7588    #[test]
7589    pub fn test_simple_point_var() -> Result<(), SpaceErr> {
7590        /*
7591        let point = util::log(result(point_var(new_span("localhost:base"))))?;
7592        println!("point '{}'", point.to_string());
7593        let point :Point = point.collapse()?;
7594        assert_eq!("localhost:base", point.to_string().as_str());
7595        let point = util::log(result(point_var(new_span("localhost:base<Kind>"))))?;
7596        let point :Point = point.collapse()?;
7597        assert_eq!("localhost:base", point.to_string().as_str());
7598
7599        let point = util::log(result(point_var(new_span("localhost:base:3.0.0<Kind>"))))?;
7600        let point :Point = point.collapse()?;
7601        assert_eq!("localhost:base:3.0.0", point.to_string().as_str());
7602        let point = util::log(result(point_var(new_span("localhost:base:3.0.0:/some/file.txt<Kind>"))))?;
7603        assert_eq!("localhost:base:3.0.0:/some/file.txt", point.to_string().as_str());
7604        let point :Point = point.collapse()?;
7605        println!("point: '{}'",point.to_string());
7606
7607        for seg in &point.segments {
7608            println!("\tseg: '{}'",seg.to_string());
7609        }
7610        assert_eq!("some/",point.segments.get(4).unwrap().to_string().as_str());
7611
7612         */
7613
7614        let point = util::log(result(point_var(new_span(
7615            "localhost:base:/fs/file.txt<Kind>",
7616        ))))?;
7617        let point: Point = point.collapse()?;
7618        assert_eq!("localhost:base:/fs/file.txt", point.to_string().as_str());
7619
7620        Ok(())
7621    }
7622
7623    #[test]
7624    pub fn test_lex_block() -> Result<(), SpaceErr> {
7625        let esc = result(escaped(anychar, '\\', anychar)(new_span("\\}")))?;
7626        //println!("esc: {}", esc);
7627        util::log(result(all_consuming(lex_block(BlockKind::Nested(
7628            NestedBlockKind::Curly,
7629        )))(new_span("{}"))))?;
7630        util::log(result(all_consuming(lex_block(BlockKind::Nested(
7631            NestedBlockKind::Curly,
7632        )))(new_span("{x}"))))?;
7633        util::log(result(all_consuming(lex_block(BlockKind::Nested(
7634            NestedBlockKind::Curly,
7635        )))(new_span("{\\}}"))))?;
7636        util::log(result(all_consuming(lex_block(BlockKind::Delimited(
7637            DelimitedBlockKind::SingleQuotes,
7638        )))(new_span("'hello'"))))?;
7639        util::log(result(all_consuming(lex_block(BlockKind::Delimited(
7640            DelimitedBlockKind::SingleQuotes,
7641        )))(new_span("'ain\\'t it cool?'"))))?;
7642
7643        //assert!(log(result(all_consuming(lex_block( BlockKind::Nested(NestedBlockKind::Curly)))(create_span("{ }}")))).is_err());
7644        Ok(())
7645    }
7646    #[test]
7647    pub fn test_path_regex2() -> Result<(), SpaceErr> {
7648        util::log(result(path_regex(new_span("/xyz"))))?;
7649        Ok(())
7650    }
7651    #[test]
7652    pub fn test_bind_config() -> Result<(), SpaceErr> {
7653        let bind_config_str = r#"Bind(version=1.0.0)  { Route<Http> -> { <Get> -> ((*)) => &; } }
7654        "#;
7655
7656        util::log(doc(bind_config_str))?;
7657        if let Document::BindConfig(bind) = util::log(doc(bind_config_str))? {
7658            assert_eq!(bind.route_scopes().len(), 1);
7659            let mut pipelines = bind.route_scopes();
7660            let pipeline_scope = pipelines.pop().unwrap();
7661            assert_eq!(pipeline_scope.selector.selector.name.as_str(), "Route");
7662            let message_scope = pipeline_scope.block.first().unwrap();
7663            assert_eq!(
7664                message_scope.selector.selector.name.to_string().as_str(),
7665                "Http"
7666            );
7667            let method_scope = message_scope.block.first().unwrap();
7668            assert_eq!(
7669                method_scope.selector.selector.name.to_string().as_str(),
7670                "Http<Get>"
7671            );
7672        } else {
7673            assert!(false);
7674        }
7675
7676        let bind_config_str = r#"Bind(version=1.0.0)  {
7677              Route<Ext<Create>> -> localhost:app => &;
7678           }"#;
7679
7680        if let Document::BindConfig(bind) = util::log(doc(bind_config_str))? {
7681            assert_eq!(bind.route_scopes().len(), 1);
7682            let mut pipelines = bind.route_scopes();
7683            let pipeline_scope = pipelines.pop().unwrap();
7684            assert_eq!(pipeline_scope.selector.selector.name.as_str(), "Route");
7685            let message_scope = pipeline_scope.block.first().unwrap();
7686            assert_eq!(
7687                message_scope.selector.selector.name.to_string().as_str(),
7688                "Ext"
7689            );
7690            let action_scope = message_scope.block.first().unwrap();
7691            assert_eq!(
7692                action_scope.selector.selector.name.to_string().as_str(),
7693                "Ext<Create>"
7694            );
7695        } else {
7696            assert!(false);
7697        }
7698
7699        let bind_config_str = r#"  Bind(version=1.0.0) {
7700              Route -> {
7701                 <*> -> {
7702                    <Get>/users/(?P<user>)/.* -> localhost:users:${user} => &;
7703                 }
7704              }
7705           }
7706
7707           "#;
7708        util::log(doc(bind_config_str))?;
7709
7710        let bind_config_str = r#"  Bind(version=1.0.0) {
7711              Route -> {
7712                 <Http<*>>/users -> localhost:users => &;
7713              }
7714           }
7715
7716           "#;
7717        util::log(doc(bind_config_str))?;
7718
7719        let bind_config_str = r#"  Bind(version=1.0.0) {
7720              * -> { // This should fail since Route needs to be defined
7721                 <*> -> {
7722                    <Get>/users -> localhost:users => &;
7723                 }
7724              }
7725           }
7726
7727           "#;
7728        assert!(util::log(doc(bind_config_str)).is_err());
7729        let bind_config_str = r#"  Bind(version=1.0.0) {
7730              Route<Rc> -> {
7731                Create ; Bok;
7732                  }
7733           }
7734
7735           "#;
7736        assert!(util::log(doc(bind_config_str)).is_err());
7737        //   assert!(log(config(bind_config_str)).is_err());
7738
7739        Ok(())
7740    }
7741
7742    #[test]
7743    pub fn test_pipeline_segment() -> Result<(), SpaceErr> {
7744        util::log(result(pipeline_segment(new_span("-> localhost"))))?;
7745        assert!(util::log(result(pipeline_segment(new_span("->")))).is_err());
7746        assert!(util::log(result(pipeline_segment(new_span("localhost")))).is_err());
7747        Ok(())
7748    }
7749
7750    #[test]
7751    pub fn test_pipeline_stop() -> Result<(), SpaceErr> {
7752        util::log(result(space_chars(new_span("localhost"))))?;
7753        util::log(result(space_no_dupe_dots(new_span("localhost"))))?;
7754
7755        util::log(result(mesh_eos(new_span(""))))?;
7756        util::log(result(mesh_eos(new_span(":"))))?;
7757
7758        util::log(result(recognize(tuple((
7759            context("point:space_segment_leading", peek(alpha1)),
7760            space_no_dupe_dots,
7761            space_chars,
7762        )))(new_span("localhost"))))?;
7763        util::log(result(space_point_segment(new_span("localhost.com"))))?;
7764
7765        util::log(result(point_var(new_span("mechtron.io:app:hello")))?.to_point())?;
7766        util::log(result(pipeline_stop_var(new_span("localhost:app:hello"))))?;
7767        Ok(())
7768    }
7769
7770    #[test]
7771    pub fn test_pipeline() -> Result<(), SpaceErr> {
7772        util::log(result(pipeline(new_span("-> localhost => &"))))?;
7773        Ok(())
7774    }
7775
7776    #[test]
7777    pub fn test_pipeline_step() -> Result<(), SpaceErr> {
7778        util::log(result(pipeline_step_var(new_span("->"))))?;
7779        util::log(result(pipeline_step_var(new_span("-[ Text ]->"))))?;
7780        util::log(result(pipeline_step_var(new_span("-[ Text ]=>"))))?;
7781        util::log(result(pipeline_step_var(new_span("=[ Text ]=>"))))?;
7782
7783        assert!(util::log(result(pipeline_step_var(new_span("=")))).is_err());
7784        assert!(util::log(result(pipeline_step_var(new_span("-[ Bin ]=")))).is_err());
7785        assert!(util::log(result(pipeline_step_var(new_span("[ Bin ]=>")))).is_err());
7786        Ok(())
7787    }
7788
7789    #[test]
7790    pub fn test_rough_bind_config() -> Result<(), SpaceErr> {
7791        let unknown_config_kind = r#"
7792Unknown(version=1.0.0) # mem unknown config kind
7793{
7794    Route{
7795    }
7796}"#;
7797        let unsupported_bind_version = r#"
7798Bind(version=100.0.0) # mem unsupported version
7799{
7800    Route{
7801    }
7802}"#;
7803        let multiple_unknown_sub_selectors = r#"
7804Bind(version=1.0.0)
7805{
7806    Whatever -> { # Someone doesn't care what sub selectors he creates
7807    }
7808
7809    Dude(filter $(value)) -> {}  # he doesn't care one bit!
7810
7811}"#;
7812
7813        let now_we_got_rows_to_parse = r#"
7814Bind(version=1.0.0)
7815{
7816    Route(auth) -> {
7817       Http {
7818          <$(method=.*)>/users/$(user=.*)/$(path=.*)-> localhost:app:users:$(user)^Http<$(method)>/$(path) => &;
7819          <Get>/logout -> localhost:app:mechtrons:logout-handler => &;
7820       }
7821    }
7822
7823    Route -> {
7824       Ext<FullStop> -> localhost:apps:
7825       * -> localhost:app:bad-page => &;
7826    }
7827
7828
7829}"#;
7830        util::log(doc(unknown_config_kind));
7831        util::log(doc(unsupported_bind_version));
7832        util::log(doc(multiple_unknown_sub_selectors));
7833        util::log(doc(now_we_got_rows_to_parse));
7834
7835        Ok(())
7836    }
7837
7838    #[test]
7839    pub fn test_remove_comments() -> Result<(), SpaceErr> {
7840        let bind_str = r#"
7841# this is a mem of comments
7842Bind(version=1.0.0)->
7843{
7844  # let's see if it works a couple of spaces in.
7845  Route(auth)-> {  # and if it works on teh same line as something we wan to keep
7846
7847  }
7848
7849  # looky!  I deliberatly put an error here (space between the filter and the kazing -> )
7850  # My hope is that we will get a an appropriate error message WITH COMMENTS INTACT
7851  Route(noauth)-> # look!  I made a boo boo
7852  {
7853     # nothign to see here
7854  }
7855}"#;
7856
7857        match doc(bind_str) {
7858            Ok(_) => {}
7859            Err(err) => {
7860                err.print();
7861            }
7862        }
7863
7864        Ok(())
7865    }
7866
7867    #[test]
7868    pub fn test_version() -> Result<(), SpaceErr> {
7869        rec_version(new_span("1.0.0"))?;
7870        rec_version(new_span("1.0.0-alpha"))?;
7871        version(new_span("1.0.0-alpha"))?;
7872
7873        Ok(())
7874    }
7875    #[test]
7876    pub fn test_rough_block() -> Result<(), SpaceErr> {
7877        result(all_consuming(lex_nested_block(NestedBlockKind::Curly))(
7878            new_span("{  }"),
7879        ))?;
7880        result(all_consuming(lex_nested_block(NestedBlockKind::Curly))(
7881            new_span("{ {} }"),
7882        ))?;
7883        assert!(
7884            result(all_consuming(lex_nested_block(NestedBlockKind::Curly))(
7885                new_span("{ } }")
7886            ))
7887            .is_err()
7888        );
7889        // this is allowed by rough_block
7890        result(all_consuming(lex_nested_block(NestedBlockKind::Curly))(
7891            new_span("{ ] }"),
7892        ))?;
7893
7894        result(lex_nested_block(NestedBlockKind::Curly)(new_span(
7895            r#"x blah
7896
7897
7898Hello my friend
7899
7900
7901        }"#,
7902        )))
7903        .err()
7904        .unwrap()
7905        .print();
7906
7907        result(lex_nested_block(NestedBlockKind::Curly)(new_span(
7908            r#"{
7909
7910Hello my friend
7911
7912
7913        "#,
7914        )))
7915        .err()
7916        .unwrap()
7917        .print();
7918        Ok(())
7919    }
7920
7921    #[test]
7922    pub fn test_block() -> Result<(), SpaceErr> {
7923        util::log(result(lex_nested_block(NestedBlockKind::Curly)(new_span(
7924            "{ <Get> -> localhost; }    ",
7925        ))))?;
7926        if true {
7927            return Ok(());
7928        }
7929        all_consuming(nested_block(NestedBlockKind::Curly))(new_span("{  }"))?;
7930        all_consuming(nested_block(NestedBlockKind::Curly))(new_span("{ {} }"))?;
7931        util::log(result(nested_block(NestedBlockKind::Curly)(new_span(
7932            "{ [] }",
7933        ))))?;
7934        assert!(
7935            expected_block_terminator_or_non_terminator(NestedBlockKind::Curly)(new_span("}"))
7936                .is_ok()
7937        );
7938        assert!(
7939            expected_block_terminator_or_non_terminator(NestedBlockKind::Curly)(new_span("]"))
7940                .is_err()
7941        );
7942        assert!(
7943            expected_block_terminator_or_non_terminator(NestedBlockKind::Square)(new_span("x"))
7944                .is_ok()
7945        );
7946        assert!(nested_block(NestedBlockKind::Curly)(new_span("{ ] }")).is_err());
7947        result(nested_block(NestedBlockKind::Curly)(new_span(
7948            r#"{
7949
7950
7951
7952        ]
7953
7954
7955        }"#,
7956        )))
7957        .err()
7958        .unwrap()
7959        .print();
7960        Ok(())
7961    }
7962
7963    //#[test]
7964    pub fn test_root_scope_selector() -> Result<(), SpaceErr> {
7965        assert!(
7966            (result(root_scope_selector(new_span(
7967                r#"
7968
7969            Bind(version=1.0.0)->"#,
7970            )))
7971            .is_ok())
7972        );
7973
7974        assert!(
7975            (result(root_scope_selector(new_span(
7976                r#"
7977
7978            Bind(version=1.0.0-alpha)->"#,
7979            )))
7980            .is_ok())
7981        );
7982
7983        result(root_scope_selector(new_span(
7984            r#"
7985
7986            Bind(version=1.0.0) ->"#,
7987        )))
7988        .err()
7989        .unwrap()
7990        .print();
7991
7992        result(root_scope_selector(new_span(
7993            r#"
7994
7995        Bind   x"#,
7996        )))
7997        .err()
7998        .unwrap()
7999        .print();
8000
8001        result(root_scope_selector(new_span(
8002            r#"
8003
8004        (Bind(version=3.2.0)   "#,
8005        )))
8006        .err()
8007        .unwrap()
8008        .print();
8009
8010        Ok(())
8011    }
8012
8013    //    #[test]
8014    pub fn test_scope_filter() -> Result<(), SpaceErr> {
8015        result(scope_filter(new_span("(auth)")))?;
8016        result(scope_filter(new_span("(auth )")))?;
8017        result(scope_filter(new_span("(auth hello)")))?;
8018        result(scope_filter(new_span("(auth +hello)")))?;
8019        result(scope_filters(new_span("(auth +hello)->")))?;
8020        result(scope_filters(new_span("(auth +hello)-(filter2)->")))?;
8021        result(scope_filters(new_span("(3auth +hello)-(filter2)->")))
8022            .err()
8023            .unwrap()
8024            .print();
8025        result(scope_filters(new_span("(a?th +hello)-(filter2)->")))
8026            .err()
8027            .unwrap()
8028            .print();
8029        result(scope_filters(new_span("(auth +hello)-(filter2) {}")))
8030            .err()
8031            .unwrap()
8032            .print();
8033
8034        assert!(skewer_case_chars(new_span("3x")).is_err());
8035
8036        Ok(())
8037    }
8038    #[test]
8039    pub fn test_next_selector() {
8040        assert_eq!(
8041            "Http",
8042            next_stacked_name(new_span("Http"))
8043                .unwrap()
8044                .1
8045                 .0
8046                .to_string()
8047                .as_str()
8048        );
8049        assert_eq!(
8050            "Http",
8051            next_stacked_name(new_span("<Http>"))
8052                .unwrap()
8053                .1
8054                 .0
8055                .to_string()
8056                .as_str()
8057        );
8058        assert_eq!(
8059            "Http",
8060            next_stacked_name(new_span("Http<Ext>"))
8061                .unwrap()
8062                .1
8063                 .0
8064                .to_string()
8065                .as_str()
8066        );
8067        assert_eq!(
8068            "Http",
8069            next_stacked_name(new_span("<Http<Ext>>"))
8070                .unwrap()
8071                .1
8072                 .0
8073                .to_string()
8074                .as_str()
8075        );
8076
8077        assert_eq!(
8078            "*",
8079            next_stacked_name(new_span("<*<Ext>>"))
8080                .unwrap()
8081                .1
8082                 .0
8083                .to_string()
8084                .as_str()
8085        );
8086
8087        assert_eq!(
8088            "*",
8089            next_stacked_name(new_span("*"))
8090                .unwrap()
8091                .1
8092                 .0
8093                .to_string()
8094                .as_str()
8095        );
8096
8097        assert!(next_stacked_name(new_span("<*x<Ext>>")).is_err());
8098    }
8099    #[test]
8100    pub fn test_lex_scope2() -> Result<(), SpaceErr> {
8101        /*        let scope = log(result(lex_scopes(create_span(
8102                   "  Get -> {}\n\nPut -> {}   ",
8103               ))))?;
8104
8105        */
8106        util::log(result(many0(delimited(
8107            multispace0,
8108            lex_scope,
8109            multispace0,
8110        ))(new_span(""))))?;
8111        util::log(result(path_regex(new_span("/root/$(subst)"))))?;
8112        util::log(result(path_regex(new_span("/users/$(user=.*)"))))?;
8113
8114        Ok(())
8115    }
8116
8117    #[test]
8118    pub fn test_lex_scope() -> Result<(), SpaceErr> {
8119        let pipes = util::log(result(lex_scope(new_span("Pipes -> {}")))).unwrap();
8120
8121        //        let pipes = log(result(lex_scope(create_span("Pipes {}"))));
8122
8123        assert_eq!(pipes.selector.name.to_string().as_str(), "Pipes");
8124        assert_eq!(pipes.block.kind, BlockKind::Nested(NestedBlockKind::Curly));
8125        assert_eq!(pipes.block.content.len(), 0);
8126        assert!(pipes.selector.filters.is_empty());
8127        assert!(pipes.pipeline_step.is_some());
8128
8129        assert!(util::log(result(lex_scope(new_span("Pipes {}")))).is_err());
8130
8131        let pipes = util::log(result(lex_scope(new_span("Pipes -> 12345;"))))?;
8132        assert_eq!(pipes.selector.name.to_string().as_str(), "Pipes");
8133        assert_eq!(pipes.block.content.to_string().as_str(), "-> 12345");
8134        assert_eq!(
8135            pipes.block.kind,
8136            BlockKind::Terminated(TerminatedBlockKind::Semicolon)
8137        );
8138        assert_eq!(pipes.selector.filters.len(), 0);
8139        assert!(pipes.pipeline_step.is_none());
8140        let pipes = util::log(result(lex_scope(new_span(
8141            //This time adding a space before the 12345... there should be one space in the content, not two
8142            r#"Pipes ->  12345;"#,
8143        ))))?;
8144        assert_eq!(pipes.selector.name.to_string().as_str(), "Pipes");
8145        assert_eq!(pipes.block.content.to_string().as_str(), "->  12345");
8146        assert_eq!(
8147            pipes.block.kind,
8148            BlockKind::Terminated(TerminatedBlockKind::Semicolon)
8149        );
8150        assert_eq!(pipes.selector.filters.len(), 0);
8151        assert!(pipes.pipeline_step.is_none());
8152
8153        let pipes = util::log(result(lex_scope(new_span("Pipes(auth) -> {}"))))?;
8154
8155        assert_eq!(pipes.selector.name.to_string().as_str(), "Pipes");
8156        assert_eq!(pipes.block.content.len(), 0);
8157        assert_eq!(pipes.block.kind, BlockKind::Nested(NestedBlockKind::Curly));
8158        assert_eq!(pipes.selector.filters.len(), 1);
8159        assert!(pipes.pipeline_step.is_some());
8160
8161        let pipes = util::log(result(lex_scope(new_span("Route<Ext> -> {}"))))?;
8162
8163        assert_eq!(pipes.selector.name.to_string().as_str(), "Route");
8164        assert_eq!(
8165            Some(
8166                pipes
8167                    .selector
8168                    .children
8169                    .as_ref()
8170                    .unwrap()
8171                    .to_string()
8172                    .as_str()
8173            ),
8174            Some("<Ext>")
8175        );
8176
8177        assert_eq!(pipes.block.content.to_string().as_str(), "");
8178        assert_eq!(pipes.block.kind, BlockKind::Nested(NestedBlockKind::Curly));
8179        assert_eq!(pipes.selector.filters.len(), 0);
8180        assert!(pipes.pipeline_step.is_some());
8181
8182        let pipes = util::log(result(lex_scope(new_span(
8183            "Route<Http>(noauth) -> {zoink!{}}",
8184        ))))?;
8185        assert_eq!(pipes.selector.name.to_string().as_str(), "Route");
8186        assert_eq!(
8187            Some(
8188                pipes
8189                    .selector
8190                    .children
8191                    .as_ref()
8192                    .unwrap()
8193                    .to_string()
8194                    .as_str()
8195            ),
8196            Some("<Http>")
8197        );
8198        assert_eq!(pipes.block.content.to_string().as_str(), "zoink!{}");
8199        assert_eq!(pipes.block.kind, BlockKind::Nested(NestedBlockKind::Curly));
8200        assert_eq!(pipes.selector.filters.len(), 1);
8201        //        assert_eq!(Some(pipes.pipeline_step.unwrap().to_string().as_str()),Some("->") );
8202
8203        let msg = "Hello my future friend";
8204        let parseme = format!("<Http<Get>> -> {};", msg);
8205        let pipes = util::log(result(lex_scope(new_span(parseme.as_str()))))?;
8206
8207        assert_eq!(pipes.selector.name.to_string().as_str(), "Http");
8208        assert_eq!(
8209            pipes.block.content.to_string().as_str(),
8210            format!("-> {}", msg)
8211        );
8212        assert_eq!(
8213            pipes.block.kind,
8214            BlockKind::Terminated(TerminatedBlockKind::Semicolon)
8215        );
8216        assert_eq!(pipes.selector.filters.len(), 0);
8217        assert!(pipes.pipeline_step.is_none());
8218
8219        assert_eq!(
8220            lex_scope_selector(new_span("<Route<Http>>/users/",))
8221                .unwrap()
8222                .0
8223                .len(),
8224            0
8225        );
8226
8227        util::log(result(lex_scope_selector(new_span(
8228            "Route<Http<Get>>/users/",
8229        ))))
8230        .unwrap();
8231
8232        let pipes = util::log(result(lex_scope(new_span(
8233            "Route<Http<Get>>/blah -[Text ]-> {}",
8234        ))))
8235        .unwrap();
8236        assert_eq!(pipes.selector.name.to_string().as_str(), "Route");
8237        assert_eq!(
8238            Some(
8239                pipes
8240                    .selector
8241                    .children
8242                    .as_ref()
8243                    .unwrap()
8244                    .to_string()
8245                    .as_str()
8246            ),
8247            Some("<Http<Get>>")
8248        );
8249        assert_eq!(pipes.block.kind, BlockKind::Nested(NestedBlockKind::Curly));
8250        assert_eq!(pipes.selector.filters.len(), 0);
8251        assert_eq!(
8252            pipes.pipeline_step.as_ref().unwrap().to_string().as_str(),
8253            "-[Text ]->"
8254        );
8255
8256        let pipes = util::log(result(lex_scope(new_span(
8257            "Route<Http<Get>>(auth)/users/ -[Text ]-> {}",
8258        ))))?;
8259        assert_eq!(pipes.selector.name.to_string().as_str(), "Route");
8260        assert_eq!(
8261            Some(
8262                pipes
8263                    .selector
8264                    .children
8265                    .as_ref()
8266                    .unwrap()
8267                    .to_string()
8268                    .as_str()
8269            ),
8270            Some("<Http<Get>>")
8271        );
8272        assert_eq!(pipes.block.kind, BlockKind::Nested(NestedBlockKind::Curly));
8273        assert_eq!(pipes.selector.filters.len(), 1);
8274        assert_eq!(
8275            pipes.pipeline_step.as_ref().unwrap().to_string().as_str(),
8276            "-[Text ]->"
8277        );
8278
8279        let pipes = util::log(result(lex_scope(new_span(
8280            "Route<Http<Get>>(auth)-(blah xyz)/users/ -[Text ]-> {}",
8281        ))))?;
8282        assert_eq!(pipes.selector.name.to_string().as_str(), "Route");
8283        assert_eq!(
8284            Some(
8285                pipes
8286                    .selector
8287                    .children
8288                    .as_ref()
8289                    .unwrap()
8290                    .to_string()
8291                    .as_str()
8292            ),
8293            Some("<Http<Get>>")
8294        );
8295        assert_eq!(pipes.block.kind, BlockKind::Nested(NestedBlockKind::Curly));
8296        assert_eq!(pipes.selector.filters.len(), 2);
8297        assert_eq!(
8298            pipes.pipeline_step.as_ref().unwrap().to_string().as_str(),
8299            "-[Text ]->"
8300        );
8301
8302        let (next, stripped) = strip_comments(new_span(
8303            r#"Route<Http>(auth)-(blah xyz)/users/ -[Text]-> {
8304
8305            Get -> {}
8306            <Put>(superuser) -> localhost:app => &;
8307            Post/users/scott -> localhost:app^Ext<SuperScott> => &;
8308
8309        }"#,
8310        ))?;
8311        let span = span_with_extra(stripped.as_str(), Arc::new(stripped.to_string()));
8312        let pipes = util::log(result(lex_scope(span)))?;
8313
8314        let pipes = util::log(result(lex_scope(new_span("* -> {}"))))?;
8315
8316        /* let pipes = log(result(lex_scope(create_span(
8317            "* -> {}",
8318        ))))?;
8319
8320        */
8321        Ok(())
8322    }
8323
8324    pub fn test_nesting_bind() {
8325        let pipes = util::log(result(lex_scope(new_span(
8326            r#"
8327
8328
8329            Route<Http>/auth/.*(auth) -> {
8330
8331                   <Get>/auth/more ->
8332
8333            }"#,
8334        ))))
8335        .unwrap();
8336    }
8337
8338    //#[test]
8339    pub fn test_root_and_subscope_phases() -> Result<(), SpaceErr> {
8340        let config = r#"
8341Bind(version=1.2.3)-> {
8342   Route -> {
8343   }
8344
8345   Route(auth)-> {
8346   }
8347}
8348
8349        "#;
8350
8351        let root = result(root_scope(new_span(config)))?;
8352
8353        util::log(lex_scopes(root.block.content.clone()));
8354        let sub_scopes = lex_scopes(root.block.content.clone())?;
8355
8356        assert_eq!(sub_scopes.len(), 2);
8357
8358        Ok(())
8359    }
8360    #[test]
8361    pub fn test_variable_name() -> Result<(), SpaceErr> {
8362        assert_eq!(
8363            "v".to_string(),
8364            util::log(result(lowercase1(new_span("v"))))?.to_string()
8365        );
8366        assert_eq!(
8367            "var".to_string(),
8368            util::log(result(skewer_dot(new_span("var"))))?.to_string()
8369        );
8370
8371        util::log(result(variable_name(new_span("var"))))?;
8372        Ok(())
8373    }
8374
8375    //#[test]
8376    pub fn test_subst() -> Result<(), SpaceErr> {
8377        /*
8378        #[derive(Clone)]
8379        pub struct SomeParser();
8380        impl SubstParser<String> for SomeParser {
8381            fn parse_span<'a>(&self, span: I) -> Res<I, String> {
8382                recognize(terminated(
8383                    recognize(many0(pair(peek(not(eof)), recognize(anychar)))),
8384                    eof,
8385                ))(span)
8386                .map(|(next, span)| (next, span.to_string()))
8387            }
8388        }
8389
8390        let chunks = log(result(subst(SomeParser())(create_span("123[]:${var}:abc"))))?;
8391        assert_eq!(chunks.chunks.len(), 3);
8392        let mut resolver = MapResolver::new();
8393        resolver.insert("var", "hello");
8394        let resolved = log(chunks.resolve_vars(&resolver))?;
8395
8396        let chunks = log(result(subst(SomeParser())(create_span(
8397            "123[]:\\${var}:abc",
8398        ))))?;
8399        let resolved = log(chunks.resolve_vars(&resolver))?;
8400
8401        let r = log(result(subst(SomeParser())(create_span(
8402            "123[    ]:${var}:abc",
8403        ))))?;
8404        println!("{}", r.to_string());
8405        log(result(subst(SomeParser())(create_span("123[]:${vAr}:abc"))));
8406        log(result(subst(SomeParser())(create_span(
8407            "123[]:${vAr }:abc",
8408        ))));
8409
8410        Ok(())
8411
8412         */
8413        unimplemented!()
8414    }
8415}
8416
8417fn create_command<I: Span>(input: I) -> Res<I, CommandVar> {
8418    tuple((tag("create"), create))(input)
8419        .map(|(next, (_, create))| (next, CommandVar::Create(create)))
8420}
8421
8422pub fn publish_command<I: Span>(input: I) -> Res<I, CommandVar> {
8423    tuple((tag("publish"), space1, publish))(input)
8424        .map(|(next, (_, _, create))| (next, CommandVar::Create(create)))
8425}
8426
8427fn select_command<I: Span>(input: I) -> Res<I, CommandVar> {
8428    tuple((tag("select"), space1, select))(input)
8429        .map(|(next, (_, _, select))| (next, CommandVar::Select(select)))
8430}
8431
8432fn set_command<I: Span>(input: I) -> Res<I, CommandVar> {
8433    tuple((tag("set"), space1, set))(input).map(|(next, (_, _, set))| (next, CommandVar::Set(set)))
8434}
8435
8436fn get_command<I: Span>(input: I) -> Res<I, CommandVar> {
8437    tuple((tag("get"), space1, get))(input).map(|(next, (_, _, get))| (next, CommandVar::Get(get)))
8438}
8439
8440pub fn command_strategy<I: Span>(input: I) -> Res<I, Strategy> {
8441    opt(tuple((tag("?"), multispace0)))(input).map(|(next, hint)| match hint {
8442        None => (next, Strategy::Commit),
8443        Some(_) => (next, Strategy::Ensure),
8444    })
8445}
8446
8447pub fn command<I: Span>(input: I) -> Res<I, CommandVar> {
8448    context(
8449        "command",
8450        alt((
8451            create_command,
8452            publish_command,
8453            select_command,
8454            set_command,
8455            get_command,
8456            fail,
8457        )),
8458    )(input)
8459}
8460
8461pub fn command_line<I: Span>(input: I) -> Res<I, CommandVar> {
8462    tuple((
8463        multispace0,
8464        command,
8465        multispace0,
8466        opt(tag(";")),
8467        multispace0,
8468    ))(input)
8469    .map(|(next, (_, command, _, _, _))| (next, command))
8470}
8471
8472pub fn script_line<I: Span>(input: I) -> Res<I, CommandVar> {
8473    tuple((multispace0, command, multispace0, tag(";"), multispace0))(input)
8474        .map(|(next, (_, command, _, _, _))| (next, command))
8475}
8476
8477pub fn script<I: Span>(input: I) -> Res<I, Vec<CommandVar>> {
8478    many0(script_line)(input)
8479}
8480
8481pub fn consume_command_line<I: Span>(input: I) -> Res<I, CommandVar> {
8482    all_consuming(command_line)(input)
8483}
8484
8485pub fn rec_script_line<I: Span>(input: I) -> Res<I, I> {
8486    recognize(script_line)(input)
8487}
8488
8489
8490
8491pub fn layer<I: Span>(input: I) -> Res<I, Layer> {
8492    let (next, layer) = recognize(camel_case)(input.clone())?;
8493    match Layer::from_str(layer.to_string().as_str()) {
8494        Ok(layer) => Ok((next, layer)),
8495        Err(err) => Err(nom::Err::Error(ErrorTree::from_error_kind(
8496            input,
8497            ErrorKind::Alpha,
8498        ))),
8499    }
8500}
8501
8502fn topic_uuid<I: Span>(input: I) -> Res<I, Topic> {
8503    delimited(tag("Topic<Uuid>("), parse_uuid, tag(")"))(input)
8504        .map(|(next, uuid)| ((next, Topic::Uuid(uuid))))
8505}
8506
8507fn topic_cli<I: Span>(input: I) -> Res<I, Topic> {
8508    value(Topic::Cli, tag("Topic<Cli>"))(input)
8509}
8510
8511fn topic_path<I: Span>(input: I) -> Res<I, Topic> {
8512    delimited(tag("Topic<Path>("), many1(skewer_case), tag(")"))(input)
8513        .map(|(next, segments)| ((next, Topic::Path(segments))))
8514}
8515
8516fn topic_any<I: Span>(input: I) -> Res<I, Topic> {
8517    context("Topic<*>", value(Topic::Any, tag("Topic<*>")))(input)
8518}
8519
8520fn topic_not<I: Span>(input: I) -> Res<I, Topic> {
8521    context("Topic<Not>", value(Topic::Not, tag("Topic<!>")))(input)
8522}
8523
8524pub fn topic_none<I: Span>(input: I) -> Res<I, Topic> {
8525    Ok((input, Topic::None))
8526}
8527
8528pub fn topic<I: Span>(input: I) -> Res<I, Topic> {
8529    context(
8530        "topic",
8531        alt((topic_cli, topic_path, topic_uuid, topic_any, topic_not)),
8532    )(input)
8533}
8534
8535pub fn topic_or_none<I: Span>(input: I) -> Res<I, Topic> {
8536    context("topic_or_none", alt((topic, topic_none)))(input)
8537}
8538
8539pub fn plus_topic_or_none<I: Span>(input: I) -> Res<I, Topic> {
8540    context(
8541        "plus_topic_or_none",
8542        alt((preceded(tag("+"), topic), topic_none)),
8543    )(input)
8544}
8545
8546pub fn port<I: Span>(input: I) -> Res<I, Surface> {
8547    let (next, (point, layer, topic)) = context(
8548        "port",
8549        tuple((
8550            terminated(tw(point_var), tag("@")),
8551            layer,
8552            plus_topic_or_none,
8553        )),
8554    )(input.clone())?;
8555
8556    match point.w.collapse() {
8557        Ok(point) => Ok((next, Surface::new(point, layer, topic))),
8558        Err(err) => {
8559            let err = ErrorTree::from_error_kind(input.clone(), ErrorKind::Alpha);
8560            let loc = input.slice(point.trace.range);
8561            Err(nom::Err::Error(ErrorTree::add_context(
8562                loc,
8563                "resolver-not-available",
8564                err,
8565            )))
8566        }
8567    }
8568}
8569
8570pub type SurfaceSelectorVal = SurfaceSelectorDef<Hop, VarVal<Topic>, VarVal<ValuePattern<Layer>>>;
8571pub type SurfaceSelectorCtx = SurfaceSelectorDef<Hop, Topic, ValuePattern<Layer>>;
8572pub type SurfaceSelector = SurfaceSelectorDef<Hop, Topic, ValuePattern<Layer>>;
8573
8574pub struct SurfaceSelectorDef<Hop, Topic, Layer> {
8575    point: SelectorDef<Hop>,
8576    topic: Topic,
8577    layer: Layer,
8578}
8579
8580pub struct KindLex {
8581    pub base: CamelCase,
8582    pub sub: Option<CamelCase>,
8583    pub specific: Option<Specific>,
8584}
8585
8586impl TryInto<KindParts> for KindLex {
8587    type Error = SpaceErr;
8588
8589    fn try_into(self) -> Result<KindParts, Self::Error> {
8590        Ok(KindParts {
8591            base: BaseKind::try_from(self.base)?,
8592            sub: self.sub,
8593            specific: self.specific,
8594        })
8595    }
8596}
8597
8598pub fn expect<I,O,F>( mut f: F ) -> impl FnMut(I) -> Res<I,O> where F: FnMut(I) -> Res<I,O>+Copy{
8599    move |i: I| {
8600        f(i).map_err( |e| {
8601            match e {
8602                Err::Incomplete(i) => {
8603                    Err::Incomplete(i)
8604                }
8605                Err::Error(e) => {
8606                    Err::Failure(e)
8607                }
8608                Err::Failure(e) => {
8609                    Err::Failure(e)
8610                }
8611            }
8612        })
8613    }
8614}
8615
8616
8617#[cfg(test)]
8618pub mod cmd_test {
8619    use core::str::FromStr;
8620
8621    use nom::error::{VerboseError, VerboseErrorKind};
8622    use nom_supreme::final_parser::{ExtractContext, final_parser};
8623
8624    use cosmic_nom::{new_span, Res};
8625
8626    use crate::command::{Command, CommandVar};
8627    use crate::err::SpaceErr;
8628    use crate::parse::error::result;
8629    use crate::parse::{CamelCase, command, consume_point, create_command, point_selector, publish_command, script, upload_blocks};
8630    use crate::util::ToResolved;
8631    use crate::{BaseKind, KindTemplate, SetProperties};
8632    use crate::kind::Kind;
8633    use crate::point::{PointSeg, RouteSeg};
8634    use crate::selector::{PointHierarchy, PointKindSeg};
8635
8636    /*
8637    #[mem]
8638    pub async fn test2() -> Result<(),Error>{
8639        let input = "? xreate localhost<Space>";
8640        let x: Result<CommandOp,VerboseError<&str>> = final_parser(command)(input);
8641        match x {
8642            Ok(_) => {}
8643            Err(err) => {
8644                println!("err: {}", err.to_string())
8645            }
8646        }
8647
8648
8649        Ok(())
8650    }
8651
8652     */
8653
8654    //    #[test]
8655    pub fn test() -> Result<(), SpaceErr> {
8656        let input = "xreate? localhost<Space>";
8657        match command(new_span(input)) {
8658            Ok(_) => {}
8659            Err(nom::Err::Error(e)) => {
8660                eprintln!("yikes!");
8661                return Err("could not find context".into());
8662            }
8663            Err(e) => {
8664                return Err("some err".into());
8665            }
8666        }
8667        Ok(())
8668    }
8669
8670    #[test]
8671    pub fn test_kind() -> Result<(), SpaceErr> {
8672        let input = "create localhost:users<UserBase<Keycloak>>";
8673        let (_, command) = command(new_span(input))?;
8674        match command {
8675            CommandVar::Create(create) => {
8676                assert_eq!(
8677                    create.template.kind.sub,
8678                    Some(CamelCase::from_str("Keycloak").unwrap())
8679                );
8680            }
8681            _ => {
8682                panic!("expected create command")
8683            }
8684        }
8685        Ok(())
8686    }
8687
8688    #[test]
8689    pub fn test_script() -> Result<(), SpaceErr> {
8690        let input = r#" create? localhost<Space>;
8691 Xcrete localhost:repo<Base<Repo>>;
8692 create? localhost:repo:tutorial<ArtifactBundleSeries>;
8693 publish? ^[ bundle.zip ]-> localhost:repo:tutorial:1.0.0;
8694 set localhost{ +bind=localhost:repo:tutorial:1.0.0:/bind/localhost.bind } ;
8695        "#;
8696
8697        crate::parse::script(new_span(input))?;
8698        Ok(())
8699    }
8700
8701    #[test]
8702    pub fn test_publish() -> Result<(), SpaceErr> {
8703        let input = r#"publish ^[ bundle.zip ]-> localhost:repo:tutorial:1.0.0"#;
8704        publish_command(new_span(input))?;
8705        Ok(())
8706    }
8707
8708    #[test]
8709    pub fn test_upload_blocks() -> Result<(), SpaceErr> {
8710        let input = r#"publish ^[ bundle.zip ]-> localhost:repo:tutorial:1.0.0"#;
8711        let blocks = result(upload_blocks(new_span(input)))?;
8712        assert_eq!(1, blocks.len());
8713        let block = blocks.get(0).unwrap();
8714        assert_eq!("bundle.zip", block.name.as_str());
8715
8716        // this should fail bcause it has multiple ^[
8717        let input = r#"publish ^[ ^[ bundle.zip ]-> localhost:repo:tutorial:1.0.0"#;
8718        let blocks = result(upload_blocks(new_span(input)))?;
8719        assert_eq!(0, blocks.len());
8720
8721        // this should fail bcause it has no ^[
8722        let input = r#"publish localhost:repo:tutorial:1.0.0"#;
8723        let blocks = result(upload_blocks(new_span(input)))?;
8724        assert_eq!(0, blocks.len());
8725
8726        Ok(())
8727    }
8728
8729    #[test]
8730    pub fn test_create_kind() -> Result<(), SpaceErr> {
8731        let input = r#"create localhost:repo:tutorial:1.0.0<Repo>"#;
8732        let mut command = result(create_command(new_span(input)))?;
8733        let command = command.collapse()?;
8734        if let Command::Create(create) = command {
8735            let kind = KindTemplate {
8736                base: BaseKind::Repo,
8737                sub: None,
8738                specific: None,
8739            };
8740            assert_eq!(create.template.kind, kind);
8741        } else {
8742            assert!(false);
8743        }
8744
8745        Ok(())
8746    }
8747
8748    #[test]
8749    pub fn test_create_properties() -> Result<(), SpaceErr> {
8750        let input = r#"create localhost:repo:tutorial:1.0.0<Repo>{ +config=the:cool:property }"#;
8751        let mut command = result(create_command(new_span(input)))?;
8752        let command = command.collapse()?;
8753        if let Command::Create(create) = command {
8754            assert!(create.properties.get("config").is_some());
8755        } else {
8756            assert!(false);
8757        }
8758
8759        Ok(())
8760    }
8761
8762    #[test]
8763    pub fn test_selector() {
8764        let less = PointHierarchy::new(RouteSeg::Local, vec![PointKindSeg {
8765            segment: PointSeg::Base("less".to_string()),
8766            kind: Kind::Base
8767        }]
8768        );
8769
8770        let fae = PointHierarchy::new(RouteSeg::Local, vec![PointKindSeg {
8771            segment: PointSeg::Base("fae".to_string()),
8772            kind: Kind::Base
8773        },
8774        PointKindSeg {
8775            segment: PointSeg::Base("dra".to_string()),
8776            kind: Kind::User
8777        }]
8778        );
8779
8780
8781        assert!(result(point_selector(new_span("less"))).unwrap().matches(&less));
8782        assert!(result(point_selector(new_span("*"))).unwrap().matches(&less));
8783        assert!(!result(point_selector(new_span("*"))).unwrap().matches(&fae ));
8784        assert!(result(point_selector(new_span("*:dra"))).unwrap().matches(&fae ));
8785        assert!(!result(point_selector(new_span("*:dra"))).unwrap().matches(&less ));
8786        assert!(result(point_selector(new_span("fae:*"))).unwrap().matches(&fae));
8787        assert!(result(point_selector(new_span("**<User>"))).unwrap().matches(&fae));
8788        assert!(!result(point_selector(new_span("**<User>"))).unwrap().matches(&less));
8789        assert!(result(point_selector(new_span("**"))).unwrap().matches(&less));
8790        assert!(result(point_selector(new_span("**"))).unwrap().matches(&fae));
8791        assert!(!result(point_selector(new_span("**<Base>"))).unwrap().matches(&fae));
8792
8793        let less = result(point_selector(new_span("less"))).unwrap();
8794    }
8795}