GPAL - Generally Positive Automation Library v1.0
GPAL The Fluent Automation LIbrary
Loading...
Searching...
No Matches
IPAddressYamlConverter.cs
1// =============================================================================
2// GPAL - Generally Positive Automation Library
3// Copyright © 2026 Software Decisions, Inc. All rights reserved.
4//
5// This file is part of GPAL.
6// Licensed under the Business Source License 1.1
7//
8// Primary development, architecture, and vision by Michael B. Vederman,
9// CEO of Software Decisions, Inc., Texas.
10//
11// Internal development maintained privately.
12// Public releases appear on GitHub: https://github.com/SoftwareDecisionsInc/GPAL.
13//
14// See LICENSE for full terms, including Additional Use Grant.
15// =============================================================================
16
17using System;
18using System.Net;
19using YamlDotNet.Core;
20using YamlDotNet.Core.Events;
21using YamlDotNet.Serialization;
22
23public class IPAddressYamlConverter : IYamlTypeConverter
24{
25 public bool Accepts(Type type)
26 {
27 return type == typeof(IPAddress);
28 }
29
30 public object ReadYaml(IParser parser, Type type)
31 {
32 var value = parser.Consume<Scalar>().Value;
33 if (IPAddress.TryParse(value, out var ipAddress))
34 {
35 return ipAddress;
36 }
37 return null; // Handle parsing failure accordingly
38 }
39
40 public void WriteYaml(IEmitter emitter, object value, Type type)
41 {
42 if (value is IPAddress ipAddress)
43 {
44 emitter.Emit(new Scalar(ipAddress.ToString()));
45 }
46 else
47 {
48 emitter.Emit(new Scalar(null)); // Handle writing failure accordingly
49 }
50 }
51 public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer)
52 {
53 IPAddress retVal = null;
54 string value;
55
56 // read the events here. asking rootDeserializer for an IPAddress sent the node straight back
57 // into this converter and recursed until the stack was gone, which is a StackOverflowException
58 // the workflow cannot catch. WriteYaml below emits a mapping of one key, so accept that shape
59 // as well as the plain scalar the sibling overload writes
60 if (true == parser.Accept<MappingStart>(out _))
61 {
62 parser.Consume<MappingStart>();
63 parser.Consume<Scalar>(); // the "ipAddress" key
64 value = parser.Consume<Scalar>().Value;
65 parser.Consume<MappingEnd>();
66 }
67 else
68 value = parser.Consume<Scalar>().Value;
69
70 // a written null arrives as the scalar "null", and a null is data
71 if (false == string.IsNullOrWhiteSpace(value) && false == "null".Equals(value.Trim(), StringComparison.OrdinalIgnoreCase))
72 if (false == IPAddress.TryParse(value.Trim(), out retVal))
73 throw new YamlException($"Invalid IP address format: {value}");
74
75 return retVal;
76 }
77
78 public void WriteYaml(IEmitter emitter, object value, Type type, ObjectSerializer serializer)
79 {
80 if (value is IPAddress ipAddress)
81 {
82 // Emit the mapping for IP address in YAML format
83 emitter.Emit(new MappingStart()); // Start a new mapping
84
85 emitter.Emit(new Scalar("ipAddress")); // Emit the field name
86 serializer(ipAddress.ToString()); // Use the serializer to handle the value
87
88 emitter.Emit(new MappingEnd()); // End the mapping
89 }
90 else if (value == null)
91 {
92 // a null is data, not a failure. throwing here killed the whole conversion on a null entry in a
93 // collection of IPAddress, and the sibling overload above already writes null for this case
94 emitter.Emit(new Scalar("null"));
95 }
96 else
97 {
98 throw new ArgumentException("Expected an IPAddress object.", nameof(value));
99 }
100 }
101}
102