Example #1
0
 internal static FullDataSet <ItemDescriptor> ParseFullDataset(ref JReader r)
 {
     try
     {
         var dataBuilder = ImmutableList.CreateBuilder <KeyValuePair <DataKind, KeyedItems <ItemDescriptor> > >();
         for (var topLevelObj = r.Object(); topLevelObj.Next(ref r);)
         {
             var name = topLevelObj.Name.ToString();
             var kind = DataModel.AllDataKinds.FirstOrDefault(k => name == PathNameForKind(k));
             if (kind == null)
             {
                 continue;
             }
             var itemsBuilder = ImmutableList.CreateBuilder <KeyValuePair <string, ItemDescriptor> >();
             for (var itemsObj = r.Object(); itemsObj.Next(ref r);)
             {
                 var key  = itemsObj.Name.ToString();
                 var item = kind.DeserializeFromJReader(ref r);
                 itemsBuilder.Add(new KeyValuePair <string, ItemDescriptor>(key, item));
             }
             dataBuilder.Add(new KeyValuePair <DataKind, KeyedItems <ItemDescriptor> >(kind,
                                                                                       new KeyedItems <ItemDescriptor>(itemsBuilder.ToImmutable())));
         }
         return(new FullDataSet <ItemDescriptor>(dataBuilder.ToImmutable()));
     }
     catch (Exception e)
     {
         throw r.TranslateException(e);
     }
 }
        public object ReadJson(ref JReader reader)
        {
            var valid = true;
            var flags = new Dictionary <string, FlagState>();

            for (var topLevelObj = reader.Object(); topLevelObj.Next(ref reader);)
            {
                var key = topLevelObj.Name.ToString();
                switch (key)
                {
                case "$valid":
                    valid = reader.Bool();
                    break;

                case "$flagsState":
                    for (var flagsObj = reader.Object(); flagsObj.Next(ref reader);)
                    {
                        var subKey = flagsObj.Name.ToString();
                        var flag   = flags.ContainsKey(subKey) ? flags[subKey] : new FlagState();
                        for (var metaObj = reader.Object(); metaObj.Next(ref reader);)
                        {
                            switch (metaObj.Name.ToString())
                            {
                            case "variation":
                                flag.Variation = reader.IntOrNull();
                                break;

                            case "version":
                                flag.Version = reader.IntOrNull();
                                break;

                            case "trackEvents":
                                flag.TrackEvents = reader.Bool();
                                break;

                            case "debugEventsUntilDate":
                                var n = reader.LongOrNull();
                                flag.DebugEventsUntilDate = n.HasValue ? UnixMillisecondTime.OfMillis(n.Value) :
                                                            (UnixMillisecondTime?)null;
                                break;

                            case "reason":
                                flag.Reason = EvaluationReasonConverter.ReadJsonNullableValue(ref reader);
                                break;
                            }
                        }
                        flags[subKey] = flag;
                    }
                    break;

                default:
                    var flagForValue = flags.ContainsKey(key) ? flags[key] : new FlagState();
                    flagForValue.Value = LdValueConverter.ReadJsonValue(ref reader);
                    flags[key]         = flagForValue;
                    break;
                }
            }
            return(new FeatureFlagsState(valid, flags));
        }
Example #3
0
        internal static SegmentRule ReadSegmentRule(ref JReader reader)
        {
            ImmutableList <Clause> clauses = null;
            int?          weight           = null;
            UserAttribute?bucketBy         = null;

            for (var obj = reader.Object(); obj.Next(ref reader);)
            {
                switch (obj.Name)
                {
                case var n when n == "clauses":
                    clauses = SerializationHelpers.ReadClauses(ref reader);
                    break;

                case var n when n == "weight":
                    weight = reader.IntOrNull();
                    break;

                case var n when n == "bucketBy":
                    var s = reader.StringOrNull();
                    bucketBy = s is null ? (UserAttribute?)null : UserAttribute.ForName(s);
                    break;
                }
            }
            return(new SegmentRule(clauses, weight, bucketBy));
        }
