Converters.cs 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. using System.Globalization;
  2. using System.Text.RegularExpressions;
  3. using YamlDotNet.Core;
  4. using YamlDotNet.Core.Events;
  5. using YamlDotNet.Serialization;
  6. namespace RackPeek.Domain.Persistence.Yaml;
  7. public static class StorageSizeParser {
  8. private static readonly Regex _sizeRegex = new(@"^\s*(\d+(?:\.\d+)?)\s*(gb|tb)?\s*$",
  9. RegexOptions.IgnoreCase | RegexOptions.Compiled);
  10. public static double ParseToGbDouble(string input) {
  11. Match match = _sizeRegex.Match(input);
  12. if (!match.Success) throw new FormatException($"Invalid storage size: '{input}'");
  13. var value = double.Parse(match.Groups[1].Value, CultureInfo.InvariantCulture);
  14. var unit = match.Groups[2].Value.ToLowerInvariant();
  15. return unit switch {
  16. "tb" => value * 1024,
  17. "gb" or "" => value,
  18. _ => throw new FormatException($"Unknown unit in '{input}'")
  19. };
  20. }
  21. }
  22. public class StorageSizeYamlConverter : IYamlTypeConverter {
  23. public bool Accepts(Type type) {
  24. return type == typeof(int) ||
  25. type == typeof(int?) ||
  26. type == typeof(double) ||
  27. type == typeof(double?);
  28. }
  29. public object? ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer) {
  30. Scalar scalar = parser.Consume<Scalar>();
  31. var value = scalar.Value;
  32. if (string.IsNullOrWhiteSpace(value))
  33. return null;
  34. // If it's already a number, parse directly
  35. if (double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var numericDouble)) {
  36. if (type == typeof(double) || type == typeof(double?))
  37. return numericDouble;
  38. if (type == typeof(int) || type == typeof(int?))
  39. return (int)numericDouble;
  40. }
  41. // Otherwise parse with size parser
  42. var gb = StorageSizeParser.ParseToGbDouble(value);
  43. if (type == typeof(double) || type == typeof(double?))
  44. return gb;
  45. return (int)Math.Round(gb);
  46. }
  47. public void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer) =>
  48. emitter.Emit(new Scalar(value?.ToString() ?? string.Empty));
  49. }