Private/SampleJson.ps1

#Requires -Version 5.1

function Initialize-SMBeatSampleJsonNative {
    if ($script:SMBeatSampleJsonReady) {
        return $true
    }
    if ($script:SMBeatSampleJsonFailed) {
        return $false
    }
    if ('SMBeat.Native.SampleJson' -as [type]) {
        $script:SMBeatSampleJsonReady = $true
        return $true
    }

    $code = @'
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
 
namespace SMBeat.Native
{
    public sealed class SampleRecord
    {
        public string ts { get; set; }
        public DateTime TsUtc { get; set; }
        public string server { get; set; }
        public string kind { get; set; }
        public string name { get; set; }
        public string client { get; set; }
        public string user { get; set; }
        public long readBytesDelta { get; set; }
        public long writeBytesDelta { get; set; }
        public long sentBytesDelta { get; set; }
        public long receivedBytesDelta { get; set; }
        public int sampleIntervalSec { get; set; }
    }
 
    public sealed class SampleWindowPair
    {
        public List<SampleRecord> Previous = new List<SampleRecord>();
        public List<SampleRecord> Current = new List<SampleRecord>();
    }
 
    public static class SampleJson
    {
        public static SampleRecord ParseLine(string line)
        {
            if (string.IsNullOrWhiteSpace(line))
            {
                return null;
            }
 
            int i = 0;
            SkipWs(line, ref i);
            if (i >= line.Length || line[i] != '{')
            {
                return null;
            }
            i++;
 
            SampleRecord rec = new SampleRecord();
            StringBuilder sb = new StringBuilder(64);
            bool any = false;
            while (i < line.Length)
            {
                SkipWs(line, ref i);
                if (i >= line.Length)
                {
                    return null;
                }
                if (line[i] == '}')
                {
                    break;
                }
                if (line[i] == ',')
                {
                    i++;
                    continue;
                }
                if (line[i] != '"')
                {
                    return null;
                }
 
                string key;
                if (!TryReadString(line, ref i, sb, out key))
                {
                    return null;
                }
                SkipWs(line, ref i);
                if (i >= line.Length || line[i] != ':')
                {
                    return null;
                }
                i++;
                SkipWs(line, ref i);
                if (i >= line.Length)
                {
                    return null;
                }
 
                if (line[i] == '"')
                {
                    string text;
                    if (!TryReadString(line, ref i, sb, out text))
                    {
                        return null;
                    }
                    AssignString(rec, key, text);
                    any = true;
                }
                else if (line[i] == 'n' || line[i] == 'N')
                {
                    if (!TrySkipLiteral(line, ref i, "null"))
                    {
                        return null;
                    }
                    AssignString(rec, key, null);
                    any = true;
                }
                else if (line[i] == 't' || line[i] == 'T' || line[i] == 'f' || line[i] == 'F')
                {
                    if (!TrySkipBool(line, ref i))
                    {
                        return null;
                    }
                }
                else
                {
                    long n;
                    if (!TryReadInt64(line, ref i, out n))
                    {
                        return null;
                    }
                    AssignNumber(rec, key, n);
                    any = true;
                }
            }
 
            if (!any || string.IsNullOrEmpty(rec.ts))
            {
                return null;
            }
 
            DateTime ts;
            if (!TryParseTs(rec.ts, out ts))
            {
                return null;
            }
            rec.TsUtc = ts;
            return rec;
        }
 
        public static List<SampleRecord> ReadFile(string path, DateTime startUtc, DateTime endUtc)
        {
            List<SampleRecord> list = new List<SampleRecord>();
            if (string.IsNullOrEmpty(path) || !File.Exists(path))
            {
                return list;
            }
 
            foreach (string line in File.ReadLines(path, Encoding.UTF8))
            {
                SampleRecord rec = ParseLine(line);
                if (rec == null)
                {
                    continue;
                }
                if (rec.TsUtc >= startUtc && rec.TsUtc < endUtc)
                {
                    list.Add(rec);
                }
            }
            return list;
        }
 
        public static SampleWindowPair ReadDirectory(
            string dir,
            DateTime prevStart,
            DateTime prevEnd,
            DateTime windowStart,
            DateTime windowEnd)
        {
            SampleWindowPair pair = new SampleWindowPair();
            if (string.IsNullOrEmpty(dir) || !Directory.Exists(dir))
            {
                return pair;
            }
 
            DateTime spanStart = prevStart < windowStart ? prevStart : windowStart;
            DateTime spanEnd = prevEnd > windowEnd ? prevEnd : windowEnd;
            DateTime startDay = spanStart.Date.AddDays(-1);
            DateTime endDay = spanEnd.Date.AddDays(1);
 
            string[] files = Directory.GetFiles(dir, "*.jsonl");
            Array.Sort(files, StringComparer.OrdinalIgnoreCase);
            foreach (string path in files)
            {
                string dayPart = Path.GetFileNameWithoutExtension(path);
                DateTime fileDay;
                if (!DateTime.TryParseExact(dayPart, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out fileDay))
                {
                    continue;
                }
                if (fileDay < startDay || fileDay > endDay)
                {
                    continue;
                }
 
                foreach (string line in File.ReadLines(path, Encoding.UTF8))
                {
                    SampleRecord rec = ParseLine(line);
                    if (rec == null)
                    {
                        continue;
                    }
                    if (rec.TsUtc >= prevStart && rec.TsUtc < prevEnd)
                    {
                        pair.Previous.Add(rec);
                    }
                    if (rec.TsUtc >= windowStart && rec.TsUtc < windowEnd)
                    {
                        pair.Current.Add(rec);
                    }
                }
            }
            return pair;
        }
 
        private static void AssignString(SampleRecord rec, string key, string value)
        {
            if (key == "ts") { rec.ts = value; }
            else if (key == "server") { rec.server = value; }
            else if (key == "kind") { rec.kind = value; }
            else if (key == "name") { rec.name = value; }
            else if (key == "client") { rec.client = value; }
            else if (key == "user") { rec.user = value; }
        }
 
        private static void AssignNumber(SampleRecord rec, string key, long value)
        {
            if (key == "readBytesDelta") { rec.readBytesDelta = value; }
            else if (key == "writeBytesDelta") { rec.writeBytesDelta = value; }
            else if (key == "sentBytesDelta") { rec.sentBytesDelta = value; }
            else if (key == "receivedBytesDelta") { rec.receivedBytesDelta = value; }
            else if (key == "sampleIntervalSec") { rec.sampleIntervalSec = (int)value; }
        }
 
        private static bool TryParseTs(string value, out DateTime ts)
        {
            if (DateTime.TryParseExact(value, "yyyy-MM-ddTHH:mm:ssZ", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal, out ts))
            {
                return true;
            }
            return DateTime.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal, out ts);
        }
 
        private static void SkipWs(string s, ref int i)
        {
            while (i < s.Length && char.IsWhiteSpace(s[i]))
            {
                i++;
            }
        }
 
        private static bool TrySkipLiteral(string s, ref int i, string lit)
        {
            if (i + lit.Length > s.Length)
            {
                return false;
            }
            for (int k = 0; k < lit.Length; k++)
            {
                if (char.ToLowerInvariant(s[i + k]) != lit[k])
                {
                    return false;
                }
            }
            i += lit.Length;
            return true;
        }
 
        private static bool TrySkipBool(string s, ref int i)
        {
            if (s[i] == 't' || s[i] == 'T')
            {
                return TrySkipLiteral(s, ref i, "true");
            }
            return TrySkipLiteral(s, ref i, "false");
        }
 
        private static bool TryReadInt64(string s, ref int i, out long value)
        {
            value = 0;
            int start = i;
            if (i < s.Length && (s[i] == '-' || s[i] == '+'))
            {
                i++;
            }
            bool digit = false;
            while (i < s.Length && s[i] >= '0' && s[i] <= '9')
            {
                digit = true;
                i++;
            }
            if (i < s.Length && s[i] == '.')
            {
                i++;
                while (i < s.Length && s[i] >= '0' && s[i] <= '9')
                {
                    i++;
                }
            }
            if (!digit)
            {
                return false;
            }
            string raw = s.Substring(start, i - start);
            double d;
            if (!double.TryParse(raw, NumberStyles.Float, CultureInfo.InvariantCulture, out d))
            {
                return false;
            }
            if (d >= long.MaxValue)
            {
                value = long.MaxValue;
            }
            else if (d <= long.MinValue)
            {
                value = long.MinValue;
            }
            else
            {
                value = (long)d;
            }
            return true;
        }
 
        private static bool TryReadString(string s, ref int i, StringBuilder sb, out string value)
        {
            value = null;
            if (i >= s.Length || s[i] != '"')
            {
                return false;
            }
            i++;
            sb.Length = 0;
            while (i < s.Length)
            {
                char c = s[i];
                if (c == '"')
                {
                    i++;
                    value = sb.ToString();
                    return true;
                }
                if (c == '\\')
                {
                    i++;
                    if (i >= s.Length)
                    {
                        return false;
                    }
                    char e = s[i];
                    if (e == '"' || e == '\\' || e == '/')
                    {
                        sb.Append(e);
                    }
                    else if (e == 'b') { sb.Append('\b'); }
                    else if (e == 'f') { sb.Append('\f'); }
                    else if (e == 'n') { sb.Append('\n'); }
                    else if (e == 'r') { sb.Append('\r'); }
                    else if (e == 't') { sb.Append('\t'); }
                    else if (e == 'u' && i + 4 < s.Length)
                    {
                        int hex;
                        if (!int.TryParse(s.Substring(i + 1, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out hex))
                        {
                            return false;
                        }
                        sb.Append((char)hex);
                        i += 4;
                    }
                    else
                    {
                        sb.Append(e);
                    }
                    i++;
                    continue;
                }
                sb.Append(c);
                i++;
            }
            return false;
        }
    }
}
'@


    try {
        Add-Type -TypeDefinition $code -Language CSharp -ErrorAction Stop
        $script:SMBeatSampleJsonReady = $true
        return $true
    }
    catch {
        $script:SMBeatSampleJsonFailed = $true
        return $false
    }
}