Example #4
0
        internal static FlagRule ReadFlagRule(ref JReader r)
        {
            string  id        = null;
            int?    variation = null;
            Rollout?rollout   = null;
            ImmutableList <Clause> clauses = null;
            bool trackEvents = false;

            for (var obj = r.Object(); obj.Next(ref r);)
            {
                switch (obj.Name)
                {
                case var n when n == "id":
                    id = r.StringOrNull();
                    break;

                case var n when n == "variation":
                    variation = r.IntOrNull();
                    break;

                case var n when n == "rollout":
                    rollout = ReadRollout(ref r);
                    break;

                case var n when n == "clauses":
                    clauses = SerializationHelpers.ReadClauses(ref r);
                    break;

                case var n when n == "trackEvents":
                    trackEvents = r.Bool();
                    break;
                }
            }
            return(new FlagRule(variation, rollout, id, clauses, trackEvents));
        }
        public object ReadJson(ref JReader reader)
        {
            string key = null;
            int    version = 0;
            bool   deleted = false;
            ImmutableList <string>      included = null, excluded = null;
            ImmutableList <SegmentRule> rules = null;
            string salt = null;

            for (var obj = reader.Object().WithRequiredProperties(_requiredProperties); obj.Next(ref reader);)
            {
                switch (obj.Name)
                {
                case var n when n == "key":
                    key = reader.String();
                    break;

                case var n when n == "version":
                    version = reader.Int();
                    break;

                case var n when n == "deleted":
                    deleted = reader.Bool();
                    break;

                case var n when n == "included":
                    included = SerializationHelpers.ReadStrings(ref reader);
                    break;

                case var n when n == "excluded":
                    excluded = SerializationHelpers.ReadStrings(ref reader);
                    break;

                case var n when n == "rules":
                    var rulesBuilder = ImmutableList.CreateBuilder <SegmentRule>();
                    for (var rulesArr = reader.Array(); rulesArr.Next(ref reader);)
                    {
                        rulesBuilder.Add(ReadSegmentRule(ref reader));
                    }
                    rules = rulesBuilder.ToImmutable();
                    break;

                case var n when n == "salt":
                    salt = reader.StringOrNull();
                    break;
                }
            }
            if (key is null && !deleted)
            {
                throw new RequiredPropertyException("key", 0);
            }
            return(new Segment(key, version, deleted, included, excluded, rules, salt));
        }
        private static FullDataSet <ItemDescriptor> ParseJson(ref JReader r, int version)
        {
            var flagsBuilder    = ImmutableList.CreateBuilder <KeyValuePair <string, ItemDescriptor> >();
            var segmentsBuilder = ImmutableList.CreateBuilder <KeyValuePair <string, ItemDescriptor> >();

            for (var obj = r.Object(); obj.Next(ref r);)
            {
                switch (obj.Name.ToString())
                {
                case "flags":
                    for (var subObj = r.ObjectOrNull(); subObj.Next(ref r);)
                    {
                        var key  = subObj.Name.ToString();
                        var flag = FeatureFlagSerialization.Instance.ReadJson(ref r) as FeatureFlag;
                        flagsBuilder.Add(new KeyValuePair <string, ItemDescriptor>(key, new ItemDescriptor(version,
                                                                                                           FlagWithVersion(flag, version))));
                    }
                    break;

                case "flagValues":
                    for (var subObj = r.ObjectOrNull(); subObj.Next(ref r);)
                    {
                        var key   = subObj.Name.ToString();
                        var value = LdValueConverter.ReadJsonValue(ref r);
                        var flag  = FlagWithValue(key, value, version);
                        flagsBuilder.Add(new KeyValuePair <string, ItemDescriptor>(key, new ItemDescriptor(version, flag)));
                    }
                    break;

                case "segments":
                    for (var subObj = r.ObjectOrNull(); subObj.Next(ref r);)
                    {
                        var key     = subObj.Name.ToString();
                        var segment = SegmentSerialization.Instance.ReadJson(ref r) as Segment;
                        segmentsBuilder.Add(new KeyValuePair <string, ItemDescriptor>(key, new ItemDescriptor(version,
                                                                                                              SegmentWithVersion(segment, version))));
                    }
                    break;
                }
            }
            return(new FullDataSet <ItemDescriptor>(ImmutableList.Create <KeyValuePair <DataKind, KeyedItems <ItemDescriptor> > >(
                                                        new KeyValuePair <DataKind, KeyedItems <ItemDescriptor> >(DataModel.Features,
                                                                                                                  new KeyedItems <ItemDescriptor>(flagsBuilder.ToImmutable())),
                                                        new KeyValuePair <DataKind, KeyedItems <ItemDescriptor> >(DataModel.Segments,
                                                                                                                  new KeyedItems <ItemDescriptor>(segmentsBuilder.ToImmutable()))
                                                        )));
        }
        internal static Rollout?ReadRollout(ref JReader r)
        {
            ImmutableList <WeightedVariation> variations = null;
            UserAttribute?bucketBy = null;
            var           obj      = r.ObjectOrNull();

            if (!obj.IsDefined)
            {
                return(null);
            }
            while (obj.Next(ref r))
            {
                switch (obj.Name)
                {
                case var n when n == "variations":
                    var listBuilder = ImmutableList.CreateBuilder <WeightedVariation>();
                    for (var arr = r.ArrayOrNull(); arr.Next(ref r);)
                    {
                        int variation = 0, weight = 0;
                        for (var wvObj = r.Object(); wvObj.Next(ref r);)
                        {
                            switch (wvObj.Name)
                            {
                            case var nn when nn == "variation":
                                variation = r.Int();
                                break;

                            case var nn when nn == "weight":
                                weight = r.Int();
                                break;
                            }
                        }
                        listBuilder.Add(new WeightedVariation(variation, weight));
                    }
                    variations = listBuilder.ToImmutable();
                    break;

                case var n when n == "bucketBy":
                    var s = r.StringOrNull();
                    bucketBy = s is null ? (UserAttribute?)null : UserAttribute.ForName(s);
                    break;
                }
            }
            return(new Rollout(variations, bucketBy));
        }
