Converters.cs 2.2 KB

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