Example #8
0
        internal static Target ReadTarget(ref JReader r)
        {
            ImmutableList <string> values = null;
            int variation = 0;

            for (var obj = r.Object(); obj.Next(ref r);)
            {
                switch (obj.Name)
                {
                case var n when n == "values":
                    values = SerializationHelpers.ReadStrings(ref r);
                    break;

                case var n when n == "variation":
                    variation = r.Int();
                    break;
                }
            }
            return(new Target(values, variation));
        }
Example #9
0
        internal static Prerequisite ReadPrerequisite(ref JReader r)
        {
            string key       = null;
            int    variation = 0;

            for (var obj = r.Object(); obj.Next(ref r);)
            {
                switch (obj.Name)
                {
                case var n when n == "key":
                    key = r.String();
                    break;

                case var n when n == "variation":
                    variation = r.Int();
                    break;
                }
            }
            return(new Prerequisite(key, variation));
        }
        private static FlagFileData ParseJson(ref JReader r)
        {
            var ret = new FlagFileData
            {
                Flags      = new Dictionary <string, FeatureFlag>(),
                FlagValues = new Dictionary <string, LdValue>(),
                Segments   = new Dictionary <string, Segment>()
            };

            for (var obj = r.Object(); obj.Next(ref r);)
            {
                switch (obj.Name.ToString())
                {
                case "flags":
                    for (var subObj = r.ObjectOrNull(); subObj.Next(ref r);)
                    {
                        ret.Flags[subObj.Name.ToString()] = FeatureFlagSerialization.Instance.ReadJson(ref r) as FeatureFlag;
                    }
                    break;

                case "flagValues":
                    for (var subObj = r.ObjectOrNull(); subObj.Next(ref r);)
                    {
                        ret.FlagValues[subObj.Name.ToString()] = LdValueConverter.ReadJsonValue(ref r);
                    }
                    break;

                case "segments":
                    for (var subObj = r.ObjectOrNull(); subObj.Next(ref r);)
                    {
                        ret.Segments[subObj.Name.ToString()] = SegmentSerialization.Instance.ReadJson(ref r) as Segment;
                    }
                    break;
                }
            }
            return(ret);
        }
Example #11
0
        internal static ImmutableList <Clause> ReadClauses(ref JReader r)
        {
            var builder = ImmutableList.CreateBuilder <Clause>();

            for (var arr = r.ArrayOrNull(); arr.Next(ref r);)
            {
                UserAttribute           attribute = new UserAttribute();
                Operator                op        = null;
                ImmutableList <LdValue> values    = null;
                bool negate = false;
                for (var obj = r.Object(); obj.Next(ref r);)
                {
                    switch (obj.Name)
                    {
                    case var n when n == "attribute":
                        attribute = UserAttribute.ForName(r.String());
                        break;

                    case var n when n == "op":
                        op = Operator.ForName(r.String());
                        // Operator.ForName never returns null - unrecognized operators return a stub object
                        break;

                    case var n when n == "values":
                        values = ReadValues(ref r);
                        break;

                    case var n when n == "negate":
                        negate = r.Bool();
                        break;
                    }
                }
                builder.Add(new Clause(attribute, op, values, negate));
            }
            return(builder.ToImmutable());
        }
Example #12
0
        internal static Rollout?ReadRollout(ref JReader r)
        {
            ImmutableList <WeightedVariation> variations = null;
            UserAttribute?bucketBy = null;
            RolloutKind   kind     = RolloutKind.Rollout;
            int?          seed     = null;
            var           obj      = r.ObjectOrNull();

            if (!obj.IsDefined)
            {
                return(null);
            }
            while (obj.Next(ref r))
            {
                switch (obj.Name)
                {
                case var n when n == "variations":
                    var listBuilder = ImmutableList.CreateBuilder <WeightedVariation>();
                    for (var arr = r.ArrayOrNull(); arr.Next(ref r);)
                    {
                        int  variation = 0, weight = 0;
                        bool untracked = false;
                        for (var wvObj = r.Object(); wvObj.Next(ref r);)
                        {
                            switch (wvObj.Name)
                            {
                            case var nn when nn == "variation":
                                variation = r.Int();
                                break;

                            case var nn when nn == "weight":
                                weight = r.Int();
                                break;

                            case var nn when nn == "untracked":
                                untracked = r.Bool();
                                break;
                            }
                        }
                        listBuilder.Add(new WeightedVariation(variation, weight, untracked));
                    }
                    variations = listBuilder.ToImmutable();
                    break;

                case var n when n == "bucketBy":
                    var s = r.StringOrNull();
                    bucketBy = s is null ? (UserAttribute?)null : UserAttribute.ForName(s);
                    break;

                case var n when n == "kind":
                    var kindStr = r.StringOrNull();
                    kind = "experiment".Equals(kindStr) ? RolloutKind.Experiment : RolloutKind.Rollout;
                    break;

                case var n when n == "seed":
                    seed = r.IntOrNull();
                    break;
                }
            }
            return(new Rollout(kind, seed, variations, bucketBy));
        }
Example #13
0
        public object ReadJson(ref JReader reader)
        {
            string key     = null;
            int    version = 0;
            bool   deleted = false;
            bool   on      = false;
            ImmutableList <Prerequisite> prerequisites = null;
            ImmutableList <Target>       targets       = null;
            ImmutableList <FlagRule>     rules         = null;
            string             salt        = null;
            VariationOrRollout fallthrough = new VariationOrRollout();
            int?offVariation = null;
            ImmutableList <LdValue> variations = null;
            bool trackEvents = false, trackEventsFallthrough = false;
            UnixMillisecondTime?debugEventsUntilDate = null;
            bool clientSide = false;

            for (var obj = reader.Object().WithRequiredProperties(_requiredProperties); obj.Next(ref reader);)
            {
                switch (obj.Name)
                {
                case var n when n == "key":
                    key = reader.String();
                    break;

                case var n when n == "version":
                    version = reader.Int();
                    break;

                case var n when n == "deleted":
                    deleted = reader.Bool();
                    break;

                case var n when n == "on":
                    on = reader.Bool();
                    break;

                case var n when n == "prerequisites":
                    var prereqsBuilder = ImmutableList.CreateBuilder <Prerequisite>();
                    for (var arr = reader.ArrayOrNull(); arr.Next(ref reader);)
                    {
                        prereqsBuilder.Add(ReadPrerequisite(ref reader));
                    }
                    prerequisites = prereqsBuilder.ToImmutable();
                    break;

                case var n when n == "targets":
                    var targetsBuilder = ImmutableList.CreateBuilder <Target>();
                    for (var arr = reader.ArrayOrNull(); arr.Next(ref reader);)
                    {
                        targetsBuilder.Add(ReadTarget(ref reader));
                    }
                    targets = targetsBuilder.ToImmutable();
                    break;

                case var n when n == "rules":
                    var rulesBuilder = ImmutableList.CreateBuilder <FlagRule>();
                    for (var arr = reader.ArrayOrNull(); arr.Next(ref reader);)
                    {
                        rulesBuilder.Add(ReadFlagRule(ref reader));
                    }
                    rules = rulesBuilder.ToImmutable();
                    break;

                case var n when n == "fallthrough":
                    fallthrough = ReadVariationOrRollout(ref reader);
                    break;

                case var n when n == "offVariation":
                    offVariation = reader.IntOrNull();
                    break;

                case var n when n == "variations":
                    variations = SerializationHelpers.ReadValues(ref reader);
                    break;

                case var n when n == "salt":
                    salt = reader.StringOrNull();
                    break;

                case var n when n == "trackEvents":
                    trackEvents = reader.Bool();
                    break;

                case var n when n == "trackEventsFallthrough":
                    trackEventsFallthrough = reader.Bool();
                    break;

                case var n when n == "debugEventsUntilDate":
                    var dt = reader.LongOrNull();
                    debugEventsUntilDate = dt.HasValue ? UnixMillisecondTime.OfMillis(dt.Value) : (UnixMillisecondTime?)null;
                    break;

                case var n when n == "clientSide":
                    clientSide = reader.Bool();
                    break;
                }
            }
            if (key is null && !deleted)
            {
                throw new RequiredPropertyException("key", 0);
            }
            return(new FeatureFlag(key, version, deleted, on, prerequisites, targets, rules, fallthrough,
                                   offVariation, variations, salt, trackEvents, trackEventsFallthrough, debugEventsUntilDate, clientSide));
        }
            public static FeatureFlag ReadJsonValue(ref JReader reader)
            {
                LdValue             value                = LdValue.Null;
                int                 version              = 0;
                int?                flagVersion          = null;
                int?                variation            = null;
                EvaluationReason?   reason               = null;
                bool                trackEvents          = false;
                bool                trackReason          = false;
                UnixMillisecondTime?debugEventsUntilDate = null;

                for (var or = reader.Object(); or.Next(ref reader);)
                {
                    // The use of multiple == tests instead of switch allows for a slight optimization on
                    // some platforms where it wouldn't always need to allocate a string for or.Name. See:
                    // https://github.com/launchdarkly/dotnet-jsonstream/blob/master/src/LaunchDarkly.JsonStream/PropertyNameToken.cs
                    var name = or.Name;
                    if (name == "value")
                    {
                        value = LdJsonConverters.LdValueConverter.ReadJsonValue(ref reader);
                    }
                    else if (name == "version")
                    {
                        version = reader.Int();
                    }
                    else if (name == "flagVersion")
                    {
                        flagVersion = reader.IntOrNull();
                    }
                    else if (name == "variation")
                    {
                        variation = reader.IntOrNull();
                    }
                    else if (name == "reason")
                    {
                        reason = LdJsonConverters.EvaluationReasonConverter.ReadJsonNullableValue(ref reader);
                    }
                    else if (name == "trackEvents")
                    {
                        trackEvents = reader.Bool();
                    }
                    else if (name == "trackReason")
                    {
                        trackReason = reader.Bool();
                    }
                    else if (name == "debugEventsUntilDate")
                    {
                        var dt = reader.LongOrNull();
                        if (dt.HasValue)
                        {
                            debugEventsUntilDate = UnixMillisecondTime.OfMillis(dt.Value);
                        }
                    }
                }

                return(new FeatureFlag(
                           value,
                           variation,
                           reason,
                           version,
                           flagVersion,
                           trackEvents,
                           trackReason,
                           debugEventsUntilDate
                           ));
            }
Example #15
0
            private static EvaluationReason?ReadJsonInternal(ref JReader reader, bool nullable)
            {
                var obj = (nullable ? reader.ObjectOrNull() : reader.Object())
                          .WithRequiredProperties(_requiredProperties);

                if (!obj.IsDefined)
                {
                    return(null);
                }
                try
                {
                    EvaluationReasonKind kind           = EvaluationReasonKind.Error;
                    int?   ruleIndex                    = null;
                    string ruleId                       = null;
                    string prerequisiteKey              = null;
                    EvaluationErrorKind?errorKind       = null;
                    bool inExperiment                   = false;
                    BigSegmentsStatus?bigSegmentsStatus = null;

                    while (obj.Next(ref reader))
                    {
                        var name = obj.Name;
                        if (name == "kind")
                        {
                            try
                            {
                                kind = EvaluationReasonKindConverter.FromIdentifier(reader.String());
                            }
                            catch (ArgumentException)
                            {
                                throw new SyntaxException("unsupported value for \"kind\"", 0);
                            }
                        }
                        else if (name == "ruleIndex")
                        {
                            ruleIndex = reader.Int();
                        }
                        else if (name == "ruleId")
                        {
                            ruleId = reader.String();
                        }
                        else if (name == "prerequisiteKey")
                        {
                            prerequisiteKey = reader.String();
                        }
                        else if (name == "errorKind")
                        {
                            try
                            {
                                errorKind = EvaluationErrorKindConverter.FromIdentifier(reader.String());
                            }
                            catch (ArgumentException)
                            {
                                throw new SyntaxException("unsupported value for \"errorKind\"", 0);
                            }
                        }
                        else if (name == "inExperiment")
                        {
                            inExperiment = reader.Bool();
                        }
                        else if (name == "bigSegmentsStatus")
                        {
                            try
                            {
                                bigSegmentsStatus = BigSegmentsStatusConverter.FromIdentifier(reader.String());
                            }
                            catch (ArgumentException)
                            {
                                throw new SyntaxException("unsupported value for \"bigSegmentsStatus\"", 0);
                            }
                        }
                    }

                    EvaluationReason reason;
                    switch (kind) // it's guaranteed to have a value, otherwise there'd be a required property error above
                    {
                    case EvaluationReasonKind.Off:
                        reason = EvaluationReason.OffReason;
                        break;

                    case EvaluationReasonKind.Fallthrough:
                        reason = EvaluationReason.FallthroughReason;
                        break;

                    case EvaluationReasonKind.TargetMatch:
                        reason = EvaluationReason.TargetMatchReason;
                        break;

                    case EvaluationReasonKind.RuleMatch:
                        reason = EvaluationReason.RuleMatchReason(ruleIndex ?? 0, ruleId);
                        break;

                    case EvaluationReasonKind.PrerequisiteFailed:
                        reason = EvaluationReason.PrerequisiteFailedReason(prerequisiteKey);
                        break;

                    case EvaluationReasonKind.Error:
                        reason = EvaluationReason.ErrorReason(errorKind ?? EvaluationErrorKind.Exception);
                        break;

                    default:
                        return(null);
                    }
                    if (inExperiment)
                    {
                        reason = reason.WithInExperiment(true);
                    }
                    if (bigSegmentsStatus.HasValue)
                    {
                        reason = reason.WithBigSegmentsStatus(bigSegmentsStatus);
                    }
                    return(reason);
                }
                catch (Exception e)
                {
                    throw reader.TranslateException(e);
                }
            }